88#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
99#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
1010
11- #include < type_traits>
12-
13- #include " clang/AST/AST.h"
1411#include " clang/ASTMatchers/ASTMatchers.h"
1512#include " llvm/ADT/DenseMap.h"
13+ #include < memory>
1614
1715namespace clang {
1816
@@ -21,75 +19,127 @@ class FunctionParmMutationAnalyzer;
2119// / Analyzes whether any mutative operations are applied to an expression within
2220// / a given statement.
2321class ExprMutationAnalyzer {
22+ friend class FunctionParmMutationAnalyzer ;
23+
2424public:
25+ struct Memoized {
26+ using ResultMap = llvm::DenseMap<const Expr *, const Stmt *>;
27+ using FunctionParaAnalyzerMap =
28+ llvm::SmallDenseMap<const FunctionDecl *,
29+ std::unique_ptr<FunctionParmMutationAnalyzer>>;
30+
31+ ResultMap Results;
32+ ResultMap PointeeResults;
33+ FunctionParaAnalyzerMap FuncParmAnalyzer;
34+
35+ void clear () {
36+ Results.clear ();
37+ PointeeResults.clear ();
38+ FuncParmAnalyzer.clear ();
39+ }
40+ };
41+ struct Analyzer {
42+ Analyzer (const Stmt &Stm, ASTContext &Context, Memoized &Memorized)
43+ : Stm(Stm), Context(Context), Memorized(Memorized) {}
44+
45+ const Stmt *findMutation (const Expr *Exp);
46+ const Stmt *findMutation (const Decl *Dec);
47+
48+ const Stmt *findPointeeMutation (const Expr *Exp);
49+ const Stmt *findPointeeMutation (const Decl *Dec);
50+ static bool isUnevaluated (const Stmt *Smt, const Stmt &Stm,
51+ ASTContext &Context);
52+
53+ private:
54+ using MutationFinder = const Stmt *(Analyzer::*)(const Expr *);
55+
56+ const Stmt *findMutationMemoized (const Expr *Exp,
57+ llvm::ArrayRef<MutationFinder> Finders,
58+ Memoized::ResultMap &MemoizedResults);
59+ const Stmt *tryEachDeclRef (const Decl *Dec, MutationFinder Finder);
60+
61+ bool isUnevaluated (const Expr *Exp);
62+
63+ const Stmt *findExprMutation (ArrayRef<ast_matchers::BoundNodes> Matches);
64+ const Stmt *findDeclMutation (ArrayRef<ast_matchers::BoundNodes> Matches);
65+ const Stmt *
66+ findExprPointeeMutation (ArrayRef<ast_matchers::BoundNodes> Matches);
67+ const Stmt *
68+ findDeclPointeeMutation (ArrayRef<ast_matchers::BoundNodes> Matches);
69+
70+ const Stmt *findDirectMutation (const Expr *Exp);
71+ const Stmt *findMemberMutation (const Expr *Exp);
72+ const Stmt *findArrayElementMutation (const Expr *Exp);
73+ const Stmt *findCastMutation (const Expr *Exp);
74+ const Stmt *findRangeLoopMutation (const Expr *Exp);
75+ const Stmt *findReferenceMutation (const Expr *Exp);
76+ const Stmt *findFunctionArgMutation (const Expr *Exp);
77+
78+ const Stmt &Stm;
79+ ASTContext &Context;
80+ Memoized &Memorized;
81+ };
82+
2583 ExprMutationAnalyzer (const Stmt &Stm, ASTContext &Context)
26- : Stm(Stm ), Context( Context) {}
84+ : Memorized( ), A(Stm, Context, Memorized ) {}
2785
2886 bool isMutated (const Expr *Exp) { return findMutation (Exp) != nullptr ; }
2987 bool isMutated (const Decl *Dec) { return findMutation (Dec) != nullptr ; }
30- const Stmt *findMutation (const Expr *Exp);
31- const Stmt *findMutation (const Decl *Dec);
88+ const Stmt *findMutation (const Expr *Exp) { return A. findMutation (Exp); }
89+ const Stmt *findMutation (const Decl *Dec) { return A. findMutation (Dec); }
3290
3391 bool isPointeeMutated (const Expr *Exp) {
3492 return findPointeeMutation (Exp) != nullptr ;
3593 }
3694 bool isPointeeMutated (const Decl *Dec) {
3795 return findPointeeMutation (Dec) != nullptr ;
3896 }
39- const Stmt *findPointeeMutation (const Expr *Exp);
40- const Stmt *findPointeeMutation (const Decl *Dec);
97+ const Stmt *findPointeeMutation (const Expr *Exp) {
98+ return A.findPointeeMutation (Exp);
99+ }
100+ const Stmt *findPointeeMutation (const Decl *Dec) {
101+ return A.findPointeeMutation (Dec);
102+ }
103+
41104 static bool isUnevaluated (const Stmt *Smt, const Stmt &Stm,
42- ASTContext &Context);
105+ ASTContext &Context) {
106+ return Analyzer::isUnevaluated (Smt, Stm, Context);
107+ }
43108
44109private:
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;
110+ Memoized Memorized;
111+ Analyzer A;
77112};
78113
79114// A convenient wrapper around ExprMutationAnalyzer for analyzing function
80115// params.
81116class FunctionParmMutationAnalyzer {
82117public:
83- FunctionParmMutationAnalyzer (const FunctionDecl &Func, ASTContext &Context);
118+ static FunctionParmMutationAnalyzer *
119+ getFunctionParmMutationAnalyzer (const FunctionDecl &Func, ASTContext &Context,
120+ ExprMutationAnalyzer::Memoized &Memorized) {
121+ auto it = Memorized.FuncParmAnalyzer .find (&Func);
122+ if (it == Memorized.FuncParmAnalyzer .end ())
123+ it =
124+ Memorized.FuncParmAnalyzer
125+ .try_emplace (&Func, std::unique_ptr<FunctionParmMutationAnalyzer>(
126+ new FunctionParmMutationAnalyzer (
127+ Func, Context, Memorized)))
128+ .first ;
129+ return it->getSecond ().get ();
130+ }
84131
85132 bool isMutated (const ParmVarDecl *Parm) {
86133 return findMutation (Parm) != nullptr ;
87134 }
88135 const Stmt *findMutation (const ParmVarDecl *Parm);
89136
90137private:
91- ExprMutationAnalyzer BodyAnalyzer;
138+ ExprMutationAnalyzer::Analyzer BodyAnalyzer;
92139 llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
140+
141+ FunctionParmMutationAnalyzer (const FunctionDecl &Func, ASTContext &Context,
142+ ExprMutationAnalyzer::Memoized &Memorized);
93143};
94144
95145} // namespace clang
0 commit comments