1 //== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines SymbolManager, a class that manages symbolic values
11 // created for use by ExprEngine and related classes.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_GR_SYMMGR_H
16 #define LLVM_CLANG_GR_SYMMGR_H
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/Analysis/AnalysisContext.h"
21 #include "llvm/Support/DataTypes.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/ADT/DenseSet.h"
26 class BumpPtrAllocator
;
32 class StackFrameContext
;
35 class BasicValueFactory
;
41 class SymExpr
: public llvm::FoldingSetNode
{
43 enum Kind
{ BEGIN_SYMBOLS
,
44 RegionValueKind
, ConjuredKind
, DerivedKind
, ExtentKind
,
47 SymIntKind
, SymSymKind
};
52 SymExpr(Kind k
) : K(k
) {}
57 Kind
getKind() const { return K
; }
61 virtual void dumpToStream(llvm::raw_ostream
&os
) const = 0;
63 virtual QualType
getType(ASTContext
&) const = 0;
64 virtual void Profile(llvm::FoldingSetNodeID
& profile
) = 0;
66 // Implement isa<T> support.
67 static inline bool classof(const SymExpr
*) { return true; }
70 typedef unsigned SymbolID
;
72 class SymbolData
: public SymExpr
{
77 SymbolData(Kind k
, SymbolID sym
) : SymExpr(k
), Sym(sym
) {}
80 virtual ~SymbolData() {}
82 SymbolID
getSymbolID() const { return Sym
; }
84 // Implement isa<T> support.
85 static inline bool classof(const SymExpr
* SE
) {
86 Kind k
= SE
->getKind();
87 return k
> BEGIN_SYMBOLS
&& k
< END_SYMBOLS
;
91 typedef const SymbolData
* SymbolRef
;
93 // A symbol representing the value of a MemRegion.
94 class SymbolRegionValue
: public SymbolData
{
98 SymbolRegionValue(SymbolID sym
, const TypedRegion
*r
)
99 : SymbolData(RegionValueKind
, sym
), R(r
) {}
101 const TypedRegion
* getRegion() const { return R
; }
103 static void Profile(llvm::FoldingSetNodeID
& profile
, const TypedRegion
* R
) {
104 profile
.AddInteger((unsigned) RegionValueKind
);
105 profile
.AddPointer(R
);
108 virtual void Profile(llvm::FoldingSetNodeID
& profile
) {
112 void dumpToStream(llvm::raw_ostream
&os
) const;
114 QualType
getType(ASTContext
&) const;
116 // Implement isa<T> support.
117 static inline bool classof(const SymExpr
* SE
) {
118 return SE
->getKind() == RegionValueKind
;
122 // A symbol representing the result of an expression.
123 class SymbolConjured
: public SymbolData
{
127 const void* SymbolTag
;
130 SymbolConjured(SymbolID sym
, const Stmt
* s
, QualType t
, unsigned count
,
131 const void* symbolTag
)
132 : SymbolData(ConjuredKind
, sym
), S(s
), T(t
), Count(count
),
133 SymbolTag(symbolTag
) {}
135 const Stmt
* getStmt() const { return S
; }
136 unsigned getCount() const { return Count
; }
137 const void* getTag() const { return SymbolTag
; }
139 QualType
getType(ASTContext
&) const;
141 void dumpToStream(llvm::raw_ostream
&os
) const;
143 static void Profile(llvm::FoldingSetNodeID
& profile
, const Stmt
* S
,
144 QualType T
, unsigned Count
, const void* SymbolTag
) {
145 profile
.AddInteger((unsigned) ConjuredKind
);
146 profile
.AddPointer(S
);
148 profile
.AddInteger(Count
);
149 profile
.AddPointer(SymbolTag
);
152 virtual void Profile(llvm::FoldingSetNodeID
& profile
) {
153 Profile(profile
, S
, T
, Count
, SymbolTag
);
156 // Implement isa<T> support.
157 static inline bool classof(const SymExpr
* SE
) {
158 return SE
->getKind() == ConjuredKind
;
162 // A symbol representing the value of a MemRegion whose parent region has
164 class SymbolDerived
: public SymbolData
{
165 SymbolRef parentSymbol
;
166 const TypedRegion
*R
;
169 SymbolDerived(SymbolID sym
, SymbolRef parent
, const TypedRegion
*r
)
170 : SymbolData(DerivedKind
, sym
), parentSymbol(parent
), R(r
) {}
172 SymbolRef
getParentSymbol() const { return parentSymbol
; }
173 const TypedRegion
*getRegion() const { return R
; }
175 QualType
getType(ASTContext
&) const;
177 void dumpToStream(llvm::raw_ostream
&os
) const;
179 static void Profile(llvm::FoldingSetNodeID
& profile
, SymbolRef parent
,
180 const TypedRegion
*r
) {
181 profile
.AddInteger((unsigned) DerivedKind
);
182 profile
.AddPointer(r
);
183 profile
.AddPointer(parent
);
186 virtual void Profile(llvm::FoldingSetNodeID
& profile
) {
187 Profile(profile
, parentSymbol
, R
);
190 // Implement isa<T> support.
191 static inline bool classof(const SymExpr
* SE
) {
192 return SE
->getKind() == DerivedKind
;
196 /// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
197 /// Clients should not ask the SymbolManager for a region's extent. Always use
198 /// SubRegion::getExtent instead -- the value returned may not be a symbol.
199 class SymbolExtent
: public SymbolData
{
203 SymbolExtent(SymbolID sym
, const SubRegion
*r
)
204 : SymbolData(ExtentKind
, sym
), R(r
) {}
206 const SubRegion
*getRegion() const { return R
; }
208 QualType
getType(ASTContext
&) const;
210 void dumpToStream(llvm::raw_ostream
&os
) const;
212 static void Profile(llvm::FoldingSetNodeID
& profile
, const SubRegion
*R
) {
213 profile
.AddInteger((unsigned) ExtentKind
);
214 profile
.AddPointer(R
);
217 virtual void Profile(llvm::FoldingSetNodeID
& profile
) {
221 // Implement isa<T> support.
222 static inline bool classof(const SymExpr
* SE
) {
223 return SE
->getKind() == ExtentKind
;
227 /// SymbolMetadata - Represents path-dependent metadata about a specific region.
228 /// Metadata symbols remain live as long as they are marked as in use before
229 /// dead-symbol sweeping AND their associated regions are still alive.
230 /// Intended for use by checkers.
231 class SymbolMetadata
: public SymbolData
{
238 SymbolMetadata(SymbolID sym
, const MemRegion
* r
, const Stmt
* s
, QualType t
,
239 unsigned count
, const void* tag
)
240 : SymbolData(MetadataKind
, sym
), R(r
), S(s
), T(t
), Count(count
), Tag(tag
) {}
242 const MemRegion
*getRegion() const { return R
; }
243 const Stmt
* getStmt() const { return S
; }
244 unsigned getCount() const { return Count
; }
245 const void* getTag() const { return Tag
; }
247 QualType
getType(ASTContext
&) const;
249 void dumpToStream(llvm::raw_ostream
&os
) const;
251 static void Profile(llvm::FoldingSetNodeID
& profile
, const MemRegion
*R
,
252 const Stmt
*S
, QualType T
, unsigned Count
,
254 profile
.AddInteger((unsigned) MetadataKind
);
255 profile
.AddPointer(R
);
256 profile
.AddPointer(S
);
258 profile
.AddInteger(Count
);
259 profile
.AddPointer(Tag
);
262 virtual void Profile(llvm::FoldingSetNodeID
& profile
) {
263 Profile(profile
, R
, S
, T
, Count
, Tag
);
266 // Implement isa<T> support.
267 static inline bool classof(const SymExpr
* SE
) {
268 return SE
->getKind() == MetadataKind
;
272 // SymIntExpr - Represents symbolic expression like 'x' + 3.
273 class SymIntExpr
: public SymExpr
{
275 BinaryOperator::Opcode Op
;
276 const llvm::APSInt
& RHS
;
280 SymIntExpr(const SymExpr
*lhs
, BinaryOperator::Opcode op
,
281 const llvm::APSInt
& rhs
, QualType t
)
282 : SymExpr(SymIntKind
), LHS(lhs
), Op(op
), RHS(rhs
), T(t
) {}
284 // FIXME: We probably need to make this out-of-line to avoid redundant
285 // generation of virtual functions.
286 QualType
getType(ASTContext
& C
) const { return T
; }
288 BinaryOperator::Opcode
getOpcode() const { return Op
; }
290 void dumpToStream(llvm::raw_ostream
&os
) const;
292 const SymExpr
*getLHS() const { return LHS
; }
293 const llvm::APSInt
&getRHS() const { return RHS
; }
295 static void Profile(llvm::FoldingSetNodeID
& ID
, const SymExpr
*lhs
,
296 BinaryOperator::Opcode op
, const llvm::APSInt
& rhs
,
298 ID
.AddInteger((unsigned) SymIntKind
);
305 void Profile(llvm::FoldingSetNodeID
& ID
) {
306 Profile(ID
, LHS
, Op
, RHS
, T
);
309 // Implement isa<T> support.
310 static inline bool classof(const SymExpr
* SE
) {
311 return SE
->getKind() == SymIntKind
;
315 // SymSymExpr - Represents symbolic expression like 'x' + 'y'.
316 class SymSymExpr
: public SymExpr
{
318 BinaryOperator::Opcode Op
;
323 SymSymExpr(const SymExpr
*lhs
, BinaryOperator::Opcode op
, const SymExpr
*rhs
,
325 : SymExpr(SymSymKind
), LHS(lhs
), Op(op
), RHS(rhs
), T(t
) {}
327 BinaryOperator::Opcode
getOpcode() const { return Op
; }
328 const SymExpr
*getLHS() const { return LHS
; }
329 const SymExpr
*getRHS() const { return RHS
; }
331 // FIXME: We probably need to make this out-of-line to avoid redundant
332 // generation of virtual functions.
333 QualType
getType(ASTContext
& C
) const { return T
; }
335 void dumpToStream(llvm::raw_ostream
&os
) const;
337 static void Profile(llvm::FoldingSetNodeID
& ID
, const SymExpr
*lhs
,
338 BinaryOperator::Opcode op
, const SymExpr
*rhs
, QualType t
) {
339 ID
.AddInteger((unsigned) SymSymKind
);
346 void Profile(llvm::FoldingSetNodeID
& ID
) {
347 Profile(ID
, LHS
, Op
, RHS
, T
);
350 // Implement isa<T> support.
351 static inline bool classof(const SymExpr
* SE
) {
352 return SE
->getKind() == SymSymKind
;
356 class SymbolManager
{
357 typedef llvm::FoldingSet
<SymExpr
> DataSetTy
;
359 unsigned SymbolCounter
;
360 llvm::BumpPtrAllocator
& BPAlloc
;
361 BasicValueFactory
&BV
;
365 SymbolManager(ASTContext
& ctx
, BasicValueFactory
&bv
,
366 llvm::BumpPtrAllocator
& bpalloc
)
367 : SymbolCounter(0), BPAlloc(bpalloc
), BV(bv
), Ctx(ctx
) {}
371 static bool canSymbolicate(QualType T
);
373 /// Make a unique symbol for MemRegion R according to its kind.
374 const SymbolRegionValue
* getRegionValueSymbol(const TypedRegion
* R
);
376 const SymbolConjured
* getConjuredSymbol(const Stmt
* E
, QualType T
,
378 const void* SymbolTag
= 0);
380 const SymbolConjured
* getConjuredSymbol(const Expr
* E
, unsigned VisitCount
,
381 const void* SymbolTag
= 0) {
382 return getConjuredSymbol(E
, E
->getType(), VisitCount
, SymbolTag
);
385 const SymbolDerived
*getDerivedSymbol(SymbolRef parentSymbol
,
386 const TypedRegion
*R
);
388 const SymbolExtent
*getExtentSymbol(const SubRegion
*R
);
390 const SymbolMetadata
* getMetadataSymbol(const MemRegion
* R
, const Stmt
* S
,
391 QualType T
, unsigned VisitCount
,
392 const void* SymbolTag
= 0);
394 const SymIntExpr
*getSymIntExpr(const SymExpr
*lhs
, BinaryOperator::Opcode op
,
395 const llvm::APSInt
& rhs
, QualType t
);
397 const SymIntExpr
*getSymIntExpr(const SymExpr
&lhs
, BinaryOperator::Opcode op
,
398 const llvm::APSInt
& rhs
, QualType t
) {
399 return getSymIntExpr(&lhs
, op
, rhs
, t
);
402 const SymSymExpr
*getSymSymExpr(const SymExpr
*lhs
, BinaryOperator::Opcode op
,
403 const SymExpr
*rhs
, QualType t
);
405 QualType
getType(const SymExpr
*SE
) const {
406 return SE
->getType(Ctx
);
409 ASTContext
&getContext() { return Ctx
; }
410 BasicValueFactory
&getBasicVals() { return BV
; }
414 typedef llvm::DenseSet
<SymbolRef
> SetTy
;
419 const LocationContext
*LCtx
;
421 SymbolManager
& SymMgr
;
424 SymbolReaper(const LocationContext
*ctx
, const Stmt
*s
, SymbolManager
& symmgr
)
425 : LCtx(ctx
), Loc(s
), SymMgr(symmgr
) {}
429 const LocationContext
*getLocationContext() const { return LCtx
; }
430 const Stmt
*getCurrentStatement() const { return Loc
; }
432 bool isLive(SymbolRef sym
);
433 bool isLive(const Stmt
*ExprVal
) const;
434 bool isLive(const VarRegion
*VR
) const;
436 // markLive - Unconditionally marks a symbol as live. This should never be
437 // used by checkers, only by the state infrastructure such as the store and
438 // environment. Checkers should instead use metadata symbols and markInUse.
439 void markLive(SymbolRef sym
);
441 // markInUse - Marks a symbol as important to a checker. For metadata symbols,
442 // this will keep the symbol alive as long as its associated region is also
443 // live. For other symbols, this has no effect; checkers are not permitted
444 // to influence the life of other symbols. This should be used before any
445 // symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
446 void markInUse(SymbolRef sym
);
448 // maybeDead - If a symbol is known to be live, marks the symbol as live.
449 // Otherwise, if the symbol cannot be proven live, it is marked as dead.
450 // Returns true if the symbol is dead, false if live.
451 bool maybeDead(SymbolRef sym
);
453 typedef SetTy::const_iterator dead_iterator
;
454 dead_iterator
dead_begin() const { return TheDead
.begin(); }
455 dead_iterator
dead_end() const { return TheDead
.end(); }
457 bool hasDeadSymbols() const {
458 return !TheDead
.empty();
461 /// isDead - Returns whether or not a symbol has been confirmed dead. This
462 /// should only be called once all marking of dead symbols has completed.
463 /// (For checkers, this means only in the evalDeadSymbols callback.)
464 bool isDead(SymbolRef sym
) const {
465 return TheDead
.count(sym
);
469 class SymbolVisitor
{
471 // VisitSymbol - A visitor method invoked by
472 // GRStateManager::scanReachableSymbols. The method returns \c true if
473 // symbols should continue be scanned and \c false otherwise.
474 virtual bool VisitSymbol(SymbolRef sym
) = 0;
475 virtual ~SymbolVisitor();
478 } // end GR namespace
480 } // end clang namespace
483 static inline llvm::raw_ostream
& operator<<(llvm::raw_ostream
& os
,
484 const clang::ento::SymExpr
*SE
) {
485 SE
->dumpToStream(os
);
488 } // end llvm namespace