File indexing completed on 2026-05-10 08:36:23
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
0009 #define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
0010
0011 #include "clang/ASTMatchers/ASTMatchers.h"
0012 #include "llvm/ADT/DenseMap.h"
0013 #include <memory>
0014
0015 namespace clang {
0016
0017 class FunctionParmMutationAnalyzer;
0018
0019
0020
0021 class ExprMutationAnalyzer {
0022 friend class FunctionParmMutationAnalyzer;
0023
0024 public:
0025 struct Memoized {
0026 using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
0027 using FunctionParaAnalyzerMap =
0028 llvm::SmallDenseMap<const FunctionDecl *,
0029 std::unique_ptr<FunctionParmMutationAnalyzer>>;
0030
0031 ResultMap Results;
0032 ResultMap PointeeResults;
0033 FunctionParaAnalyzerMap FuncParmAnalyzer;
0034
0035 void clear() {
0036 Results.clear();
0037 PointeeResults.clear();
0038 FuncParmAnalyzer.clear();
0039 }
0040 };
0041 struct Analyzer {
0042 Analyzer(const Stmt &Stm, ASTContext &Context, Memoized &Memorized)
0043 : Stm(Stm), Context(Context), Memorized(Memorized) {}
0044
0045 const Stmt *findMutation(const Expr *Exp);
0046 const Stmt *findMutation(const Decl *Dec);
0047
0048 const Stmt *findPointeeMutation(const Expr *Exp);
0049 const Stmt *findPointeeMutation(const Decl *Dec);
0050
0051 private:
0052 using MutationFinder = const Stmt *(Analyzer::*)(const Expr *);
0053
0054 const Stmt *findMutationMemoized(const Expr *Exp,
0055 llvm::ArrayRef<MutationFinder> Finders,
0056 Memoized::ResultMap &MemoizedResults);
0057 const Stmt *tryEachDeclRef(const Decl *Dec, MutationFinder Finder);
0058
0059 const Stmt *findExprMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0060 const Stmt *findDeclMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0061 const Stmt *
0062 findExprPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0063 const Stmt *
0064 findDeclPointeeMutation(ArrayRef<ast_matchers::BoundNodes> Matches);
0065
0066 const Stmt *findDirectMutation(const Expr *Exp);
0067 const Stmt *findMemberMutation(const Expr *Exp);
0068 const Stmt *findArrayElementMutation(const Expr *Exp);
0069 const Stmt *findCastMutation(const Expr *Exp);
0070 const Stmt *findRangeLoopMutation(const Expr *Exp);
0071 const Stmt *findReferenceMutation(const Expr *Exp);
0072 const Stmt *findFunctionArgMutation(const Expr *Exp);
0073
0074 const Stmt *findPointeeValueMutation(const Expr *Exp);
0075 const Stmt *findPointeeMemberMutation(const Expr *Exp);
0076 const Stmt *findPointeeToNonConst(const Expr *Exp);
0077
0078 const Stmt &Stm;
0079 ASTContext &Context;
0080 Memoized &Memorized;
0081 };
0082
0083 ExprMutationAnalyzer(const Stmt &Stm, ASTContext &Context)
0084 : Memorized(), A(Stm, Context, Memorized) {}
0085
0086
0087
0088 static bool isUnevaluated(const Stmt *Stm, ASTContext &Context);
0089
0090 bool isMutated(const Expr *Exp) { return findMutation(Exp) != nullptr; }
0091 bool isMutated(const Decl *Dec) { return findMutation(Dec) != nullptr; }
0092 const Stmt *findMutation(const Expr *Exp) { return A.findMutation(Exp); }
0093 const Stmt *findMutation(const Decl *Dec) { return A.findMutation(Dec); }
0094
0095 bool isPointeeMutated(const Expr *Exp) {
0096 return findPointeeMutation(Exp) != nullptr;
0097 }
0098 bool isPointeeMutated(const Decl *Dec) {
0099 return findPointeeMutation(Dec) != nullptr;
0100 }
0101 const Stmt *findPointeeMutation(const Expr *Exp) {
0102 return A.findPointeeMutation(Exp);
0103 }
0104 const Stmt *findPointeeMutation(const Decl *Dec) {
0105 return A.findPointeeMutation(Dec);
0106 }
0107
0108 private:
0109 Memoized Memorized;
0110 Analyzer A;
0111 };
0112
0113
0114
0115 class FunctionParmMutationAnalyzer {
0116 public:
0117 static FunctionParmMutationAnalyzer *
0118 getFunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context,
0119 ExprMutationAnalyzer::Memoized &Memorized) {
0120 auto it = Memorized.FuncParmAnalyzer.find(&Func);
0121 if (it == Memorized.FuncParmAnalyzer.end()) {
0122
0123
0124
0125
0126 it =
0127 Memorized.FuncParmAnalyzer
0128 .try_emplace(&Func, std::unique_ptr<FunctionParmMutationAnalyzer>(
0129 new FunctionParmMutationAnalyzer(
0130 Func, Context, Memorized)))
0131 .first;
0132 }
0133 return it->getSecond().get();
0134 }
0135
0136 bool isMutated(const ParmVarDecl *Parm) {
0137 return findMutation(Parm) != nullptr;
0138 }
0139 const Stmt *findMutation(const ParmVarDecl *Parm);
0140
0141 private:
0142 ExprMutationAnalyzer::Analyzer BodyAnalyzer;
0143 llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
0144
0145 FunctionParmMutationAnalyzer(const FunctionDecl &Func, ASTContext &Context,
0146 ExprMutationAnalyzer::Memoized &Memorized);
0147 };
0148
0149 }
0150
0151 #endif