8
8
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
9
9
#define LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
10
10
11
- #include < type_traits>
12
-
13
- #include " clang/AST/AST.h"
14
11
#include " clang/ASTMatchers/ASTMatchers.h"
15
12
#include " llvm/ADT/DenseMap.h"
13
+ #include < memory>
16
14
17
15
namespace clang {
18
16
@@ -21,75 +19,127 @@ class FunctionParmMutationAnalyzer;
21
19
// / Analyzes whether any mutative operations are applied to an expression within
22
20
// / a given statement.
23
21
class ExprMutationAnalyzer {
22
+ friend class FunctionParmMutationAnalyzer ;
23
+
24
24
public:
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
+
25
83
ExprMutationAnalyzer (const Stmt &Stm, ASTContext &Context)
26
- : Stm(Stm ), Context( Context) {}
84
+ : Memorized( ), A(Stm, Context, Memorized ) {}
27
85
28
86
bool isMutated (const Expr *Exp) { return findMutation (Exp) != nullptr ; }
29
87
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); }
32
90
33
91
bool isPointeeMutated (const Expr *Exp) {
34
92
return findPointeeMutation (Exp) != nullptr ;
35
93
}
36
94
bool isPointeeMutated (const Decl *Dec) {
37
95
return findPointeeMutation (Dec) != nullptr ;
38
96
}
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
+
41
104
static bool isUnevaluated (const Stmt *Smt, const Stmt &Stm,
42
- ASTContext &Context);
105
+ ASTContext &Context) {
106
+ return Analyzer::isUnevaluated (Smt, Stm, Context);
107
+ }
43
108
44
109
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;
110
+ Memoized Memorized;
111
+ Analyzer A;
77
112
};
78
113
79
114
// A convenient wrapper around ExprMutationAnalyzer for analyzing function
80
115
// params.
81
116
class FunctionParmMutationAnalyzer {
82
117
public:
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
+ }
84
131
85
132
bool isMutated (const ParmVarDecl *Parm) {
86
133
return findMutation (Parm) != nullptr ;
87
134
}
88
135
const Stmt *findMutation (const ParmVarDecl *Parm);
89
136
90
137
private:
91
- ExprMutationAnalyzer BodyAnalyzer;
138
+ ExprMutationAnalyzer::Analyzer BodyAnalyzer;
92
139
llvm::DenseMap<const ParmVarDecl *, const Stmt *> Results;
140
+
141
+ FunctionParmMutationAnalyzer (const FunctionDecl &Func, ASTContext &Context,
142
+ ExprMutationAnalyzer::Memoized &Memorized);
93
143
};
94
144
95
145
} // namespace clang
0 commit comments