1 //===---------- ExprMutationAnalyzer.h ------------------------------------===// 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 //===----------------------------------------------------------------------===// 9 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H 10 #define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H 11 12 #include <type_traits> 13 14 #include "clang/AST/AST.h" 15 #include "clang/ASTMatchers/ASTMatchers.h" 16 #include "llvm/ADT/DenseMap.h" 17 18 namespace clang { 19 20 class FunctionParmMutationAnalyzer; 21 22 /// Analyzes whether any mutative operations are applied to an expression within 23 /// a given statement. 24 class ExprMutationAnalyzer { 25 public: ExprMutationAnalyzer(const Stmt & Stm,ASTContext & Context)26 ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context) 27 : Stm(Stm), Context(Context) {} 28 isMutated(const Expr * Exp)29 bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; } isMutated(const Decl * Dec)30 bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; } 31 const Stmt *findMutation(const Expr *Exp); 32 const Stmt *findMutation(const Decl *Dec); 33 isPointeeMutated(const Expr * Exp)34 bool isPointeeMutated(const Expr *Exp) { 35 return findPointeeMutation(Exp) != nullptr; 36 } isPointeeMutated(const Decl * Dec)37 bool isPointeeMutated(const Decl *Dec) { 38 return findPointeeMutation(Dec) != nullptr; 39 } 40 const Stmt *findPointeeMutation(const Expr *Exp); 41 const Stmt *findPointeeMutation(const Decl *Dec); 42 43 private: 44 using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *); 45 using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>; 46 47 const Stmt *findMutationMemoized(const Expr *Exp, 48 llvm::ArrayRef<MutationFinder> Finders, 49 ResultMap &MemoizedResults); 50 const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder); 51 52 bool isUnevaluated(const Expr *Exp); 53 54 const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 55 const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 56 const Stmt * 57 findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 58 const Stmt * 59 findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 60 61 const Stmt *findDirectMutation(const Expr *Exp); 62 const Stmt *findMemberMutation(const Expr *Exp); 63 const Stmt *findArrayElementMutation(const Expr *Exp); 64 const Stmt *findCastMutation(const Expr *Exp); 65 const Stmt *findRangeLoopMutation(const Expr *Exp); 66 const Stmt *findReferenceMutation(const Expr *Exp); 67 const Stmt *findFunctionArgMutation(const Expr *Exp); 68 69 const Stmt &Stm; 70 ASTContext &Context; 71 llvm::DenseMap<const FunctionDecl *, 72 std::unique_ptr<FunctionParmMutationAnalyzer>> 73 FuncParmAnalyzer; 74 ResultMap Results; 75 ResultMap PointeeResults; 76 }; 77 78 // A convenient wrapper around ExprMutationAnalyzer for analyzing function 79 // params. 80 class FunctionParmMutationAnalyzer { 81 public: 82 FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context); 83 isMutated(const ParmVarDecl * Parm)84 bool isMutated(const ParmVarDecl *Parm) { 85 return findMutation(Parm) != nullptr; 86 } 87 const Stmt *findMutation(const ParmVarDecl *Parm); 88 89 private: 90 ExprMutationAnalyzer BodyAnalyzer; 91 llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results; 92 }; 93 94 } // namespace clang 95 96 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H 97