Bug Summary

File:tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
Warning:line 102, column 29
Access to field 'CurrentState' results in a dereference of a null pointer (loaded from variable 'Req')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MPIBugReporter.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn325118/build-llvm/tools/clang/lib/StaticAnalyzer/Checkers -I /build/llvm-toolchain-snapshot-7~svn325118/tools/clang/lib/StaticAnalyzer/Checkers -I /build/llvm-toolchain-snapshot-7~svn325118/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn325118/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn325118/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn325118/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn325118/build-llvm/tools/clang/lib/StaticAnalyzer/Checkers -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-02-14-150435-17243-1 -x c++ /build/llvm-toolchain-snapshot-7~svn325118/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp

/build/llvm-toolchain-snapshot-7~svn325118/tools/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp

1//===-- MPIBugReporter.cpp - bug reporter -----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// This file defines prefabricated reports which are emitted in
12/// case of MPI related bugs, detected by path-sensitive analysis.
13///
14//===----------------------------------------------------------------------===//
15
16#include "MPIBugReporter.h"
17#include "MPIChecker.h"
18#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
19
20namespace clang {
21namespace ento {
22namespace mpi {
23
24void MPIBugReporter::reportDoubleNonblocking(
25 const CallEvent &MPICallEvent, const ento::mpi::Request &Req,
26 const MemRegion *const RequestRegion,
27 const ExplodedNode *const ExplNode,
28 BugReporter &BReporter) const {
29
30 std::string ErrorText;
31 ErrorText = "Double nonblocking on request " +
32 RequestRegion->getDescriptiveName() + ". ";
33
34 auto Report = llvm::make_unique<BugReport>(*DoubleNonblockingBugType,
35 ErrorText, ExplNode);
36
37 Report->addRange(MPICallEvent.getSourceRange());
38 SourceRange Range = RequestRegion->sourceRange();
39
40 if (Range.isValid())
41 Report->addRange(Range);
42
43 Report->addVisitor(llvm::make_unique<RequestNodeVisitor>(
44 RequestRegion, "Request is previously used by nonblocking call here. "));
45 Report->markInteresting(RequestRegion);
46
47 BReporter.emitReport(std::move(Report));
48}
49
50void MPIBugReporter::reportMissingWait(
51 const ento::mpi::Request &Req, const MemRegion *const RequestRegion,
52 const ExplodedNode *const ExplNode,
53 BugReporter &BReporter) const {
54 std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
55 " has no matching wait. "};
56
57 auto Report =
58 llvm::make_unique<BugReport>(*MissingWaitBugType, ErrorText, ExplNode);
59
60 SourceRange Range = RequestRegion->sourceRange();
61 if (Range.isValid())
62 Report->addRange(Range);
63 Report->addVisitor(llvm::make_unique<RequestNodeVisitor>(
64 RequestRegion, "Request is previously used by nonblocking call here. "));
65 Report->markInteresting(RequestRegion);
66
67 BReporter.emitReport(std::move(Report));
68}
69
70void MPIBugReporter::reportUnmatchedWait(
71 const CallEvent &CE, const clang::ento::MemRegion *const RequestRegion,
72 const ExplodedNode *const ExplNode,
73 BugReporter &BReporter) const {
74 std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
75 " has no matching nonblocking call. "};
76
77 auto Report =
78 llvm::make_unique<BugReport>(*UnmatchedWaitBugType, ErrorText, ExplNode);
79
80 Report->addRange(CE.getSourceRange());
81 SourceRange Range = RequestRegion->sourceRange();
82 if (Range.isValid())
83 Report->addRange(Range);
84
85 BReporter.emitReport(std::move(Report));
86}
87
88std::shared_ptr<PathDiagnosticPiece>
89MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
90 const ExplodedNode *PrevN,
91 BugReporterContext &BRC,
92 BugReport &BR) {
93
94 if (IsNodeFound)
1
Assuming the condition is false
2
Taking false branch
95 return nullptr;
96
97 const Request *const Req = N->getState()->get<RequestMap>(RequestRegion);
3
Calling 'ProgramState::get'
12
Returning from 'ProgramState::get'
13
'Req' initialized here
98 const Request *const PrevReq =
99 PrevN->getState()->get<RequestMap>(RequestRegion);
100
101 // Check if request was previously unused or in a different state.
102 if ((Req && !PrevReq) || (Req->CurrentState != PrevReq->CurrentState)) {
14
Assuming 'Req' is null
15
Access to field 'CurrentState' results in a dereference of a null pointer (loaded from variable 'Req')
103 IsNodeFound = true;
104
105 ProgramPoint P = PrevN->getLocation();
106 PathDiagnosticLocation L =
107 PathDiagnosticLocation::create(P, BRC.getSourceManager());
108
109 return std::make_shared<PathDiagnosticEventPiece>(L, ErrorText);
110 }
111
112 return nullptr;
113}
114
115} // end of namespace: mpi
116} // end of namespace: ento
117} // end of namespace: clang

/build/llvm-toolchain-snapshot-7~svn325118/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h

1//== ProgramState.h - Path-sensitive "State" for tracking values -*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the state of the program along the analysisa path.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
15#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
16
17#include "clang/Basic/LLVM.h"
18#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
21#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
22#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
23#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
24#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
25#include "llvm/ADT/FoldingSet.h"
26#include "llvm/ADT/ImmutableMap.h"
27#include "llvm/Support/Allocator.h"
28#include <utility>
29
30namespace llvm {
31class APSInt;
32}
33
34namespace clang {
35class ASTContext;
36
37namespace ento {
38
39class CallEvent;
40class CallEventManager;
41
42typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)(
43 ProgramStateManager &, SubEngine *);
44typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)(
45 ProgramStateManager &);
46typedef llvm::ImmutableMap<const SubRegion*, TaintTagType> TaintedSubRegions;
47
48//===----------------------------------------------------------------------===//
49// ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState.
50//===----------------------------------------------------------------------===//
51
52template <typename T> struct ProgramStatePartialTrait;
53
54template <typename T> struct ProgramStateTrait {
55 typedef typename T::data_type data_type;
56 static inline void *MakeVoidPtr(data_type D) { return (void*) D; }
57 static inline data_type MakeData(void *const* P) {
58 return P ? (data_type) *P : (data_type) 0;
59 }
60};
61
62/// \class ProgramState
63/// ProgramState - This class encapsulates:
64///
65/// 1. A mapping from expressions to values (Environment)
66/// 2. A mapping from locations to values (Store)
67/// 3. Constraints on symbolic values (GenericDataMap)
68///
69/// Together these represent the "abstract state" of a program.
70///
71/// ProgramState is intended to be used as a functional object; that is,
72/// once it is created and made "persistent" in a FoldingSet, its
73/// values will never change.
74class ProgramState : public llvm::FoldingSetNode {
75public:
76 typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
77 typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
78
79private:
80 void operator=(const ProgramState& R) = delete;
81
82 friend class ProgramStateManager;
83 friend class ExplodedGraph;
84 friend class ExplodedNode;
85
86 ProgramStateManager *stateMgr;
87 Environment Env; // Maps a Stmt to its current SVal.
88 Store store; // Maps a location to its current value.
89 GenericDataMap GDM; // Custom data stored by a client of this class.
90 unsigned refCount;
91
92 /// makeWithStore - Return a ProgramState with the same values as the current
93 /// state with the exception of using the specified Store.
94 ProgramStateRef makeWithStore(const StoreRef &store) const;
95
96 void setStore(const StoreRef &storeRef);
97
98public:
99 /// This ctor is used when creating the first ProgramState object.
100 ProgramState(ProgramStateManager *mgr, const Environment& env,
101 StoreRef st, GenericDataMap gdm);
102
103 /// Copy ctor - We must explicitly define this or else the "Next" ptr
104 /// in FoldingSetNode will also get copied.
105 ProgramState(const ProgramState &RHS);
106
107 ~ProgramState();
108
109 /// Return the ProgramStateManager associated with this state.
110 ProgramStateManager &getStateManager() const {
111 return *stateMgr;
112 }
113
114 /// Return the ConstraintManager.
115 ConstraintManager &getConstraintManager() const;
116
117 /// getEnvironment - Return the environment associated with this state.
118 /// The environment is the mapping from expressions to values.
119 const Environment& getEnvironment() const { return Env; }
120
121 /// Return the store associated with this state. The store
122 /// is a mapping from locations to values.
123 Store getStore() const { return store; }
124
125
126 /// getGDM - Return the generic data map associated with this state.
127 GenericDataMap getGDM() const { return GDM; }
128
129 void setGDM(GenericDataMap gdm) { GDM = gdm; }
130
131 /// Profile - Profile the contents of a ProgramState object for use in a
132 /// FoldingSet. Two ProgramState objects are considered equal if they
133 /// have the same Environment, Store, and GenericDataMap.
134 static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *V) {
135 V->Env.Profile(ID);
136 ID.AddPointer(V->store);
137 V->GDM.Profile(ID);
138 }
139
140 /// Profile - Used to profile the contents of this object for inclusion
141 /// in a FoldingSet.
142 void Profile(llvm::FoldingSetNodeID& ID) const {
143 Profile(ID, this);
144 }
145
146 BasicValueFactory &getBasicVals() const;
147 SymbolManager &getSymbolManager() const;
148
149 //==---------------------------------------------------------------------==//
150 // Constraints on values.
151 //==---------------------------------------------------------------------==//
152 //
153 // Each ProgramState records constraints on symbolic values. These constraints
154 // are managed using the ConstraintManager associated with a ProgramStateManager.
155 // As constraints gradually accrue on symbolic values, added constraints
156 // may conflict and indicate that a state is infeasible (as no real values
157 // could satisfy all the constraints). This is the principal mechanism
158 // for modeling path-sensitivity in ExprEngine/ProgramState.
159 //
160 // Various "assume" methods form the interface for adding constraints to
161 // symbolic values. A call to 'assume' indicates an assumption being placed
162 // on one or symbolic values. 'assume' methods take the following inputs:
163 //
164 // (1) A ProgramState object representing the current state.
165 //
166 // (2) The assumed constraint (which is specific to a given "assume" method).
167 //
168 // (3) A binary value "Assumption" that indicates whether the constraint is
169 // assumed to be true or false.
170 //
171 // The output of "assume*" is a new ProgramState object with the added constraints.
172 // If no new state is feasible, NULL is returned.
173 //
174
175 /// Assumes that the value of \p cond is zero (if \p assumption is "false")
176 /// or non-zero (if \p assumption is "true").
177 ///
178 /// This returns a new state with the added constraint on \p cond.
179 /// If no new state is feasible, NULL is returned.
180 ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const;
181
182 /// Assumes both "true" and "false" for \p cond, and returns both
183 /// corresponding states (respectively).
184 ///
185 /// This is more efficient than calling assume() twice. Note that one (but not
186 /// both) of the returned states may be NULL.
187 std::pair<ProgramStateRef, ProgramStateRef>
188 assume(DefinedOrUnknownSVal cond) const;
189
190 ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx,
191 DefinedOrUnknownSVal upperBound,
192 bool assumption,
193 QualType IndexType = QualType()) const;
194
195 /// Assumes that the value of \p Val is bounded with [\p From; \p To]
196 /// (if \p assumption is "true") or it is fully out of this range
197 /// (if \p assumption is "false").
198 ///
199 /// This returns a new state with the added constraint on \p cond.
200 /// If no new state is feasible, NULL is returned.
201 ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val,
202 const llvm::APSInt &From,
203 const llvm::APSInt &To,
204 bool assumption) const;
205
206 /// Assumes given range both "true" and "false" for \p Val, and returns both
207 /// corresponding states (respectively).
208 ///
209 /// This is more efficient than calling assume() twice. Note that one (but not
210 /// both) of the returned states may be NULL.
211 std::pair<ProgramStateRef, ProgramStateRef>
212 assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
213 const llvm::APSInt &To) const;
214
215 /// \brief Check if the given SVal is not constrained to zero and is not
216 /// a zero constant.
217 ConditionTruthVal isNonNull(SVal V) const;
218
219 /// \brief Check if the given SVal is constrained to zero or is a zero
220 /// constant.
221 ConditionTruthVal isNull(SVal V) const;
222
223 /// \return Whether values \p Lhs and \p Rhs are equal.
224 ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const;
225
226 /// Utility method for getting regions.
227 const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
228
229 //==---------------------------------------------------------------------==//
230 // Binding and retrieving values to/from the environment and symbolic store.
231 //==---------------------------------------------------------------------==//
232
233 /// Create a new state by binding the value 'V' to the statement 'S' in the
234 /// state's environment.
235 ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx,
236 SVal V, bool Invalidate = true) const;
237
238 ProgramStateRef bindLoc(Loc location,
239 SVal V,
240 const LocationContext *LCtx,
241 bool notifyChanges = true) const;
242
243 ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const;
244
245 ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const;
246
247 ProgramStateRef killBinding(Loc LV) const;
248
249 /// \brief Returns the state with bindings for the given regions
250 /// cleared from the store.
251 ///
252 /// Optionally invalidates global regions as well.
253 ///
254 /// \param Regions the set of regions to be invalidated.
255 /// \param E the expression that caused the invalidation.
256 /// \param BlockCount The number of times the current basic block has been
257 // visited.
258 /// \param CausesPointerEscape the flag is set to true when
259 /// the invalidation entails escape of a symbol (representing a
260 /// pointer). For example, due to it being passed as an argument in a
261 /// call.
262 /// \param IS the set of invalidated symbols.
263 /// \param Call if non-null, the invalidated regions represent parameters to
264 /// the call and should be considered directly invalidated.
265 /// \param ITraits information about special handling for a particular
266 /// region/symbol.
267 ProgramStateRef
268 invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
269 unsigned BlockCount, const LocationContext *LCtx,
270 bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
271 const CallEvent *Call = nullptr,
272 RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
273
274 ProgramStateRef
275 invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
276 unsigned BlockCount, const LocationContext *LCtx,
277 bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
278 const CallEvent *Call = nullptr,
279 RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
280
281 /// enterStackFrame - Returns the state for entry to the given stack frame,
282 /// preserving the current state.
283 ProgramStateRef enterStackFrame(const CallEvent &Call,
284 const StackFrameContext *CalleeCtx) const;
285
286 /// Get the lvalue for a variable reference.
287 Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
288
289 Loc getLValue(const CompoundLiteralExpr *literal,
290 const LocationContext *LC) const;
291
292 /// Get the lvalue for an ivar reference.
293 SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
294
295 /// Get the lvalue for a field reference.
296 SVal getLValue(const FieldDecl *decl, SVal Base) const;
297
298 /// Get the lvalue for an indirect field reference.
299 SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const;
300
301 /// Get the lvalue for an array index.
302 SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
303
304 /// Returns the SVal bound to the statement 'S' in the state's environment.
305 SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
306
307 SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
308
309 /// \brief Return the value bound to the specified location.
310 /// Returns UnknownVal() if none found.
311 SVal getSVal(Loc LV, QualType T = QualType()) const;
312
313 /// Returns the "raw" SVal bound to LV before any value simplfication.
314 SVal getRawSVal(Loc LV, QualType T= QualType()) const;
315
316 /// \brief Return the value bound to the specified location.
317 /// Returns UnknownVal() if none found.
318 SVal getSVal(const MemRegion* R, QualType T = QualType()) const;
319
320 /// \brief Return the value bound to the specified location, assuming
321 /// that the value is a scalar integer or an enumeration or a pointer.
322 /// Returns UnknownVal() if none found or the region is not known to hold
323 /// a value of such type.
324 SVal getSValAsScalarOrLoc(const MemRegion *R) const;
325
326 /// \brief Visits the symbols reachable from the given SVal using the provided
327 /// SymbolVisitor.
328 ///
329 /// This is a convenience API. Consider using ScanReachableSymbols class
330 /// directly when making multiple scans on the same state with the same
331 /// visitor to avoid repeated initialization cost.
332 /// \sa ScanReachableSymbols
333 bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
334
335 /// \brief Visits the symbols reachable from the SVals in the given range
336 /// using the provided SymbolVisitor.
337 bool scanReachableSymbols(const SVal *I, const SVal *E,
338 SymbolVisitor &visitor) const;
339
340 /// \brief Visits the symbols reachable from the regions in the given
341 /// MemRegions range using the provided SymbolVisitor.
342 bool scanReachableSymbols(const MemRegion * const *I,
343 const MemRegion * const *E,
344 SymbolVisitor &visitor) const;
345
346 template <typename CB> CB scanReachableSymbols(SVal val) const;
347 template <typename CB> CB scanReachableSymbols(const SVal *beg,
348 const SVal *end) const;
349
350 template <typename CB> CB
351 scanReachableSymbols(const MemRegion * const *beg,
352 const MemRegion * const *end) const;
353
354 /// Create a new state in which the statement is marked as tainted.
355 ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx,
356 TaintTagType Kind = TaintTagGeneric) const;
357
358 /// Create a new state in which the value is marked as tainted.
359 ProgramStateRef addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const;
360
361 /// Create a new state in which the symbol is marked as tainted.
362 ProgramStateRef addTaint(SymbolRef S,
363 TaintTagType Kind = TaintTagGeneric) const;
364
365 /// Create a new state in which the region symbol is marked as tainted.
366 ProgramStateRef addTaint(const MemRegion *R,
367 TaintTagType Kind = TaintTagGeneric) const;
368
369 /// Create a new state in a which a sub-region of a given symbol is tainted.
370 /// This might be necessary when referring to regions that can not have an
371 /// individual symbol, e.g. if they are represented by the default binding of
372 /// a LazyCompoundVal.
373 ProgramStateRef addPartialTaint(SymbolRef ParentSym,
374 const SubRegion *SubRegion,
375 TaintTagType Kind = TaintTagGeneric) const;
376
377 /// Check if the statement is tainted in the current state.
378 bool isTainted(const Stmt *S, const LocationContext *LCtx,
379 TaintTagType Kind = TaintTagGeneric) const;
380 bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const;
381 bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
382 bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
383
384 //==---------------------------------------------------------------------==//
385 // Accessing the Generic Data Map (GDM).
386 //==---------------------------------------------------------------------==//
387
388 void *const* FindGDM(void *K) const;
389
390 template<typename T>
391 ProgramStateRef add(typename ProgramStateTrait<T>::key_type K) const;
392
393 template <typename T>
394 typename ProgramStateTrait<T>::data_type
395 get() const {
396 return ProgramStateTrait<T>::MakeData(FindGDM(ProgramStateTrait<T>::GDMIndex()));
397 }
398
399 template<typename T>
400 typename ProgramStateTrait<T>::lookup_type
401 get(typename ProgramStateTrait<T>::key_type key) const {
402 void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex());
4
Calling 'ProgramStateTrait::GDMIndex'
5
Returning from 'ProgramStateTrait::GDMIndex'
403 return ProgramStateTrait<T>::Lookup(ProgramStateTrait<T>::MakeData(d), key);
6
Calling 'ProgramStatePartialTrait::MakeData'
9
Returning from 'ProgramStatePartialTrait::MakeData'
10
Calling 'ProgramStatePartialTrait::Lookup'
11
Returning from 'ProgramStatePartialTrait::Lookup'
404 }
405
406 template <typename T>
407 typename ProgramStateTrait<T>::context_type get_context() const;
408
409
410 template<typename T>
411 ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K) const;
412
413 template<typename T>
414 ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K,
415 typename ProgramStateTrait<T>::context_type C) const;
416 template <typename T>
417 ProgramStateRef remove() const;
418
419 template<typename T>
420 ProgramStateRef set(typename ProgramStateTrait<T>::data_type D) const;
421
422 template<typename T>
423 ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
424 typename ProgramStateTrait<T>::value_type E) const;
425
426 template<typename T>
427 ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
428 typename ProgramStateTrait<T>::value_type E,
429 typename ProgramStateTrait<T>::context_type C) const;
430
431 template<typename T>
432 bool contains(typename ProgramStateTrait<T>::key_type key) const {
433 void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex());
434 return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key);
435 }
436
437 // Pretty-printing.
438 void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "",
439 const LocationContext *CurrentLC = nullptr) const;
440 void printDOT(raw_ostream &Out,
441 const LocationContext *CurrentLC = nullptr) const;
442 void printTaint(raw_ostream &Out, const char *nl = "\n",
443 const char *sep = "") const;
444
445 void dump() const;
446 void dumpTaint() const;
447
448private:
449 friend void ProgramStateRetain(const ProgramState *state);
450 friend void ProgramStateRelease(const ProgramState *state);
451
452 /// \sa invalidateValues()
453 /// \sa invalidateRegions()
454 ProgramStateRef
455 invalidateRegionsImpl(ArrayRef<SVal> Values,
456 const Expr *E, unsigned BlockCount,
457 const LocationContext *LCtx,
458 bool ResultsInSymbolEscape,
459 InvalidatedSymbols *IS,
460 RegionAndSymbolInvalidationTraits *HTraits,
461 const CallEvent *Call) const;
462};
463
464//===----------------------------------------------------------------------===//
465// ProgramStateManager - Factory object for ProgramStates.
466//===----------------------------------------------------------------------===//
467
468class ProgramStateManager {
469 friend class ProgramState;
470 friend void ProgramStateRelease(const ProgramState *state);
471private:
472 /// Eng - The SubEngine that owns this state manager.
473 SubEngine *Eng; /* Can be null. */
474
475 EnvironmentManager EnvMgr;
476 std::unique_ptr<StoreManager> StoreMgr;
477 std::unique_ptr<ConstraintManager> ConstraintMgr;
478
479 ProgramState::GenericDataMap::Factory GDMFactory;
480 TaintedSubRegions::Factory TSRFactory;
481
482 typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
483 GDMContextsTy GDMContexts;
484
485 /// StateSet - FoldingSet containing all the states created for analyzing
486 /// a particular function. This is used to unique states.
487 llvm::FoldingSet<ProgramState> StateSet;
488
489 /// Object that manages the data for all created SVals.
490 std::unique_ptr<SValBuilder> svalBuilder;
491
492 /// Manages memory for created CallEvents.
493 std::unique_ptr<CallEventManager> CallEventMgr;
494
495 /// A BumpPtrAllocator to allocate states.
496 llvm::BumpPtrAllocator &Alloc;
497
498 /// A vector of ProgramStates that we can reuse.
499 std::vector<ProgramState *> freeStates;
500
501public:
502 ProgramStateManager(ASTContext &Ctx,
503 StoreManagerCreator CreateStoreManager,
504 ConstraintManagerCreator CreateConstraintManager,
505 llvm::BumpPtrAllocator& alloc,
506 SubEngine *subeng);
507
508 ~ProgramStateManager();
509
510 ProgramStateRef getInitialState(const LocationContext *InitLoc);
511
512 ASTContext &getContext() { return svalBuilder->getContext(); }
513 const ASTContext &getContext() const { return svalBuilder->getContext(); }
514
515 BasicValueFactory &getBasicVals() {
516 return svalBuilder->getBasicValueFactory();
517 }
518
519 SValBuilder &getSValBuilder() {
520 return *svalBuilder;
521 }
522
523 SymbolManager &getSymbolManager() {
524 return svalBuilder->getSymbolManager();
525 }
526 const SymbolManager &getSymbolManager() const {
527 return svalBuilder->getSymbolManager();
528 }
529
530 llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
531
532 MemRegionManager& getRegionManager() {
533 return svalBuilder->getRegionManager();
534 }
535 const MemRegionManager& getRegionManager() const {
536 return svalBuilder->getRegionManager();
537 }
538
539 CallEventManager &getCallEventManager() { return *CallEventMgr; }
540
541 StoreManager& getStoreManager() { return *StoreMgr; }
542 ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
543 SubEngine* getOwningEngine() { return Eng; }
544
545 ProgramStateRef removeDeadBindings(ProgramStateRef St,
546 const StackFrameContext *LCtx,
547 SymbolReaper& SymReaper);
548
549public:
550
551 SVal ArrayToPointer(Loc Array, QualType ElementTy) {
552 return StoreMgr->ArrayToPointer(Array, ElementTy);
553 }
554
555 // Methods that manipulate the GDM.
556 ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data);
557 ProgramStateRef removeGDM(ProgramStateRef state, void *Key);
558
559 // Methods that query & manipulate the Store.
560
561 void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler& F) {
562 StoreMgr->iterBindings(state->getStore(), F);
563 }
564
565 ProgramStateRef getPersistentState(ProgramState &Impl);
566 ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState,
567 ProgramStateRef GDMState);
568
569 bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) {
570 return S1->Env == S2->Env;
571 }
572
573 bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) {
574 return S1->store == S2->store;
575 }
576
577 //==---------------------------------------------------------------------==//
578 // Generic Data Map methods.
579 //==---------------------------------------------------------------------==//
580 //
581 // ProgramStateManager and ProgramState support a "generic data map" that allows
582 // different clients of ProgramState objects to embed arbitrary data within a
583 // ProgramState object. The generic data map is essentially an immutable map
584 // from a "tag" (that acts as the "key" for a client) and opaque values.
585 // Tags/keys and values are simply void* values. The typical way that clients
586 // generate unique tags are by taking the address of a static variable.
587 // Clients are responsible for ensuring that data values referred to by a
588 // the data pointer are immutable (and thus are essentially purely functional
589 // data).
590 //
591 // The templated methods below use the ProgramStateTrait<T> class
592 // to resolve keys into the GDM and to return data values to clients.
593 //
594
595 // Trait based GDM dispatch.
596 template <typename T>
597 ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::data_type D) {
598 return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
599 ProgramStateTrait<T>::MakeVoidPtr(D));
600 }
601
602 template<typename T>
603 ProgramStateRef set(ProgramStateRef st,
604 typename ProgramStateTrait<T>::key_type K,
605 typename ProgramStateTrait<T>::value_type V,
606 typename ProgramStateTrait<T>::context_type C) {
607
608 return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
609 ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Set(st->get<T>(), K, V, C)));
610 }
611
612 template <typename T>
613 ProgramStateRef add(ProgramStateRef st,
614 typename ProgramStateTrait<T>::key_type K,
615 typename ProgramStateTrait<T>::context_type C) {
616 return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
617 ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Add(st->get<T>(), K, C)));
618 }
619
620 template <typename T>
621 ProgramStateRef remove(ProgramStateRef st,
622 typename ProgramStateTrait<T>::key_type K,
623 typename ProgramStateTrait<T>::context_type C) {
624
625 return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
626 ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Remove(st->get<T>(), K, C)));
627 }
628
629 template <typename T>
630 ProgramStateRef remove(ProgramStateRef st) {
631 return removeGDM(st, ProgramStateTrait<T>::GDMIndex());
632 }
633
634 void *FindGDMContext(void *index,
635 void *(*CreateContext)(llvm::BumpPtrAllocator&),
636 void (*DeleteContext)(void*));
637
638 template <typename T>
639 typename ProgramStateTrait<T>::context_type get_context() {
640 void *p = FindGDMContext(ProgramStateTrait<T>::GDMIndex(),
641 ProgramStateTrait<T>::CreateContext,
642 ProgramStateTrait<T>::DeleteContext);
643
644 return ProgramStateTrait<T>::MakeContext(p);
645 }
646
647 void EndPath(ProgramStateRef St) {
648 ConstraintMgr->EndPath(St);
649 }
650};
651
652
653//===----------------------------------------------------------------------===//
654// Out-of-line method definitions for ProgramState.
655//===----------------------------------------------------------------------===//
656
657inline ConstraintManager &ProgramState::getConstraintManager() const {
658 return stateMgr->getConstraintManager();
659}
660
661inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
662 const LocationContext *LC) const
663{
664 return getStateManager().getRegionManager().getVarRegion(D, LC);
665}
666
667inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
668 bool Assumption) const {
669 if (Cond.isUnknown())
670 return this;
671
672 return getStateManager().ConstraintMgr
673 ->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
674}
675
676inline std::pair<ProgramStateRef , ProgramStateRef >
677ProgramState::assume(DefinedOrUnknownSVal Cond) const {
678 if (Cond.isUnknown())
679 return std::make_pair(this, this);
680
681 return getStateManager().ConstraintMgr
682 ->assumeDual(this, Cond.castAs<DefinedSVal>());
683}
684
685inline ProgramStateRef ProgramState::assumeInclusiveRange(
686 DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To,
687 bool Assumption) const {
688 if (Val.isUnknown())
689 return this;
690
691 assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!")(static_cast <bool> (Val.getAs<NonLoc>() &&
"Only NonLocs are supported!") ? void (0) : __assert_fail ("Val.getAs<NonLoc>() && \"Only NonLocs are supported!\""
, "/build/llvm-toolchain-snapshot-7~svn325118/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
, 691, __extension__ __PRETTY_FUNCTION__))
;
692
693 return getStateManager().ConstraintMgr->assumeInclusiveRange(
694 this, Val.castAs<NonLoc>(), From, To, Assumption);
695}
696
697inline std::pair<ProgramStateRef, ProgramStateRef>
698ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val,
699 const llvm::APSInt &From,
700 const llvm::APSInt &To) const {
701 if (Val.isUnknown())
702 return std::make_pair(this, this);
703
704 assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!")(static_cast <bool> (Val.getAs<NonLoc>() &&
"Only NonLocs are supported!") ? void (0) : __assert_fail ("Val.getAs<NonLoc>() && \"Only NonLocs are supported!\""
, "/build/llvm-toolchain-snapshot-7~svn325118/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
, 704, __extension__ __PRETTY_FUNCTION__))
;
705
706 return getStateManager().ConstraintMgr->assumeInclusiveRangeDual(
707 this, Val.castAs<NonLoc>(), From, To);
708}
709
710inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const {
711 if (Optional<Loc> L = LV.getAs<Loc>())
712 return bindLoc(*L, V, LCtx);
713 return this;
714}
715
716inline Loc ProgramState::getLValue(const VarDecl *VD,
717 const LocationContext *LC) const {
718 return getStateManager().StoreMgr->getLValueVar(VD, LC);
719}
720
721inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal,
722 const LocationContext *LC) const {
723 return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
724}
725
726inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
727 return getStateManager().StoreMgr->getLValueIvar(D, Base);
728}
729
730inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
731 return getStateManager().StoreMgr->getLValueField(D, Base);
732}
733
734inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
735 SVal Base) const {
736 StoreManager &SM = *getStateManager().StoreMgr;
737 for (const auto *I : D->chain()) {
738 Base = SM.getLValueField(cast<FieldDecl>(I), Base);
739 }
740
741 return Base;
742}
743
744inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
745 if (Optional<NonLoc> N = Idx.getAs<NonLoc>())
746 return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
747 return UnknownVal();
748}
749
750inline SVal ProgramState::getSVal(const Stmt *Ex,
751 const LocationContext *LCtx) const{
752 return Env.getSVal(EnvironmentEntry(Ex, LCtx),
753 *getStateManager().svalBuilder);
754}
755
756inline SVal
757ProgramState::getSValAsScalarOrLoc(const Stmt *S,
758 const LocationContext *LCtx) const {
759 if (const Expr *Ex = dyn_cast<Expr>(S)) {
760 QualType T = Ex->getType();
761 if (Ex->isGLValue() || Loc::isLocType(T) ||
762 T->isIntegralOrEnumerationType())
763 return getSVal(S, LCtx);
764 }
765
766 return UnknownVal();
767}
768
769inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const {
770 return getStateManager().StoreMgr->getBinding(getStore(), LV, T);
771}
772
773inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const {
774 return getStateManager().StoreMgr->getBinding(getStore(),
775 loc::MemRegionVal(R),
776 T);
777}
778
779inline BasicValueFactory &ProgramState::getBasicVals() const {
780 return getStateManager().getBasicVals();
781}
782
783inline SymbolManager &ProgramState::getSymbolManager() const {
784 return getStateManager().getSymbolManager();
785}
786
787template<typename T>
788ProgramStateRef ProgramState::add(typename ProgramStateTrait<T>::key_type K) const {
789 return getStateManager().add<T>(this, K, get_context<T>());
790}
791
792template <typename T>
793typename ProgramStateTrait<T>::context_type ProgramState::get_context() const {
794 return getStateManager().get_context<T>();
795}
796
797template<typename T>
798ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const {
799 return getStateManager().remove<T>(this, K, get_context<T>());
800}
801
802template<typename T>
803ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K,
804 typename ProgramStateTrait<T>::context_type C) const {
805 return getStateManager().remove<T>(this, K, C);
806}
807
808template <typename T>
809ProgramStateRef ProgramState::remove() const {
810 return getStateManager().remove<T>(this);
811}
812
813template<typename T>
814ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::data_type D) const {
815 return getStateManager().set<T>(this, D);
816}
817
818template<typename T>
819ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K,
820 typename ProgramStateTrait<T>::value_type E) const {
821 return getStateManager().set<T>(this, K, E, get_context<T>());
822}
823
824template<typename T>
825ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K,
826 typename ProgramStateTrait<T>::value_type E,
827 typename ProgramStateTrait<T>::context_type C) const {
828 return getStateManager().set<T>(this, K, E, C);
829}
830
831template <typename CB>
832CB ProgramState::scanReachableSymbols(SVal val) const {
833 CB cb(this);
834 scanReachableSymbols(val, cb);
835 return cb;
836}
837
838template <typename CB>
839CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
840 CB cb(this);
841 scanReachableSymbols(beg, end, cb);
842 return cb;
843}
844
845template <typename CB>
846CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
847 const MemRegion * const *end) const {
848 CB cb(this);
849 scanReachableSymbols(beg, end, cb);
850 return cb;
851}
852
853/// \class ScanReachableSymbols
854/// A utility class that visits the reachable symbols using a custom
855/// SymbolVisitor. Terminates recursive traversal when the visitor function
856/// returns false.
857class ScanReachableSymbols {
858 typedef llvm::DenseSet<const void*> VisitedItems;
859
860 VisitedItems visited;
861 ProgramStateRef state;
862 SymbolVisitor &visitor;
863public:
864 ScanReachableSymbols(ProgramStateRef st, SymbolVisitor &v)
865 : state(std::move(st)), visitor(v) {}
866
867 bool scan(nonloc::LazyCompoundVal val);
868 bool scan(nonloc::CompoundVal val);
869 bool scan(SVal val);
870 bool scan(const MemRegion *R);
871 bool scan(const SymExpr *sym);
872};
873
874} // end ento namespace
875
876} // end clang namespace
877
878#endif

/build/llvm-toolchain-snapshot-7~svn325118/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h

1//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines partial implementations of template specializations of
11// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState
12// to implement set/get methods for manipulating a ProgramState's
13// generic data map.
14//
15//===----------------------------------------------------------------------===//
16
17
18#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
19#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
20
21#include "llvm/Support/Allocator.h"
22#include "llvm/Support/DataTypes.h"
23
24namespace llvm {
25 template <typename K, typename D, typename I> class ImmutableMap;
26 template <typename K, typename I> class ImmutableSet;
27 template <typename T> class ImmutableList;
28 template <typename T> class ImmutableListImpl;
29}
30
31namespace clang {
32
33namespace ento {
34 template <typename T> struct ProgramStatePartialTrait;
35
36 /// Declares a program state trait for type \p Type called \p Name, and
37 /// introduce a typedef named \c NameTy.
38 /// The macro should not be used inside namespaces, or for traits that must
39 /// be accessible from more than one translation unit.
40 #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)namespace { class Name {}; typedef Type NameTy; } namespace clang
{ namespace ento { template <> struct ProgramStateTrait
<Name> : public ProgramStatePartialTrait<NameTy> {
static void *GDMIndex() { static int Index; return &Index
; } }; } }
\
41 namespace { \
42 class Name {}; \
43 typedef Type Name ## Ty; \
44 } \
45 namespace clang { \
46 namespace ento { \
47 template <> \
48 struct ProgramStateTrait<Name> \
49 : public ProgramStatePartialTrait<Name ## Ty> { \
50 static void *GDMIndex() { static int Index; return &Index; } \
51 }; \
52 } \
53 }
54
55
56 // Partial-specialization for ImmutableMap.
57
58 template <typename Key, typename Data, typename Info>
59 struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
60 typedef llvm::ImmutableMap<Key,Data,Info> data_type;
61 typedef typename data_type::Factory& context_type;
62 typedef Key key_type;
63 typedef Data value_type;
64 typedef const value_type* lookup_type;
65
66 static inline data_type MakeData(void *const* p) {
67 return p ? data_type((typename data_type::TreeTy*) *p)
7
Assuming 'p' is null
8
'?' condition is false
68 : data_type(nullptr);
69 }
70 static inline void *MakeVoidPtr(data_type B) {
71 return B.getRoot();
72 }
73 static lookup_type Lookup(data_type B, key_type K) {
74 return B.lookup(K);
75 }
76 static data_type Set(data_type B, key_type K, value_type E,context_type F){
77 return F.add(B, K, E);
78 }
79
80 static data_type Remove(data_type B, key_type K, context_type F) {
81 return F.remove(B, K);
82 }
83
84 static bool Contains(data_type B, key_type K) {
85 return B.contains(K);
86 }
87
88 static inline context_type MakeContext(void *p) {
89 return *((typename data_type::Factory*) p);
90 }
91
92 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
93 return new typename data_type::Factory(Alloc);
94 }
95
96 static void DeleteContext(void *Ctx) {
97 delete (typename data_type::Factory*) Ctx;
98 }
99 };
100
101 /// Helper for registering a map trait.
102 ///
103 /// If the map type were written directly in the invocation of
104 /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
105 /// would be treated as a macro argument separator, which is wrong.
106 /// This allows the user to specify a map type in a way that the preprocessor
107 /// can deal with.
108 #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)llvm::ImmutableMap<Key, Value> llvm::ImmutableMap<Key, Value>
109
110
111 // Partial-specialization for ImmutableSet.
112
113 template <typename Key, typename Info>
114 struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
115 typedef llvm::ImmutableSet<Key,Info> data_type;
116 typedef typename data_type::Factory& context_type;
117 typedef Key key_type;
118
119 static inline data_type MakeData(void *const* p) {
120 return p ? data_type((typename data_type::TreeTy*) *p)
121 : data_type(nullptr);
122 }
123
124 static inline void *MakeVoidPtr(data_type B) {
125 return B.getRoot();
126 }
127
128 static data_type Add(data_type B, key_type K, context_type F) {
129 return F.add(B, K);
130 }
131
132 static data_type Remove(data_type B, key_type K, context_type F) {
133 return F.remove(B, K);
134 }
135
136 static bool Contains(data_type B, key_type K) {
137 return B.contains(K);
138 }
139
140 static inline context_type MakeContext(void *p) {
141 return *((typename data_type::Factory*) p);
142 }
143
144 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
145 return new typename data_type::Factory(Alloc);
146 }
147
148 static void DeleteContext(void *Ctx) {
149 delete (typename data_type::Factory*) Ctx;
150 }
151 };
152
153
154 // Partial-specialization for ImmutableList.
155
156 template <typename T>
157 struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
158 typedef llvm::ImmutableList<T> data_type;
159 typedef T key_type;
160 typedef typename data_type::Factory& context_type;
161
162 static data_type Add(data_type L, key_type K, context_type F) {
163 return F.add(K, L);
164 }
165
166 static bool Contains(data_type L, key_type K) {
167 return L.contains(K);
168 }
169
170 static inline data_type MakeData(void *const* p) {
171 return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
172 : data_type(nullptr);
173 }
174
175 static inline void *MakeVoidPtr(data_type D) {
176 return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
177 }
178
179 static inline context_type MakeContext(void *p) {
180 return *((typename data_type::Factory*) p);
181 }
182
183 static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
184 return new typename data_type::Factory(Alloc);
185 }
186
187 static void DeleteContext(void *Ctx) {
188 delete (typename data_type::Factory*) Ctx;
189 }
190 };
191
192
193 // Partial specialization for bool.
194 template <> struct ProgramStatePartialTrait<bool> {
195 typedef bool data_type;
196
197 static inline data_type MakeData(void *const* p) {
198 return p ? (data_type) (uintptr_t) *p
199 : data_type();
200 }
201 static inline void *MakeVoidPtr(data_type d) {
202 return (void*) (uintptr_t) d;
203 }
204 };
205
206 // Partial specialization for unsigned.
207 template <> struct ProgramStatePartialTrait<unsigned> {
208 typedef unsigned data_type;
209
210 static inline data_type MakeData(void *const* p) {
211 return p ? (data_type) (uintptr_t) *p
212 : data_type();
213 }
214 static inline void *MakeVoidPtr(data_type d) {
215 return (void*) (uintptr_t) d;
216 }
217 };
218
219 // Partial specialization for void*.
220 template <> struct ProgramStatePartialTrait<void*> {
221 typedef void *data_type;
222
223 static inline data_type MakeData(void *const* p) {
224 return p ? *p
225 : data_type();
226 }
227 static inline void *MakeVoidPtr(data_type d) {
228 return d;
229 }
230 };
231
232 // Partial specialization for const void *.
233 template <> struct ProgramStatePartialTrait<const void *> {
234 typedef const void *data_type;
235
236 static inline data_type MakeData(void * const *p) {
237 return p ? *p : data_type();
238 }
239
240 static inline void *MakeVoidPtr(data_type d) {
241 return const_cast<void *>(d);
242 }
243 };
244
245} // end ento namespace
246
247} // end clang namespace
248
249#endif