1 //== SVals.h - Abstract Values for Static Analysis ---------*- 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 SVal, Loc, and NonLoc, classes that represent
11 // abstract r-values for use with path-sensitive value tracking.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_GR_RVALUE_H
16 #define LLVM_CLANG_GR_RVALUE_H
18 #include "clang/StaticAnalyzer/PathSensitive/SymbolManager.h"
19 #include "llvm/Support/Casting.h"
20 #include "llvm/ADT/ImmutableList.h"
26 //==------------------------------------------------------------------------==//
28 //==------------------------------------------------------------------------==//
34 class CompoundValData
;
35 class LazyCompoundValData
;
37 class BasicValueFactory
;
40 class MemRegionManager
;
44 /// SVal - This represents a symbolic expression, which can be either
45 /// an L-value or an R-value.
50 // The enumerators must be representable using 2 bits.
51 UndefinedKind
= 0, // for subclass UndefinedVal (an uninitialized value)
52 UnknownKind
= 1, // for subclass UnknownVal (a void value)
53 LocKind
= 2, // for subclass Loc (an L-value)
54 NonLocKind
= 3 // for subclass NonLoc (an R-value that's not
57 enum { BaseBits
= 2, BaseMask
= 0x3 };
62 /// The lowest 2 bits are a BaseKind (0 -- 3).
63 /// The higher bits are an unsigned "kind" value.
67 explicit SVal(const void* d
, bool isLoc
, unsigned ValKind
)
68 : Data(d
), Kind((isLoc
? LocKind
: NonLocKind
) | (ValKind
<< BaseBits
)) {}
70 explicit SVal(BaseKind k
, const void* D
= NULL
)
74 explicit SVal() : Data(0), Kind(0) {}
77 /// BufferTy - A temporary buffer to hold a set of SVals.
78 typedef llvm::SmallVector
<SVal
,5> BufferTy
;
80 inline unsigned getRawKind() const { return Kind
; }
81 inline BaseKind
getBaseKind() const { return (BaseKind
) (Kind
& BaseMask
); }
82 inline unsigned getSubKind() const { return (Kind
& ~BaseMask
) >> BaseBits
; }
84 inline void Profile(llvm::FoldingSetNodeID
& ID
) const {
85 ID
.AddInteger((unsigned) getRawKind());
89 inline bool operator==(const SVal
& R
) const {
90 return getRawKind() == R
.getRawKind() && Data
== R
.Data
;
93 inline bool operator!=(const SVal
& R
) const {
97 inline bool isUnknown() const {
98 return getRawKind() == UnknownKind
;
101 inline bool isUndef() const {
102 return getRawKind() == UndefinedKind
;
105 inline bool isUnknownOrUndef() const {
106 return getRawKind() <= UnknownKind
;
109 inline bool isValid() const {
110 return getRawKind() > UnknownKind
;
113 bool isConstant() const;
115 bool isConstant(int I
) const;
117 bool isZeroConstant() const;
119 /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
120 bool hasConjuredSymbol() const;
122 /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
123 /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
124 /// Otherwise return 0.
125 const FunctionDecl
* getAsFunctionDecl() const;
127 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
128 /// wraps a symbol, return that SymbolRef. Otherwise return NULL.
129 SymbolRef
getAsLocSymbol() const;
131 /// Get the symbol in the SVal or its base region.
132 SymbolRef
getLocSymbolInBase() const;
134 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
135 /// Otherwise return a SymbolRef where 'isValid()' returns false.
136 SymbolRef
getAsSymbol() const;
138 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
139 /// return that expression. Otherwise return NULL.
140 const SymExpr
*getAsSymbolicExpression() const;
142 const MemRegion
*getAsRegion() const;
144 void dumpToStream(llvm::raw_ostream
& OS
) const;
148 class symbol_iterator
{
149 llvm::SmallVector
<const SymExpr
*, 5> itr
;
153 symbol_iterator(const SymExpr
* SE
);
155 symbol_iterator
& operator++();
156 SymbolRef
operator*();
158 bool operator==(const symbol_iterator
& X
) const;
159 bool operator!=(const symbol_iterator
& X
) const;
162 symbol_iterator
symbol_begin() const {
163 const SymExpr
*SE
= getAsSymbolicExpression();
165 return symbol_iterator(SE
);
167 return symbol_iterator();
170 symbol_iterator
symbol_end() const { return symbol_iterator(); }
172 // Implement isa<T> support.
173 static inline bool classof(const SVal
*) { return true; }
177 class UndefinedVal
: public SVal
{
179 UndefinedVal() : SVal(UndefinedKind
) {}
180 UndefinedVal(const void* D
) : SVal(UndefinedKind
, D
) {}
182 static inline bool classof(const SVal
* V
) {
183 return V
->getBaseKind() == UndefinedKind
;
186 const void* getData() const { return Data
; }
189 class DefinedOrUnknownSVal
: public SVal
{
191 // Do not implement. We want calling these methods to be a compiler
192 // error since they are tautologically false.
193 bool isUndef() const;
194 bool isValid() const;
197 explicit DefinedOrUnknownSVal(const void* d
, bool isLoc
, unsigned ValKind
)
198 : SVal(d
, isLoc
, ValKind
) {}
200 explicit DefinedOrUnknownSVal(BaseKind k
, void *D
= NULL
)
204 // Implement isa<T> support.
205 static inline bool classof(const SVal
*V
) {
206 return !V
->isUndef();
210 class UnknownVal
: public DefinedOrUnknownSVal
{
212 explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind
) {}
214 static inline bool classof(const SVal
*V
) {
215 return V
->getBaseKind() == UnknownKind
;
219 class DefinedSVal
: public DefinedOrUnknownSVal
{
221 // Do not implement. We want calling these methods to be a compiler
222 // error since they are tautologically true/false.
223 bool isUnknown() const;
224 bool isUnknownOrUndef() const;
225 bool isValid() const;
227 explicit DefinedSVal(const void* d
, bool isLoc
, unsigned ValKind
)
228 : DefinedOrUnknownSVal(d
, isLoc
, ValKind
) {}
230 // Implement isa<T> support.
231 static inline bool classof(const SVal
*V
) {
232 return !V
->isUnknownOrUndef();
236 class NonLoc
: public DefinedSVal
{
238 explicit NonLoc(unsigned SubKind
, const void* d
)
239 : DefinedSVal(d
, false, SubKind
) {}
242 void dumpToStream(llvm::raw_ostream
& Out
) const;
244 // Implement isa<T> support.
245 static inline bool classof(const SVal
* V
) {
246 return V
->getBaseKind() == NonLocKind
;
250 class Loc
: public DefinedSVal
{
252 explicit Loc(unsigned SubKind
, const void* D
)
253 : DefinedSVal(const_cast<void*>(D
), true, SubKind
) {}
256 void dumpToStream(llvm::raw_ostream
& Out
) const;
258 Loc(const Loc
& X
) : DefinedSVal(X
.Data
, true, X
.getSubKind()) {}
260 // Implement isa<T> support.
261 static inline bool classof(const SVal
* V
) {
262 return V
->getBaseKind() == LocKind
;
265 static inline bool IsLocType(QualType T
) {
266 return T
->isAnyPointerType() || T
->isBlockPointerType() ||
267 T
->isReferenceType();
271 //==------------------------------------------------------------------------==//
272 // Subclasses of NonLoc.
273 //==------------------------------------------------------------------------==//
277 enum Kind
{ ConcreteIntKind
, SymbolValKind
, SymExprValKind
,
278 LocAsIntegerKind
, CompoundValKind
, LazyCompoundValKind
};
280 class SymbolVal
: public NonLoc
{
282 SymbolVal(SymbolRef sym
) : NonLoc(SymbolValKind
, sym
) {}
284 SymbolRef
getSymbol() const {
285 return (const SymbolData
*) Data
;
288 static inline bool classof(const SVal
* V
) {
289 return V
->getBaseKind() == NonLocKind
&&
290 V
->getSubKind() == SymbolValKind
;
293 static inline bool classof(const NonLoc
* V
) {
294 return V
->getSubKind() == SymbolValKind
;
298 class SymExprVal
: public NonLoc
{
300 explicit SymExprVal(const SymExpr
*SE
)
301 : NonLoc(SymExprValKind
, reinterpret_cast<const void*>(SE
)) {}
303 const SymExpr
*getSymbolicExpression() const {
304 return reinterpret_cast<const SymExpr
*>(Data
);
307 static inline bool classof(const SVal
* V
) {
308 return V
->getBaseKind() == NonLocKind
&&
309 V
->getSubKind() == SymExprValKind
;
312 static inline bool classof(const NonLoc
* V
) {
313 return V
->getSubKind() == SymExprValKind
;
317 class ConcreteInt
: public NonLoc
{
319 explicit ConcreteInt(const llvm::APSInt
& V
) : NonLoc(ConcreteIntKind
, &V
) {}
321 const llvm::APSInt
& getValue() const {
322 return *static_cast<const llvm::APSInt
*>(Data
);
325 // Transfer functions for binary/unary operations on ConcreteInts.
326 SVal
evalBinOp(SValBuilder
&svalBuilder
, BinaryOperator::Opcode Op
,
327 const ConcreteInt
& R
) const;
329 ConcreteInt
evalComplement(SValBuilder
&svalBuilder
) const;
331 ConcreteInt
evalMinus(SValBuilder
&svalBuilder
) const;
333 // Implement isa<T> support.
334 static inline bool classof(const SVal
* V
) {
335 return V
->getBaseKind() == NonLocKind
&&
336 V
->getSubKind() == ConcreteIntKind
;
339 static inline bool classof(const NonLoc
* V
) {
340 return V
->getSubKind() == ConcreteIntKind
;
344 class LocAsInteger
: public NonLoc
{
345 friend class ento::SValBuilder
;
347 explicit LocAsInteger(const std::pair
<SVal
, uintptr_t>& data
) :
348 NonLoc(LocAsIntegerKind
, &data
) {
349 assert (isa
<Loc
>(data
.first
));
355 return cast
<Loc
>(((std::pair
<SVal
, uintptr_t>*) Data
)->first
);
358 const Loc
& getPersistentLoc() const {
359 const SVal
& V
= ((std::pair
<SVal
, uintptr_t>*) Data
)->first
;
363 unsigned getNumBits() const {
364 return ((std::pair
<SVal
, unsigned>*) Data
)->second
;
367 // Implement isa<T> support.
368 static inline bool classof(const SVal
* V
) {
369 return V
->getBaseKind() == NonLocKind
&&
370 V
->getSubKind() == LocAsIntegerKind
;
373 static inline bool classof(const NonLoc
* V
) {
374 return V
->getSubKind() == LocAsIntegerKind
;
378 class CompoundVal
: public NonLoc
{
379 friend class ento::SValBuilder
;
381 explicit CompoundVal(const CompoundValData
* D
) : NonLoc(CompoundValKind
, D
) {}
384 const CompoundValData
* getValue() const {
385 return static_cast<const CompoundValData
*>(Data
);
388 typedef llvm::ImmutableList
<SVal
>::iterator iterator
;
389 iterator
begin() const;
390 iterator
end() const;
392 static bool classof(const SVal
* V
) {
393 return V
->getBaseKind() == NonLocKind
&& V
->getSubKind() == CompoundValKind
;
396 static bool classof(const NonLoc
* V
) {
397 return V
->getSubKind() == CompoundValKind
;
401 class LazyCompoundVal
: public NonLoc
{
402 friend class ento::SValBuilder
;
404 explicit LazyCompoundVal(const LazyCompoundValData
*D
)
405 : NonLoc(LazyCompoundValKind
, D
) {}
407 const LazyCompoundValData
*getCVData() const {
408 return static_cast<const LazyCompoundValData
*>(Data
);
410 const void *getStore() const;
411 const TypedRegion
*getRegion() const;
413 static bool classof(const SVal
*V
) {
414 return V
->getBaseKind() == NonLocKind
&&
415 V
->getSubKind() == LazyCompoundValKind
;
417 static bool classof(const NonLoc
*V
) {
418 return V
->getSubKind() == LazyCompoundValKind
;
422 } // end namespace ento::nonloc
424 //==------------------------------------------------------------------------==//
425 // Subclasses of Loc.
426 //==------------------------------------------------------------------------==//
430 enum Kind
{ GotoLabelKind
, MemRegionKind
, ConcreteIntKind
, ObjCPropRefKind
};
432 class GotoLabel
: public Loc
{
434 explicit GotoLabel(LabelStmt
* Label
) : Loc(GotoLabelKind
, Label
) {}
436 const LabelStmt
* getLabel() const {
437 return static_cast<const LabelStmt
*>(Data
);
440 static inline bool classof(const SVal
* V
) {
441 return V
->getBaseKind() == LocKind
&&
442 V
->getSubKind() == GotoLabelKind
;
445 static inline bool classof(const Loc
* V
) {
446 return V
->getSubKind() == GotoLabelKind
;
451 class MemRegionVal
: public Loc
{
453 explicit MemRegionVal(const MemRegion
* r
) : Loc(MemRegionKind
, r
) {}
455 const MemRegion
* getRegion() const {
456 return static_cast<const MemRegion
*>(Data
);
459 const MemRegion
* StripCasts() const;
461 template <typename REGION
>
462 const REGION
* getRegionAs() const {
463 return llvm::dyn_cast
<REGION
>(getRegion());
466 inline bool operator==(const MemRegionVal
& R
) const {
467 return getRegion() == R
.getRegion();
470 inline bool operator!=(const MemRegionVal
& R
) const {
471 return getRegion() != R
.getRegion();
474 // Implement isa<T> support.
475 static inline bool classof(const SVal
* V
) {
476 return V
->getBaseKind() == LocKind
&&
477 V
->getSubKind() == MemRegionKind
;
480 static inline bool classof(const Loc
* V
) {
481 return V
->getSubKind() == MemRegionKind
;
485 class ConcreteInt
: public Loc
{
487 explicit ConcreteInt(const llvm::APSInt
& V
) : Loc(ConcreteIntKind
, &V
) {}
489 const llvm::APSInt
& getValue() const {
490 return *static_cast<const llvm::APSInt
*>(Data
);
493 // Transfer functions for binary/unary operations on ConcreteInts.
494 SVal
evalBinOp(BasicValueFactory
& BasicVals
, BinaryOperator::Opcode Op
,
495 const ConcreteInt
& R
) const;
497 // Implement isa<T> support.
498 static inline bool classof(const SVal
* V
) {
499 return V
->getBaseKind() == LocKind
&&
500 V
->getSubKind() == ConcreteIntKind
;
503 static inline bool classof(const Loc
* V
) {
504 return V
->getSubKind() == ConcreteIntKind
;
508 /// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
509 /// "store" of an ObjC property for the dot syntax.
510 class ObjCPropRef
: public Loc
{
512 explicit ObjCPropRef(const ObjCPropertyRefExpr
*E
)
513 : Loc(ObjCPropRefKind
, E
) {}
515 const ObjCPropertyRefExpr
*getPropRefExpr() const {
516 return static_cast<const ObjCPropertyRefExpr
*>(Data
);
519 // Implement isa<T> support.
520 static inline bool classof(const SVal
* V
) {
521 return V
->getBaseKind() == LocKind
&&
522 V
->getSubKind() == ObjCPropRefKind
;
525 static inline bool classof(const Loc
* V
) {
526 return V
->getSubKind() == ObjCPropRefKind
;
530 } // end ento::loc namespace
531 } // end GR namespace
533 } // end clang namespace
536 static inline llvm::raw_ostream
& operator<<(llvm::raw_ostream
& os
,
537 clang::ento::SVal V
) {
542 } // end llvm namespace