clang  8.0.0
ExprMutationAnalyzer.cpp
Go to the documentation of this file.
1 //===---------- ExprMutationAnalyzer.cpp ----------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
11 #include "llvm/ADT/STLExtras.h"
12 
13 namespace clang {
14 using namespace ast_matchers;
15 
16 namespace {
17 
18 AST_MATCHER_P(LambdaExpr, hasCaptureInit, const Expr *, E) {
19  return llvm::is_contained(Node.capture_inits(), E);
20 }
21 
22 AST_MATCHER_P(CXXForRangeStmt, hasRangeStmt,
23  ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) {
24  const DeclStmt *const Range = Node.getRangeStmt();
25  return InnerMatcher.matches(*Range, Finder, Builder);
26 }
27 
28 const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr>
29  cxxTypeidExpr;
30 
31 AST_MATCHER(CXXTypeidExpr, isPotentiallyEvaluated) {
32  return Node.isPotentiallyEvaluated();
33 }
34 
35 const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt, CXXNoexceptExpr>
36  cxxNoexceptExpr;
37 
38 const ast_matchers::internal::VariadicDynCastAllOfMatcher<Stmt,
39  GenericSelectionExpr>
40  genericSelectionExpr;
41 
42 AST_MATCHER_P(GenericSelectionExpr, hasControllingExpr,
43  ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
44  return InnerMatcher.matches(*Node.getControllingExpr(), Finder, Builder);
45 }
46 
47 const auto nonConstReferenceType = [] {
48  return hasUnqualifiedDesugaredType(
49  referenceType(pointee(unless(isConstQualified()))));
50 };
51 
52 const auto nonConstPointerType = [] {
53  return hasUnqualifiedDesugaredType(
54  pointerType(pointee(unless(isConstQualified()))));
55 };
56 
57 const auto isMoveOnly = [] {
58  return cxxRecordDecl(
59  hasMethod(cxxConstructorDecl(isMoveConstructor(), unless(isDeleted()))),
60  hasMethod(cxxMethodDecl(isMoveAssignmentOperator(), unless(isDeleted()))),
61  unless(anyOf(hasMethod(cxxConstructorDecl(isCopyConstructor(),
62  unless(isDeleted()))),
63  hasMethod(cxxMethodDecl(isCopyAssignmentOperator(),
64  unless(isDeleted()))))));
65 };
66 
67 template <class T> struct NodeID;
68 template <> struct NodeID<Expr> { static const std::string value; };
69 template <> struct NodeID<Decl> { static const std::string value; };
70 const std::string NodeID<Expr>::value = "expr";
71 const std::string NodeID<Decl>::value = "decl";
72 
73 template <class T, class F = const Stmt *(ExprMutationAnalyzer::*)(const T *)>
74 const Stmt *tryEachMatch(ArrayRef<ast_matchers::BoundNodes> Matches,
75  ExprMutationAnalyzer *Analyzer, F Finder) {
76  const StringRef ID = NodeID<T>::value;
77  for (const auto &Nodes : Matches) {
78  if (const Stmt *S = (Analyzer->*Finder)(Nodes.getNodeAs<T>(ID)))
79  return S;
80  }
81  return nullptr;
82 }
83 
84 } // namespace
85 
86 const Stmt *ExprMutationAnalyzer::findMutation(const Expr *Exp) {
87  return findMutationMemoized(Exp,
88  {&ExprMutationAnalyzer::findDirectMutation,
89  &ExprMutationAnalyzer::findMemberMutation,
90  &ExprMutationAnalyzer::findArrayElementMutation,
91  &ExprMutationAnalyzer::findCastMutation,
92  &ExprMutationAnalyzer::findRangeLoopMutation,
93  &ExprMutationAnalyzer::findReferenceMutation,
94  &ExprMutationAnalyzer::findFunctionArgMutation},
95  Results);
96 }
97 
98 const Stmt *ExprMutationAnalyzer::findMutation(const Decl *Dec) {
99  return tryEachDeclRef(Dec, &ExprMutationAnalyzer::findMutation);
100 }
101 
103  return findMutationMemoized(Exp, {/*TODO*/}, PointeeResults);
104 }
105 
107  return tryEachDeclRef(Dec, &ExprMutationAnalyzer::findPointeeMutation);
108 }
109 
110 const Stmt *ExprMutationAnalyzer::findMutationMemoized(
111  const Expr *Exp, llvm::ArrayRef<MutationFinder> Finders,
112  ResultMap &MemoizedResults) {
113  const auto Memoized = MemoizedResults.find(Exp);
114  if (Memoized != MemoizedResults.end())
115  return Memoized->second;
116 
117  if (isUnevaluated(Exp))
118  return MemoizedResults[Exp] = nullptr;
119 
120  for (const auto &Finder : Finders) {
121  if (const Stmt *S = (this->*Finder)(Exp))
122  return MemoizedResults[Exp] = S;
123  }
124 
125  return MemoizedResults[Exp] = nullptr;
126 }
127 
128 const Stmt *ExprMutationAnalyzer::tryEachDeclRef(const Decl *Dec,
129  MutationFinder Finder) {
130  const auto Refs =
131  match(findAll(declRefExpr(to(equalsNode(Dec))).bind(NodeID<Expr>::value)),
132  Stm, Context);
133  for (const auto &RefNodes : Refs) {
134  const auto *E = RefNodes.getNodeAs<Expr>(NodeID<Expr>::value);
135  if ((this->*Finder)(E))
136  return E;
137  }
138  return nullptr;
139 }
140 
141 bool ExprMutationAnalyzer::isUnevaluated(const Expr *Exp) {
142  return selectFirst<Expr>(
143  NodeID<Expr>::value,
144  match(
145  findAll(
146  expr(equalsNode(Exp),
147  anyOf(
148  // `Exp` is part of the underlying expression of
149  // decltype/typeof if it has an ancestor of
150  // typeLoc.
154  // `UnaryExprOrTypeTraitExpr` is unevaluated
155  // unless it's sizeof on VLA.
157  hasArgumentOfType(variableArrayType())))),
158  // `CXXTypeidExpr` is unevaluated unless it's
159  // applied to an expression of glvalue of
160  // polymorphic class type.
161  cxxTypeidExpr(
162  unless(isPotentiallyEvaluated())),
163  // The controlling expression of
164  // `GenericSelectionExpr` is unevaluated.
165  genericSelectionExpr(hasControllingExpr(
166  hasDescendant(equalsNode(Exp)))),
167  cxxNoexceptExpr())))))
168  .bind(NodeID<Expr>::value)),
169  Stm, Context)) != nullptr;
170 }
171 
172 const Stmt *
173 ExprMutationAnalyzer::findExprMutation(ArrayRef<BoundNodes> Matches) {
174  return tryEachMatch<Expr>(Matches, this, &ExprMutationAnalyzer::findMutation);
175 }
176 
177 const Stmt *
178 ExprMutationAnalyzer::findDeclMutation(ArrayRef<BoundNodes> Matches) {
179  return tryEachMatch<Decl>(Matches, this, &ExprMutationAnalyzer::findMutation);
180 }
181 
182 const Stmt *ExprMutationAnalyzer::findExprPointeeMutation(
184  return tryEachMatch<Expr>(Matches, this,
186 }
187 
188 const Stmt *ExprMutationAnalyzer::findDeclPointeeMutation(
190  return tryEachMatch<Decl>(Matches, this,
192 }
193 
194 const Stmt *ExprMutationAnalyzer::findDirectMutation(const Expr *Exp) {
195  // LHS of any assignment operators.
196  const auto AsAssignmentLhs =
197  binaryOperator(isAssignmentOperator(), hasLHS(equalsNode(Exp)));
198 
199  // Operand of increment/decrement operators.
200  const auto AsIncDecOperand =
201  unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")),
202  hasUnaryOperand(equalsNode(Exp)));
203 
204  // Invoking non-const member function.
205  // A member function is assumed to be non-const when it is unresolved.
206  const auto NonConstMethod = cxxMethodDecl(unless(isConst()));
207  const auto AsNonConstThis =
208  expr(anyOf(cxxMemberCallExpr(callee(NonConstMethod), on(equalsNode(Exp))),
209  cxxOperatorCallExpr(callee(NonConstMethod),
210  hasArgument(0, equalsNode(Exp))),
211  callExpr(callee(expr(anyOf(
212  unresolvedMemberExpr(hasObjectExpression(equalsNode(Exp))),
214  hasObjectExpression(equalsNode(Exp)))))))));
215 
216  // Taking address of 'Exp'.
217  // We're assuming 'Exp' is mutated as soon as its address is taken, though in
218  // theory we can follow the pointer and see whether it escaped `Stm` or is
219  // dereferenced and then mutated. This is left for future improvements.
220  const auto AsAmpersandOperand =
221  unaryOperator(hasOperatorName("&"),
222  // A NoOp implicit cast is adding const.
223  unless(hasParent(implicitCastExpr(hasCastKind(CK_NoOp)))),
224  hasUnaryOperand(equalsNode(Exp)));
225  const auto AsPointerFromArrayDecay =
226  castExpr(hasCastKind(CK_ArrayToPointerDecay),
227  unless(hasParent(arraySubscriptExpr())), has(equalsNode(Exp)));
228  // Treat calling `operator->()` of move-only classes as taking address.
229  // These are typically smart pointers with unique ownership so we treat
230  // mutation of pointee as mutation of the smart pointer itself.
231  const auto AsOperatorArrowThis =
233  callee(cxxMethodDecl(ofClass(isMoveOnly()),
234  returns(nonConstPointerType()))),
235  argumentCountIs(1), hasArgument(0, equalsNode(Exp)));
236 
237  // Used as non-const-ref argument when calling a function.
238  // An argument is assumed to be non-const-ref when the function is unresolved.
239  // Instantiated template functions are not handled here but in
240  // findFunctionArgMutation which has additional smarts for handling forwarding
241  // references.
242  const auto NonConstRefParam = forEachArgumentWithParam(
243  equalsNode(Exp), parmVarDecl(hasType(nonConstReferenceType())));
244  const auto NotInstantiated = unless(hasDeclaration(isInstantiated()));
245  const auto AsNonConstRefArg = anyOf(
246  callExpr(NonConstRefParam, NotInstantiated),
247  cxxConstructExpr(NonConstRefParam, NotInstantiated),
250  hasType(templateTypeParmType())))),
251  hasAnyArgument(equalsNode(Exp))),
252  cxxUnresolvedConstructExpr(hasAnyArgument(equalsNode(Exp))));
253 
254  // Captured by a lambda by reference.
255  // If we're initializing a capture with 'Exp' directly then we're initializing
256  // a reference capture.
257  // For value captures there will be an ImplicitCastExpr <LValueToRValue>.
258  const auto AsLambdaRefCaptureInit = lambdaExpr(hasCaptureInit(Exp));
259 
260  // Returned as non-const-ref.
261  // If we're returning 'Exp' directly then it's returned as non-const-ref.
262  // For returning by value there will be an ImplicitCastExpr <LValueToRValue>.
263  // For returning by const-ref there will be an ImplicitCastExpr <NoOp> (for
264  // adding const.)
265  const auto AsNonConstRefReturn = returnStmt(hasReturnValue(equalsNode(Exp)));
266 
267  const auto Matches =
268  match(findAll(stmt(anyOf(AsAssignmentLhs, AsIncDecOperand, AsNonConstThis,
269  AsAmpersandOperand, AsPointerFromArrayDecay,
270  AsOperatorArrowThis, AsNonConstRefArg,
271  AsLambdaRefCaptureInit, AsNonConstRefReturn))
272  .bind("stmt")),
273  Stm, Context);
274  return selectFirst<Stmt>("stmt", Matches);
275 }
276 
277 const Stmt *ExprMutationAnalyzer::findMemberMutation(const Expr *Exp) {
278  // Check whether any member of 'Exp' is mutated.
279  const auto MemberExprs =
280  match(findAll(expr(anyOf(memberExpr(hasObjectExpression(equalsNode(Exp))),
282  hasObjectExpression(equalsNode(Exp)))))
283  .bind(NodeID<Expr>::value)),
284  Stm, Context);
285  return findExprMutation(MemberExprs);
286 }
287 
288 const Stmt *ExprMutationAnalyzer::findArrayElementMutation(const Expr *Exp) {
289  // Check whether any element of an array is mutated.
290  const auto SubscriptExprs = match(
291  findAll(arraySubscriptExpr(hasBase(ignoringImpCasts(equalsNode(Exp))))
292  .bind(NodeID<Expr>::value)),
293  Stm, Context);
294  return findExprMutation(SubscriptExprs);
295 }
296 
297 const Stmt *ExprMutationAnalyzer::findCastMutation(const Expr *Exp) {
298  // If 'Exp' is casted to any non-const reference type, check the castExpr.
299  const auto Casts =
300  match(findAll(castExpr(hasSourceExpression(equalsNode(Exp)),
301  anyOf(explicitCastExpr(hasDestinationType(
302  nonConstReferenceType())),
303  implicitCastExpr(hasImplicitDestinationType(
304  nonConstReferenceType()))))
305  .bind(NodeID<Expr>::value)),
306  Stm, Context);
307  if (const Stmt *S = findExprMutation(Casts))
308  return S;
309  // Treat std::{move,forward} as cast.
310  const auto Calls =
312  hasAnyName("::std::move", "::std::forward"))),
313  hasArgument(0, equalsNode(Exp)))
314  .bind("expr")),
315  Stm, Context);
316  return findExprMutation(Calls);
317 }
318 
319 const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) {
320  // If range for looping over 'Exp' with a non-const reference loop variable,
321  // check all declRefExpr of the loop variable.
322  const auto LoopVars =
324  hasLoopVariable(varDecl(hasType(nonConstReferenceType()))
325  .bind(NodeID<Decl>::value)),
326  hasRangeInit(equalsNode(Exp)))),
327  Stm, Context);
328  return findDeclMutation(LoopVars);
329 }
330 
331 const Stmt *ExprMutationAnalyzer::findReferenceMutation(const Expr *Exp) {
332  // Follow non-const reference returned by `operator*()` of move-only classes.
333  // These are typically smart pointers with unique ownership so we treat
334  // mutation of pointee as mutation of the smart pointer itself.
335  const auto Ref =
338  callee(cxxMethodDecl(ofClass(isMoveOnly()),
339  returns(nonConstReferenceType()))),
340  argumentCountIs(1), hasArgument(0, equalsNode(Exp)))
341  .bind(NodeID<Expr>::value)),
342  Stm, Context);
343  if (const Stmt *S = findExprMutation(Ref))
344  return S;
345 
346  // If 'Exp' is bound to a non-const reference, check all declRefExpr to that.
347  const auto Refs = match(
349  varDecl(
350  hasType(nonConstReferenceType()),
351  hasInitializer(anyOf(equalsNode(Exp),
353  hasTrueExpression(equalsNode(Exp)),
354  hasFalseExpression(equalsNode(Exp)))))),
355  hasParent(declStmt().bind("stmt")),
356  // Don't follow the reference in range statement, we've handled
357  // that separately.
359  cxxForRangeStmt(hasRangeStmt(equalsBoundNode("stmt"))))))))
360  .bind(NodeID<Decl>::value))),
361  Stm, Context);
362  return findDeclMutation(Refs);
363 }
364 
365 const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
366  const auto NonConstRefParam = forEachArgumentWithParam(
367  equalsNode(Exp),
368  parmVarDecl(hasType(nonConstReferenceType())).bind("parm"));
369  const auto IsInstantiated = hasDeclaration(isInstantiated());
370  const auto FuncDecl = hasDeclaration(functionDecl().bind("func"));
371  const auto Matches = match(
372  findAll(expr(anyOf(callExpr(NonConstRefParam, IsInstantiated, FuncDecl,
373  unless(callee(namedDecl(hasAnyName(
374  "::std::move", "::std::forward"))))),
375  cxxConstructExpr(NonConstRefParam, IsInstantiated,
376  FuncDecl)))
377  .bind(NodeID<Expr>::value)),
378  Stm, Context);
379  for (const auto &Nodes : Matches) {
380  const auto *Exp = Nodes.getNodeAs<Expr>(NodeID<Expr>::value);
381  const auto *Func = Nodes.getNodeAs<FunctionDecl>("func");
382  if (!Func->getBody() || !Func->getPrimaryTemplate())
383  return Exp;
384 
385  const auto *Parm = Nodes.getNodeAs<ParmVarDecl>("parm");
386  const ArrayRef<ParmVarDecl *> AllParams =
387  Func->getPrimaryTemplate()->getTemplatedDecl()->parameters();
388  QualType ParmType =
389  AllParams[std::min<size_t>(Parm->getFunctionScopeIndex(),
390  AllParams.size() - 1)]
391  ->getType();
392  if (const auto *T = ParmType->getAs<PackExpansionType>())
393  ParmType = T->getPattern();
394 
395  // If param type is forwarding reference, follow into the function
396  // definition and see whether the param is mutated inside.
397  if (const auto *RefType = ParmType->getAs<RValueReferenceType>()) {
398  if (!RefType->getPointeeType().getQualifiers() &&
399  RefType->getPointeeType()->getAs<TemplateTypeParmType>()) {
400  std::unique_ptr<FunctionParmMutationAnalyzer> &Analyzer =
401  FuncParmAnalyzer[Func];
402  if (!Analyzer)
403  Analyzer.reset(new FunctionParmMutationAnalyzer(*Func, Context));
404  if (Analyzer->findMutation(Parm))
405  return Exp;
406  continue;
407  }
408  }
409  // Not forwarding reference.
410  return Exp;
411  }
412  return nullptr;
413 }
414 
416  const FunctionDecl &Func, ASTContext &Context)
417  : BodyAnalyzer(*Func.getBody(), Context) {
418  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(&Func)) {
419  // CXXCtorInitializer might also mutate Param but they're not part of
420  // function body, check them eagerly here since they're typically trivial.
421  for (const CXXCtorInitializer *Init : Ctor->inits()) {
422  ExprMutationAnalyzer InitAnalyzer(*Init->getInit(), Context);
423  for (const ParmVarDecl *Parm : Ctor->parameters()) {
424  if (Results.find(Parm) != Results.end())
425  continue;
426  if (const Stmt *S = InitAnalyzer.findMutation(Parm))
427  Results[Parm] = S;
428  }
429  }
430  }
431 }
432 
433 const Stmt *
435  const auto Memoized = Results.find(Parm);
436  if (Memoized != Results.end())
437  return Memoized->second;
438 
439  if (const Stmt *S = BodyAnalyzer.findMutation(Parm))
440  return Results[Parm] = S;
441 
442  return Results[Parm] = nullptr;
443 }
444 
445 } // namespace clang
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
Represents a function declaration or definition.
Definition: Decl.h:1738
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
A (possibly-)qualified type.
Definition: Type.h:638
AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width)
Matches non-static data members that are bit-fields of the specified bit width.
Definition: ASTMatchers.h:612
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXUnresolvedConstructExpr > cxxUnresolvedConstructExpr
Matches unresolved constructor call expressions.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher< Decl >, void(internal::HasDeclarationSupportedTypes)> hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
Definition: ASTMatchers.h:2865
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
bool isAssignmentOperator(OverloadedOperatorKind OK)
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const Stmt * findPointeeMutation(const Expr *Exp)
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6748
Analyzes whether any mutative operations are applied to an expression within a given statement...
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
AST_MATCHER(Decl, isPublic)
Matches public C++ declarations.
Definition: ASTMatchers.h:548
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, NamedDecl > namedDecl
Matches a declaration of anything that could have a name.
Represents a parameter to a function.
Definition: Decl.h:1550
BoundNodesTreeBuilder Nodes
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr
Matches overloaded operator calls.
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclStmt > declStmt
Matches declaration statements.
An rvalue reference type, per C++11 [dcl.ref].
Definition: Type.h:2738
llvm::DOTGraphTraits< ExplodedGraph * > DefaultDOTGraphTraits const ExplodedNode const ExplodedNode *Out<< "\l\|";Out<< "StateID: ST"<< State-> NodeID
const internal::VariadicDynCastAllOfMatcher< Stmt, DeclRefExpr > declRefExpr
Matches expressions that refer to declarations.
const internal::VariadicFunction< internal::Matcher< NamedDecl >, StringRef, internal::hasAnyNameFunc > hasAnyName
Matches NamedDecl nodes that have any of the specified names.
internal::Matcher< Stmt > sizeOfExpr(const internal::Matcher< UnaryExprOrTypeTraitExpr > &InnerMatcher)
Same as unaryExprOrTypeTraitExpr, but only matching sizeof.
Definition: ASTMatchers.h:2505
const AstTypeMatcher< VariableArrayType > variableArrayType
Matches C arrays with a specified size that is not an integer-constant-expression.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang&#39;s AST.
internal::PolymorphicMatcherWithParam1< internal::HasOverloadedOperatorNameMatcher, StringRef, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)> hasOverloadedOperatorName(StringRef Name)
Matches overloaded operator names.
Definition: ASTMatchers.h:2589
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< T > findAll(const internal::Matcher< T > &Matcher)
Matches if the node or any descendant matches.
Definition: ASTMatchers.h:2780
const internal::ArgumentAdaptingMatcherFunc< internal::ForEachDescendantMatcher > forEachDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
const internal::VariadicDynCastAllOfMatcher< Stmt, MemberExpr > memberExpr
Matches member expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, ExplicitCastExpr > explicitCastExpr
Matches explicit cast expressions.
This represents one expression.
Definition: Expr.h:106
const internal::VariadicDynCastAllOfMatcher< Stmt, UnresolvedLookupExpr > unresolvedLookupExpr
Matches reference to a name that can be looked up during parsing but could not be resolved to a speci...
const internal::VariadicDynCastAllOfMatcher< Stmt, UnresolvedMemberExpr > unresolvedMemberExpr
Matches unresolved member expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator > conditionalOperator
Matches conditional operator expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, ReturnStmt > returnStmt
Matches return statements.
const internal::ArgumentAdaptingMatcherFunc< internal::HasAncestorMatcher, internal::TypeList< Decl, NestedNameSpecifierLoc, Stmt, TypeLoc >, internal::TypeList< Decl, NestedNameSpecifierLoc, Stmt, TypeLoc > > hasAncestor
Matches AST nodes that have an ancestor that matches the provided matcher.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr > cxxMemberCallExpr
Matches member call expressions.
const internal::VariadicDynCastAllOfMatcher< Decl, ParmVarDecl > parmVarDecl
Matches parameter variable declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl
Matches method declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXForRangeStmt > cxxForRangeStmt
Matches range-based for statements.
const internal::VariadicAllOfMatcher< TypeLoc > typeLoc
Matches TypeLocs in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXConstructExpr > cxxConstructExpr
Matches constructor call expressions (including implicit ones).
const internal::VariadicDynCastAllOfMatcher< Stmt, ArraySubscriptExpr > arraySubscriptExpr
Matches array subscript expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryExprOrTypeTraitExpr > unaryExprOrTypeTraitExpr
Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
const internal::ArgumentAdaptingMatcherFunc< internal::HasParentMatcher, internal::TypeList< Decl, NestedNameSpecifierLoc, Stmt, TypeLoc >, internal::TypeList< Decl, NestedNameSpecifierLoc, Stmt, TypeLoc > > hasParent
Matches AST nodes that have a parent that matches the provided matcher.
const internal::VariadicOperatorMatcherFunc< 1, 1 > unless
Matches if the provided matcher does not match.
Represents a pack expansion of types.
Definition: Type.h:5355
ast_type_traits::DynTypedNode Node
Dataflow Directional Tag Classes.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2256
const internal::VariadicDynCastAllOfMatcher< Stmt, LambdaExpr > lambdaExpr
Matches lambda expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, UnaryOperator > unaryOperator
Matches unary operator expressions.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXConstructorDecl > cxxConstructorDecl
Matches C++ constructor declarations.
const Stmt * findMutation(const ParmVarDecl *Parm)
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXDependentScopeMemberExpr > cxxDependentScopeMemberExpr
Matches member expressions where the actual member referenced could not be resolved because the base ...
const Stmt * findMutation(const Expr *Exp)
const internal::VariadicDynCastAllOfMatcher< Stmt, ImplicitCastExpr > implicitCastExpr
Matches the implicit cast nodes of Clang&#39;s AST.
FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context)
const AstTypeMatcher< TemplateTypeParmType > templateTypeParmType
Matches template type parameter types.
const AstTypeMatcher< ReferenceType > referenceType
Matches both lvalue and rvalue reference types.