Lines Matching +full:clang +full:- +full:analyzer
1 //===---------- ExprMutationAnalyzer.cpp ----------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 #include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
9 #include "clang/AST/Expr.h"
10 #include "clang/AST/OperationKinds.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/ASTMatchers/ASTMatchers.h"
15 namespace clang { namespace
20 // - Implicit Casts
21 // - Binary Operators
22 // - ConditionalOperator
23 // - BinaryConditionalOperator
30 if ((Cast->getCastKind() == CK_DerivedToBase || in canExprResolveTo()
31 Cast->getCastKind() == CK_UncheckedDerivedToBase) && in canExprResolveTo()
32 Matcher(Cast->getSubExpr())) in canExprResolveTo()
41 dyn_cast_or_null<BinaryOperator>(Result->IgnoreParens())) { in canExprResolveTo()
42 if (!BOComma->isCommaOp()) in canExprResolveTo()
44 Result = BOComma->getRHS(); in canExprResolveTo()
53 // The edge-case `BaseClass &b = <cond> ? DerivedVar1 : DerivedVar2;` in canExprResolveTo()
59 if (const auto *TE = OP->getTrueExpr()->IgnoreParens()) in canExprResolveTo()
62 if (const auto *FE = OP->getFalseExpr()->IgnoreParens()) in canExprResolveTo()
71 if (const auto *TE = OP->getTrueExpr()->IgnoreParens()) in canExprResolveTo()
74 if (const auto *FE = OP->getFalseExpr()->IgnoreParens()) in canExprResolveTo()
81 const Expr *SourceExprP = Source->IgnoreParens(); in canExprResolveTo()
89 E->IgnoreParens(), [&](const Expr *EE) { return EE == Target; }); in canExprResolveTo()
141 const QualType T = VD->getType().getCanonicalType(); in AST_MATCHER()
143 const auto *FPT = MPT ? cast<FunctionProtoType>(MPT->getPointeeType()) in AST_MATCHER()
147 return FPT->isConst(); in AST_MATCHER()
190 class F = const Stmt *(ExprMutationAnalyzer::Analyzer::*)(const T *)>
192 ExprMutationAnalyzer::Analyzer *Analyzer, F Finder) { in tryEachMatch() argument
195 if (const Stmt *S = (Analyzer->*Finder)(Nodes.getNodeAs<T>(ID))) in tryEachMatch()
203 const Stmt *ExprMutationAnalyzer::Analyzer::findMutation(const Expr *Exp) { in findMutation()
206 {&ExprMutationAnalyzer::Analyzer::findDirectMutation, in findMutation()
207 &ExprMutationAnalyzer::Analyzer::findMemberMutation, in findMutation()
208 &ExprMutationAnalyzer::Analyzer::findArrayElementMutation, in findMutation()
209 &ExprMutationAnalyzer::Analyzer::findCastMutation, in findMutation()
210 &ExprMutationAnalyzer::Analyzer::findRangeLoopMutation, in findMutation()
211 &ExprMutationAnalyzer::Analyzer::findReferenceMutation, in findMutation()
212 &ExprMutationAnalyzer::Analyzer::findFunctionArgMutation}, in findMutation()
216 const Stmt *ExprMutationAnalyzer::Analyzer::findMutation(const Decl *Dec) { in findMutation()
217 return tryEachDeclRef(Dec, &ExprMutationAnalyzer::Analyzer::findMutation); in findMutation()
221 ExprMutationAnalyzer::Analyzer::findPointeeMutation(const Expr *Exp) { in findPointeeMutation()
226 ExprMutationAnalyzer::Analyzer::findPointeeMutation(const Decl *Dec) { in findPointeeMutation()
228 &ExprMutationAnalyzer::Analyzer::findPointeeMutation); in findPointeeMutation()
231 const Stmt *ExprMutationAnalyzer::Analyzer::findMutationMemoized( in findMutationMemoized()
236 return Memoized->second; in findMutationMemoized()
244 if (const Stmt *S = (this->*Finder)(Exp)) in findMutationMemoized()
252 ExprMutationAnalyzer::Analyzer::tryEachDeclRef(const Decl *Dec, in tryEachDeclRef()
266 if ((this->*Finder)(E)) in tryEachDeclRef()
272 bool ExprMutationAnalyzer::Analyzer::isUnevaluated(const Stmt *Exp, in isUnevaluated()
305 bool ExprMutationAnalyzer::Analyzer::isUnevaluated(const Expr *Exp) { in isUnevaluated()
310 ExprMutationAnalyzer::Analyzer::findExprMutation(ArrayRef<BoundNodes> Matches) { in findExprMutation()
312 &ExprMutationAnalyzer::Analyzer::findMutation); in findExprMutation()
316 ExprMutationAnalyzer::Analyzer::findDeclMutation(ArrayRef<BoundNodes> Matches) { in findDeclMutation()
318 &ExprMutationAnalyzer::Analyzer::findMutation); in findDeclMutation()
321 const Stmt *ExprMutationAnalyzer::Analyzer::findExprPointeeMutation( in findExprPointeeMutation()
324 Matches, this, &ExprMutationAnalyzer::Analyzer::findPointeeMutation); in findExprPointeeMutation()
327 const Stmt *ExprMutationAnalyzer::Analyzer::findDeclPointeeMutation( in findDeclPointeeMutation()
330 Matches, this, &ExprMutationAnalyzer::Analyzer::findPointeeMutation); in findDeclPointeeMutation()
334 ExprMutationAnalyzer::Analyzer::findDirectMutation(const Expr *Exp) { in findDirectMutation()
341 unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), in findDirectMutation()
344 // Invoking non-const member function. in findDirectMutation()
345 // A member function is assumed to be non-const when it is unresolved. in findDirectMutation()
388 // Treat calling `operator->()` of move-only classes as taking address. in findDirectMutation()
392 hasOverloadedOperatorName("->"), in findDirectMutation()
397 // Used as non-const-ref argument when calling a function. in findDirectMutation()
398 // An argument is assumed to be non-const-ref when the function is unresolved. in findDirectMutation()
411 // If the call is type-dependent, we can't properly process any in findDirectMutation()
420 // type-dependent. in findDirectMutation()
432 // Returned as non-const-ref. in findDirectMutation()
433 // If we're returning 'Exp' directly then it's returned as non-const-ref. in findDirectMutation()
435 // For returning by const-ref there will be an ImplicitCastExpr <NoOp> (for in findDirectMutation()
440 // It is used as a non-const-reference for initializing a range-for loop. in findDirectMutation()
458 ExprMutationAnalyzer::Analyzer::findMemberMutation(const Expr *Exp) { in findMemberMutation()
472 ExprMutationAnalyzer::Analyzer::findArrayElementMutation(const Expr *Exp) { in findArrayElementMutation()
485 const Stmt *ExprMutationAnalyzer::Analyzer::findCastMutation(const Expr *Exp) { in findCastMutation()
486 // If the 'Exp' is explicitly casted to a non-const reference type the in findCastMutation()
498 // If 'Exp' is casted to any non-const reference type, check the castExpr. in findCastMutation()
521 ExprMutationAnalyzer::Analyzer::findRangeLoopMutation(const Expr *Exp) { in findRangeLoopMutation()
527 // array is considered modified if the loop-variable is a non-const reference. in findRangeLoopMutation()
545 // Small helper to match special cases in range-for loops. in findRangeLoopMutation()
547 // It is possible that containers do not provide a const-overload for their in findRangeLoopMutation()
548 // iterator accessors. If this is the case, the variable is used non-const in findRangeLoopMutation()
573 // If range for looping over 'Exp' with a non-const reference loop variable, in findRangeLoopMutation()
585 ExprMutationAnalyzer::Analyzer::findReferenceMutation(const Expr *Exp) { in findReferenceMutation()
586 // Follow non-const reference returned by `operator*()` of move-only classes. in findReferenceMutation()
600 // If 'Exp' is bound to a non-const reference, check all declRefExpr to that. in findReferenceMutation()
618 ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) { in findFunctionArgMutation()
638 if (!Func->getBody() || !Func->getPrimaryTemplate()) in findFunctionArgMutation()
643 Func->getPrimaryTemplate()->getTemplatedDecl()->parameters(); in findFunctionArgMutation()
645 AllParams[std::min<size_t>(Parm->getFunctionScopeIndex(), in findFunctionArgMutation()
646 AllParams.size() - 1)] in findFunctionArgMutation()
647 ->getType(); in findFunctionArgMutation()
648 if (const auto *T = ParmType->getAs<PackExpansionType>()) in findFunctionArgMutation()
649 ParmType = T->getPattern(); in findFunctionArgMutation()
653 if (const auto *RefType = ParmType->getAs<RValueReferenceType>()) { in findFunctionArgMutation()
654 if (!RefType->getPointeeType().getQualifiers() && in findFunctionArgMutation()
655 RefType->getPointeeType()->getAs<TemplateTypeParmType>()) { in findFunctionArgMutation()
656 FunctionParmMutationAnalyzer *Analyzer = in findFunctionArgMutation() local
659 if (Analyzer->findMutation(Parm)) in findFunctionArgMutation()
677 for (const CXXCtorInitializer *Init : Ctor->inits()) { in FunctionParmMutationAnalyzer()
678 ExprMutationAnalyzer::Analyzer InitAnalyzer(*Init->getInit(), Context, in FunctionParmMutationAnalyzer()
680 for (const ParmVarDecl *Parm : Ctor->parameters()) { in FunctionParmMutationAnalyzer()
694 return Memoized->second; in findMutation()
695 // To handle call A -> call B -> call A. Assume parameters of A is not mutated in findMutation()
705 } // namespace clang