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