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 static bool isUnevaluated(const Stmt *Smt, const Stmt &Stm, 42 ASTContext &Context); 43 44 private: 45 using MutationFinder = const Stmt *(ExprMutationAnalyzer::*)(const Expr *); 46 using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>; 47 48 const Stmt *findMutationMemoized(const Expr *Exp, 49 llvm::ArrayRef<MutationFinder> Finders, 50 ResultMap &MemoizedResults); 51 const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder); 52 53 bool isUnevaluated(const Expr *Exp); 54 55 const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 56 const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 57 const Stmt * 58 findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 59 const Stmt * 60 findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches); 61 62 const Stmt *findDirectMutation(const Expr *Exp); 63 const Stmt *findMemberMutation(const Expr *Exp); 64 const Stmt *findArrayElementMutation(const Expr *Exp); 65 const Stmt *findCastMutation(const Expr *Exp); 66 const Stmt *findRangeLoopMutation(const Expr *Exp); 67 const Stmt *findReferenceMutation(const Expr *Exp); 68 const Stmt *findFunctionArgMutation(const Expr *Exp); 69 70 const Stmt &Stm; 71 ASTContext &Context; 72 llvm::DenseMap<const FunctionDecl *, 73 std::unique_ptr<FunctionParmMutationAnalyzer>> 74 FuncParmAnalyzer; 75 ResultMap Results; 76 ResultMap PointeeResults; 77 }; 78 79 // A convenient wrapper around ExprMutationAnalyzer for analyzing function 80 // params. 81 class FunctionParmMutationAnalyzer { 82 public: 83 FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context); 84 85 bool isMutated(const ParmVarDecl *Parm) { 86 return findMutation(Parm) != nullptr; 87 } 88 const Stmt *findMutation(const ParmVarDecl *Parm); 89 90 private: 91 ExprMutationAnalyzer BodyAnalyzer; 92 llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results; 93 }; 94 95 } // namespace clang 96 97 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H 98