forked from OSchip/llvm-project
[NFC] Minor refactoring to setup the stage for supporting pointers in ExprMutationAnalyzer
llvm-svn: 342353
This commit is contained in:
parent
cffa206423
commit
aaaa310de2
|
@ -31,13 +31,32 @@ public:
|
|||
const Stmt *findMutation(const Expr *Exp);
|
||||
const Stmt *findMutation(const Decl *Dec);
|
||||
|
||||
bool isPointeeMutated(const Expr *Exp) {
|
||||
return findPointeeMutation(Exp) != nullptr;
|
||||
}
|
||||
bool isPointeeMutated(const Decl *Dec) {
|
||||
return findPointeeMutation(Dec) != nullptr;
|
||||
}
|
||||
const Stmt *findPointeeMutation(const Expr *Exp);
|
||||
const Stmt *findPointeeMutation(const Decl *Dec);
|
||||
|
||||
private:
|
||||
using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *);
|
||||
using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
|
||||
|
||||
const Stmt *findMutationMemoized(const Expr *Exp,
|
||||
llvm::ArrayRef<MutationFinder> Finders,
|
||||
ResultMap &MemoizedResults);
|
||||
const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
|
||||
|
||||
bool isUnevaluated(const Expr *Exp);
|
||||
|
||||
const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *
|
||||
findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
const Stmt *
|
||||
findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
|
||||
|
||||
const Stmt *findDirectMutation(const Expr *Exp);
|
||||
const Stmt *findMemberMutation(const Expr *Exp);
|
||||
|
@ -53,6 +72,7 @@ private:
|
|||
std::unique_ptr<FunctionParmMutationAnalyzer>>
|
||||
FuncParmAnalyzer;
|
||||
ResultMap Results;
|
||||
ResultMap PointeeResults;
|
||||
};
|
||||
|
||||
// A convenient wrapper around ExprMutationAnalyzer for analyzing function
|
||||
|
|
|
@ -64,33 +64,83 @@ const auto isMoveOnly = [] {
|
|||
unless(isDeleted()))))));
|
||||
};
|
||||
|
||||
template <class T> struct NodeID;
|
||||
template <> struct NodeID<Expr> { static const std::string value; };
|
||||
template <> struct NodeID<Decl> { static const std::string value; };
|
||||
const std::string NodeID<Expr>::value = "expr";
|
||||
const std::string NodeID<Decl>::value = "decl";
|
||||
|
||||
template <class T, class F = const Stmt *(ExprMutationAnalyzer::*)(const T *)>
|
||||
const Stmt *tryEachMatch(ArrayRef<ast_matchers::BoundNodes> Matches,
|
||||
ExprMutationAnalyzer *Analyzer, F Finder) {
|
||||
const StringRef ID = NodeID<T>::value;
|
||||
for (const auto &Nodes : Matches) {
|
||||
if (const Stmt *S = (Analyzer->*Finder)(Nodes.getNodeAs<T>(ID)))
|
||||
return S;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) {
|
||||
const auto Memoized = Results.find(Exp);
|
||||
if (Memoized != Results.end())
|
||||
return findMutationMemoized(Exp,
|
||||
{&ExprMutationAnalyzer::findDirectMutation,
|
||||
&ExprMutationAnalyzer::findMemberMutation,
|
||||
&ExprMutationAnalyzer::findArrayElementMutation,
|
||||
&ExprMutationAnalyzer::findCastMutation,
|
||||
&ExprMutationAnalyzer::findRangeLoopMutation,
|
||||
&ExprMutationAnalyzer::findReferenceMutation,
|
||||
&ExprMutationAnalyzer::findFunctionArgMutation},
|
||||
Results);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findMutation(const Decl *Dec) {
|
||||
return tryEachDeclRef(Dec, &ExprMutationAnalyzer::findMutation);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findPointeeMutation(const Expr *Exp) {
|
||||
return findMutationMemoized(Exp, {/*TODO*/}, PointeeResults);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findPointeeMutation(const Decl *Dec) {
|
||||
return tryEachDeclRef(Dec, &ExprMutationAnalyzer::findPointeeMutation);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findMutationMemoized(
|
||||
const Expr *Exp, llvm::ArrayRef<MutationFinder> Finders,
|
||||
ResultMap &MemoizedResults) {
|
||||
const auto Memoized = MemoizedResults.find(Exp);
|
||||
if (Memoized != MemoizedResults.end())
|
||||
return Memoized->second;
|
||||
|
||||
if (isUnevaluated(Exp))
|
||||
return Results[Exp] = nullptr;
|
||||
return MemoizedResults[Exp] = nullptr;
|
||||
|
||||
for (const auto &Finder : {&ExprMutationAnalyzer::findDirectMutation,
|
||||
&ExprMutationAnalyzer::findMemberMutation,
|
||||
&ExprMutationAnalyzer::findArrayElementMutation,
|
||||
&ExprMutationAnalyzer::findCastMutation,
|
||||
&ExprMutationAnalyzer::findRangeLoopMutation,
|
||||
&ExprMutationAnalyzer::findReferenceMutation,
|
||||
&ExprMutationAnalyzer::findFunctionArgMutation}) {
|
||||
for (const auto &Finder : Finders) {
|
||||
if (const Stmt *S = (this->*Finder)(Exp))
|
||||
return Results[Exp] = S;
|
||||
return MemoizedResults[Exp] = S;
|
||||
}
|
||||
|
||||
return Results[Exp] = nullptr;
|
||||
return MemoizedResults[Exp] = nullptr;
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::tryEachDeclRef(const Decl *Dec,
|
||||
MutationFinder Finder) {
|
||||
const auto Refs =
|
||||
match(findAll(declRefExpr(to(equalsNode(Dec))).bind(NodeID<Expr>::value)),
|
||||
Stm, Context);
|
||||
for (const auto &RefNodes : Refs) {
|
||||
const auto *E = RefNodes.getNodeAs<Expr>(NodeID<Expr>::value);
|
||||
if ((this->*Finder)(E))
|
||||
return E;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) {
|
||||
return selectFirst<Expr>(
|
||||
"expr",
|
||||
NodeID<Expr>::value,
|
||||
match(
|
||||
findAll(
|
||||
expr(equalsNode(Exp),
|
||||
|
@ -115,37 +165,30 @@ bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) {
|
|||
genericSelectionExpr(hasControllingExpr(
|
||||
hasDescendant(equalsNode(Exp)))),
|
||||
cxxNoexceptExpr())))))
|
||||
.bind("expr")),
|
||||
.bind(NodeID<Expr>::value)),
|
||||
Stm, Context)) != nullptr;
|
||||
}
|
||||
|
||||
const Stmt *
|
||||
ExprMutationAnalyzer::findExprMutation(ArrayRef<BoundNodes> Matches) {
|
||||
for (const auto &Nodes : Matches) {
|
||||
if (const Stmt *S = findMutation(Nodes.getNodeAs<Expr>("expr")))
|
||||
return S;
|
||||
}
|
||||
return nullptr;
|
||||
return tryEachMatch<Expr>(Matches, this, &ExprMutationAnalyzer::findMutation);
|
||||
}
|
||||
|
||||
const Stmt *
|
||||
ExprMutationAnalyzer::findDeclMutation(ArrayRef<BoundNodes> Matches) {
|
||||
for (const auto &DeclNodes : Matches) {
|
||||
if (const Stmt *S = findMutation(DeclNodes.getNodeAs<Decl>("decl")))
|
||||
return S;
|
||||
}
|
||||
return nullptr;
|
||||
return tryEachMatch<Decl>(Matches, this, &ExprMutationAnalyzer::findMutation);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findMutation(const Decl *Dec) {
|
||||
const auto Refs = match(
|
||||
findAll(declRefExpr(to(equalsNode(Dec))).bind("expr")), Stm, Context);
|
||||
for (const auto &RefNodes : Refs) {
|
||||
const auto *E = RefNodes.getNodeAs<Expr>("expr");
|
||||
if (findMutation(E))
|
||||
return E;
|
||||
}
|
||||
return nullptr;
|
||||
const Stmt *ExprMutationAnalyzer::findExprPointeeMutation(
|
||||
ArrayRef<ast_matchers::BoundNodes> Matches) {
|
||||
return tryEachMatch<Expr>(Matches, this,
|
||||
&ExprMutationAnalyzer::findPointeeMutation);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findDeclPointeeMutation(
|
||||
ArrayRef<ast_matchers::BoundNodes> Matches) {
|
||||
return tryEachMatch<Decl>(Matches, this,
|
||||
&ExprMutationAnalyzer::findPointeeMutation);
|
||||
}
|
||||
|
||||
const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) {
|
||||
|
@ -237,7 +280,7 @@ const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) {
|
|||
match(findAll(expr(anyOf(memberExpr(hasObjectExpression(equalsNode(Exp))),
|
||||
cxxDependentScopeMemberExpr(
|
||||
hasObjectExpression(equalsNode(Exp)))))
|
||||
.bind("expr")),
|
||||
.bind(NodeID<Expr>::value)),
|
||||
Stm, Context);
|
||||
return findExprMutation(MemberExprs);
|
||||
}
|
||||
|
@ -246,7 +289,7 @@ const Stmt *ExprMutationAnalyzer::findArrayElementMutation(const Expr *Exp) {
|
|||
// Check whether any element of an array is mutated.
|
||||
const auto SubscriptExprs = match(
|
||||
findAll(arraySubscriptExpr(hasBase(ignoringImpCasts(equalsNode(Exp))))
|
||||
.bind("expr")),
|
||||
.bind(NodeID<Expr>::value)),
|
||||
Stm, Context);
|
||||
return findExprMutation(SubscriptExprs);
|
||||
}
|
||||
|
@ -259,7 +302,7 @@ const Stmt *ExprMutationAnalyzer::findCastMutation(const Expr *Exp) {
|
|||
nonConstReferenceType())),
|
||||
implicitCastExpr(hasImplicitDestinationType(
|
||||
nonConstReferenceType()))))
|
||||
.bind("expr")),
|
||||
.bind(NodeID<Expr>::value)),
|
||||
Stm, Context);
|
||||
return findExprMutation(Casts);
|
||||
}
|
||||
|
@ -269,8 +312,8 @@ const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) {
|
|||
// check all declRefExpr of the loop variable.
|
||||
const auto LoopVars =
|
||||
match(findAll(cxxForRangeStmt(
|
||||
hasLoopVariable(
|
||||
varDecl(hasType(nonConstReferenceType())).bind("decl")),
|
||||
hasLoopVariable(varDecl(hasType(nonConstReferenceType()))
|
||||
.bind(NodeID<Decl>::value)),
|
||||
hasRangeInit(equalsNode(Exp)))),
|
||||
Stm, Context);
|
||||
return findDeclMutation(LoopVars);
|
||||
|
@ -286,7 +329,7 @@ const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) {
|
|||
callee(cxxMethodDecl(ofClass(isMoveOnly()),
|
||||
returns(nonConstReferenceType()))),
|
||||
argumentCountIs(1), hasArgument(0, equalsNode(Exp)))
|
||||
.bind("expr")),
|
||||
.bind(NodeID<Expr>::value)),
|
||||
Stm, Context);
|
||||
if (const Stmt *S = findExprMutation(Ref))
|
||||
return S;
|
||||
|
@ -305,7 +348,7 @@ const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) {
|
|||
// that separately.
|
||||
unless(hasParent(declStmt(hasParent(
|
||||
cxxForRangeStmt(hasRangeStmt(equalsBoundNode("stmt"))))))))
|
||||
.bind("decl"))),
|
||||
.bind(NodeID<Decl>::value))),
|
||||
Stm, Context);
|
||||
return findDeclMutation(Refs);
|
||||
}
|
||||
|
@ -320,10 +363,10 @@ const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
|
|||
findAll(expr(anyOf(callExpr(NonConstRefParam, IsInstantiated, FuncDecl),
|
||||
cxxConstructExpr(NonConstRefParam, IsInstantiated,
|
||||
FuncDecl)))
|
||||
.bind("expr")),
|
||||
.bind(NodeID<Expr>::value)),
|
||||
Stm, Context);
|
||||
for (const auto &Nodes : Matches) {
|
||||
const auto *Exp = Nodes.getNodeAs<Expr>("expr");
|
||||
const auto *Exp = Nodes.getNodeAs<Expr>(NodeID<Expr>::value);
|
||||
const auto *Func = Nodes.getNodeAs<FunctionDecl>("func");
|
||||
if (!Func->getBody())
|
||||
return Exp;
|
||||
|
|
Loading…
Reference in New Issue