1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines CheckerContext that provides contextual info for
// path-sensitive checkers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
namespace clang {
namespace ento {
class CheckerContext {
ExprEngine &Eng;
ExplodedNode *Pred;
const ProgramPoint Location;
NodeBuilder &NB;
public:
CheckerContext(NodeBuilder &builder,
ExprEngine &eng,
ExplodedNode *pred,
const ProgramPoint &loc)
: Eng(eng),
Pred(pred),
Location(loc),
NB(builder) {
assert(Pred->getState() &&
"We should not call the checkers on an empty state.");
}
AnalysisManager &getAnalysisManager() {
return Eng.getAnalysisManager();
}
ConstraintManager &getConstraintManager() {
return Eng.getConstraintManager();
}
StoreManager &getStoreManager() {
return Eng.getStoreManager();
}
/// \brief Returns the previous node in the exploded graph, which includes
/// the state of the program before the checker ran. Note, checkers should
/// not retain the node in their state since the nodes might get invalidated.
ExplodedNode *getPredecessor() { return Pred; }
const ProgramState *getState() const { return Pred->getState(); }
/// \brief Returns the number of times the current block has been visited
/// along the analyzed path.
unsigned getCurrentBlockCount() const {
return NB.getContext().getCurrentBlockCount();
}
ASTContext &getASTContext() {
return Eng.getContext();
}
const LocationContext *getLocationContext() const {
return Pred->getLocationContext();
}
BugReporter &getBugReporter() {
return Eng.getBugReporter();
}
SourceManager &getSourceManager() {
return getBugReporter().getSourceManager();
}
SValBuilder &getSValBuilder() {
return Eng.getSValBuilder();
}
SymbolManager &getSymbolManager() {
return getSValBuilder().getSymbolManager();
}
bool isObjCGCEnabled() const {
return Eng.isObjCGCEnabled();
}
ProgramStateManager &getStateManager() {
return Eng.getStateManager();
}
AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
return Pred->getLocationContext()->getAnalysisDeclContext();
}
/// \brief Generates a new transition in the program state graph
/// (ExplodedGraph). Uses the default CheckerContext predecessor node.
///
/// @param State The state of the generated node.
/// @param Tag The tag is used to uniquely identify the creation site. If no
/// tag is specified, a default tag, unique to the given checker,
/// will be used. Tags are used to prevent states generated at
/// different sites from caching out.
ExplodedNode *addTransition(const ProgramState *State,
const ProgramPointTag *Tag = 0) {
return addTransitionImpl(State, false, 0, Tag);
}
/// \brief Generates a default transition (containing checker tag but no
/// checker state changes).
ExplodedNode *addTransition() {
return addTransition(getState());
}
/// \brief Generates a new transition with the given predecessor.
/// Allows checkers to generate a chain of nodes.
///
/// @param State The state of the generated node.
/// @param Pred The transition will be generated from the specified Pred node
/// to the newly generated node.
/// @param Tag The tag to uniquely identify the creation site.
/// @param IsSink Mark the new node as sink, which will stop exploration of
/// the given path.
ExplodedNode *addTransition(const ProgramState *State,
ExplodedNode *Pred,
const ProgramPointTag *Tag = 0,
bool IsSink = false) {
return addTransitionImpl(State, IsSink, Pred, Tag);
}
/// \brief Generate a sink node. Generating sink stops exploration of the
/// given path.
ExplodedNode *generateSink(const ProgramState *state = 0) {
return addTransitionImpl(state ? state : getState(), true);
}
/// \brief Emit the diagnostics report.
void EmitReport(BugReport *R) {
Eng.getBugReporter().EmitReport(R);
}
/// \brief Get the declaration of the called function (path-sensitive).
const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
/// \brief Get the name of the called function (path-sensitive).
StringRef getCalleeName(const FunctionDecl *FunDecl) const;
/// \brief Get the name of the called function (path-sensitive).
StringRef getCalleeName(const CallExpr *CE) const {
const FunctionDecl *FunDecl = getCalleeDecl(CE);
return getCalleeName(FunDecl);
}
/// Given a function declaration and a name checks if this is a C lib
/// function with the given name.
bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name);
private:
ExplodedNode *addTransitionImpl(const ProgramState *State,
bool MarkAsSink,
ExplodedNode *P = 0,
const ProgramPointTag *Tag = 0) {
assert(State);
if (State == Pred->getState() && !Tag && !MarkAsSink)
return Pred;
ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location,
State,
P ? P : Pred, MarkAsSink);
return node;
}
};
} // end GR namespace
} // end clang namespace
#endif
|