11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "llvm/ADT/STLExtras.h" 17 using namespace ast_matchers;
22 return llvm::is_contained(Node.capture_inits(), E);
26 ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) {
27 const DeclStmt *
const Range = Node.getRangeStmt();
28 return InnerMatcher.matches(*Range, Finder, Builder);
31 const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr>
34 AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) {
35 return Node.isPotentiallyEvaluated();
38 const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
41 const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt,
46 ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
47 return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder);
50 const auto nonConstReferenceType = [] {
51 return referenceType(pointee(unless(isConstQualified())));
57 const auto Memoized =
Results.find(Exp);
59 return Memoized->second;
61 if (isUnevaluated(Exp))
64 for (
const auto &Finder : {&ExprMutationAnalyzer::findDirectMutation,
65 &ExprMutationAnalyzer::findMemberMutation,
66 &ExprMutationAnalyzer::findArrayElementMutation,
67 &ExprMutationAnalyzer::findCastMutation,
68 &ExprMutationAnalyzer::findRangeLoopMutation,
69 &ExprMutationAnalyzer::findReferenceMutation}) {
70 if (
const Stmt *S = (this->*Finder)(Exp))
77 bool ExprMutationAnalyzer::isUnevaluated(
const Expr *Exp) {
78 return selectFirst<Expr>(
87 hasAncestor(typeLoc(unless(
88 hasAncestor(unaryExprOrTypeTraitExpr())))),
89 hasAncestor(expr(anyOf(
92 unaryExprOrTypeTraitExpr(unless(sizeOfExpr(
93 hasArgumentOfType(variableArrayType())))),
98 unless(isPotentiallyEvaluated())),
101 genericSelectionExpr(hasControllingExpr(
102 hasDescendant(equalsNode(Exp)))),
103 cxxNoexceptExpr())))))
105 *Stm, *Context)) !=
nullptr;
109 ExprMutationAnalyzer::findExprMutation(ArrayRef<BoundNodes> Matches) {
110 for (
const auto &Nodes : Matches) {
111 if (
const Stmt *S = findMutation(Nodes.getNodeAs<Expr>(
"expr")))
118 ExprMutationAnalyzer::findDeclMutation(ArrayRef<BoundNodes> Matches) {
119 for (
const auto &DeclNodes : Matches) {
120 if (
const Stmt *S = findDeclMutation(DeclNodes.getNodeAs<Decl>(
"decl")))
126 const Stmt *ExprMutationAnalyzer::findDeclMutation(
const Decl *Dec) {
127 const auto Refs = match(
128 findAll(declRefExpr(to(equalsNode(Dec))).bind(
"expr")), *Stm, *Context);
129 for (
const auto &RefNodes : Refs) {
130 const auto *E = RefNodes.getNodeAs<Expr>(
"expr");
137 const Stmt *ExprMutationAnalyzer::findDirectMutation(
const Expr *Exp) {
139 const auto AsAssignmentLhs =
140 binaryOperator(isAssignmentOperator(), hasLHS(equalsNode(Exp)));
143 const auto AsIncDecOperand =
144 unaryOperator(anyOf(hasOperatorName(
"++"), hasOperatorName(
"--")),
145 hasUnaryOperand(equalsNode(Exp)));
148 const auto NonConstMethod = cxxMethodDecl(unless(isConst()));
149 const auto AsNonConstThis =
150 expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))),
151 cxxOperatorCallExpr(callee(NonConstMethod),
152 hasArgument(0, equalsNode(Exp)))));
158 const auto AsAmpersandOperand =
159 unaryOperator(hasOperatorName(
"&"),
161 unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))),
162 hasUnaryOperand(equalsNode(Exp)));
163 const auto AsPointerFromArrayDecay =
164 castExpr(hasCastKind(CK_ArrayToPointerDecay),
165 unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp)));
168 const auto NonConstRefParam = forEachArgumentWithParam(
169 equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType())));
170 const auto AsNonConstRefArg =
171 anyOf(callExpr(NonConstRefParam), cxxConstructExpr(NonConstRefParam));
177 const auto AsLambdaRefCaptureInit = lambdaExpr(hasCaptureInit(Exp));
184 const auto AsNonConstRefReturn = returnStmt(hasReturnValue(equalsNode(Exp)));
187 match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis,
188 AsAmpersandOperand, AsPointerFromArrayDecay,
189 AsNonConstRefArg, AsLambdaRefCaptureInit,
190 AsNonConstRefReturn))
193 return selectFirst<Stmt>(
"stmt", Matches);
196 const Stmt *ExprMutationAnalyzer::findMemberMutation(
const Expr *Exp) {
198 const auto MemberExprs = match(
199 findAll(memberExpr(hasObjectExpression(equalsNode(Exp))).bind(
"expr")),
201 return findExprMutation(MemberExprs);
204 const Stmt *ExprMutationAnalyzer::findArrayElementMutation(
const Expr *Exp) {
206 const auto SubscriptExprs = match(
207 findAll(arraySubscriptExpr(hasBase(ignoringImpCasts(equalsNode(Exp))))
210 return findExprMutation(SubscriptExprs);
213 const Stmt *ExprMutationAnalyzer::findCastMutation(
const Expr *Exp) {
216 match(findAll(castExpr(hasSourceExpression(equalsNode(Exp)),
217 anyOf(explicitCastExpr(hasDestinationType(
218 nonConstReferenceType())),
219 implicitCastExpr(hasImplicitDestinationType(
220 nonConstReferenceType()))))
223 return findExprMutation(Casts);
226 const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(
const Expr *Exp) {
229 const auto LoopVars =
230 match(findAll(cxxForRangeStmt(
232 varDecl(hasType(nonConstReferenceType())).bind(
"decl")),
233 hasRangeInit(equalsNode(Exp)))),
235 return findDeclMutation(LoopVars);
238 const Stmt *ExprMutationAnalyzer::findReferenceMutation(
const Expr *Exp) {
240 const auto Refs = match(
241 stmt(forEachDescendant(
243 hasType(nonConstReferenceType()),
244 hasInitializer(anyOf(equalsNode(Exp),
245 conditionalOperator(anyOf(
246 hasTrueExpression(equalsNode(Exp)),
247 hasFalseExpression(equalsNode(Exp)))))),
248 hasParent(declStmt().bind(
"stmt")),
251 unless(hasParent(declStmt(hasParent(
252 cxxForRangeStmt(hasRangeStmt(equalsBoundNode(
"stmt"))))))))
255 return findDeclMutation(Refs);
AST_MATCHER(BinaryOperator, isAssignmentOperator)
std::vector< CodeCompletionResult > Results
const Stmt * findMutation(const Expr *Exp)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
CharSourceRange Range
SourceRange for the file name.
AST_MATCHER_P(NamespaceAliasDecl, hasTargetNamespace, ast_matchers::internal::Matcher< NamespaceDecl >, innerMatcher)