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/Basic/LLVM.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
20 #include "llvm/ADT/ImmutableList.h"
22 //==------------------------------------------------------------------------==//
24 //==------------------------------------------------------------------------==//
30 class CompoundValData;
31 class LazyCompoundValData;
33 class BasicValueFactory;
36 class MemRegionManager;
37 class ProgramStateManager;
40 /// SVal - This represents a symbolic expression, which can be either
41 /// an L-value or an R-value.
46 // The enumerators must be representable using 2 bits.
47 UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
48 UnknownKind = 1, // for subclass UnknownVal (a void value)
49 LocKind = 2, // for subclass Loc (an L-value)
50 NonLocKind = 3 // for subclass NonLoc (an R-value that's not
53 enum { BaseBits = 2, BaseMask = 0x3 };
58 /// The lowest 2 bits are a BaseKind (0 -- 3).
59 /// The higher bits are an unsigned "kind" value.
62 explicit SVal(const void *d, bool isLoc, unsigned ValKind)
63 : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
65 explicit SVal(BaseKind k, const void *D = NULL)
69 explicit SVal() : Data(0), Kind(0) {}
72 /// BufferTy - A temporary buffer to hold a set of SVals.
73 typedef SmallVector<SVal,5> BufferTy;
75 inline unsigned getRawKind() const { return Kind; }
76 inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
77 inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
79 // This method is required for using SVal in a FoldingSetNode. It
80 // extracts a unique signature for this SVal object.
81 inline void Profile(llvm::FoldingSetNodeID& ID) const {
82 ID.AddInteger((unsigned) getRawKind());
86 inline bool operator==(const SVal& R) const {
87 return getRawKind() == R.getRawKind() && Data == R.Data;
90 inline bool operator!=(const SVal& R) const {
94 inline bool isUnknown() const {
95 return getRawKind() == UnknownKind;
98 inline bool isUndef() const {
99 return getRawKind() == UndefinedKind;
102 inline bool isUnknownOrUndef() const {
103 return getRawKind() <= UnknownKind;
106 inline bool isValid() const {
107 return getRawKind() > UnknownKind;
110 bool isConstant() const;
112 bool isConstant(int I) const;
114 bool isZeroConstant() const;
116 /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
117 bool hasConjuredSymbol() const;
119 /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
120 /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
121 /// Otherwise return 0.
122 const FunctionDecl *getAsFunctionDecl() const;
124 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
125 /// wraps a symbol, return that SymbolRef. Otherwise return NULL.
126 SymbolRef getAsLocSymbol() const;
128 /// Get the symbol in the SVal or its base region.
129 SymbolRef getLocSymbolInBase() const;
131 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
132 /// Otherwise return a SymbolRef where 'isValid()' returns false.
133 SymbolRef getAsSymbol() const;
135 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
136 /// return that expression. Otherwise return NULL.
137 const SymExpr *getAsSymbolicExpression() const;
139 const MemRegion *getAsRegion() const;
141 void dumpToStream(raw_ostream &OS) const;
145 class symbol_iterator {
146 SmallVector<const SymExpr*, 5> itr;
150 symbol_iterator(const SymExpr *SE);
152 symbol_iterator &operator++();
153 SymbolRef operator*();
155 bool operator==(const symbol_iterator &X) const;
156 bool operator!=(const symbol_iterator &X) const;
159 symbol_iterator symbol_begin() const {
160 const SymExpr *SE = getAsSymbolicExpression();
162 return symbol_iterator(SE);
164 return symbol_iterator();
167 symbol_iterator symbol_end() const { return symbol_iterator(); }
169 // Implement isa<T> support.
170 static inline bool classof(const SVal*) { return true; }
174 class UndefinedVal : public SVal {
176 UndefinedVal() : SVal(UndefinedKind) {}
177 UndefinedVal(const void *D) : SVal(UndefinedKind, D) {}
179 static inline bool classof(const SVal* V) {
180 return V->getBaseKind() == UndefinedKind;
183 const void *getData() const { return Data; }
186 class DefinedOrUnknownSVal : public SVal {
188 // Do not implement. We want calling these methods to be a compiler
189 // error since they are tautologically false.
190 bool isUndef() const;
191 bool isValid() const;
194 explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
195 : SVal(d, isLoc, ValKind) {}
197 explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
201 // Implement isa<T> support.
202 static inline bool classof(const SVal *V) {
203 return !V->isUndef();
207 class UnknownVal : public DefinedOrUnknownSVal {
209 explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
211 static inline bool classof(const SVal *V) {
212 return V->getBaseKind() == UnknownKind;
216 class DefinedSVal : public DefinedOrUnknownSVal {
218 // Do not implement. We want calling these methods to be a compiler
219 // error since they are tautologically true/false.
220 bool isUnknown() const;
221 bool isUnknownOrUndef() const;
222 bool isValid() const;
224 explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
225 : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
227 // Implement isa<T> support.
228 static inline bool classof(const SVal *V) {
229 return !V->isUnknownOrUndef();
233 class NonLoc : public DefinedSVal {
235 explicit NonLoc(unsigned SubKind, const void *d)
236 : DefinedSVal(d, false, SubKind) {}
239 void dumpToStream(raw_ostream &Out) const;
241 // Implement isa<T> support.
242 static inline bool classof(const SVal* V) {
243 return V->getBaseKind() == NonLocKind;
247 class Loc : public DefinedSVal {
249 explicit Loc(unsigned SubKind, const void *D)
250 : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
253 void dumpToStream(raw_ostream &Out) const;
255 Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
257 // Implement isa<T> support.
258 static inline bool classof(const SVal* V) {
259 return V->getBaseKind() == LocKind;
262 static inline bool isLocType(QualType T) {
263 return T->isAnyPointerType() || T->isBlockPointerType() ||
264 T->isReferenceType();
268 //==------------------------------------------------------------------------==//
269 // Subclasses of NonLoc.
270 //==------------------------------------------------------------------------==//
274 enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
275 LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
277 class SymbolVal : public NonLoc {
279 SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
281 SymbolRef getSymbol() const {
282 return (const SymbolData*) Data;
285 static inline bool classof(const SVal* V) {
286 return V->getBaseKind() == NonLocKind &&
287 V->getSubKind() == SymbolValKind;
290 static inline bool classof(const NonLoc* V) {
291 return V->getSubKind() == SymbolValKind;
295 class SymExprVal : public NonLoc {
297 explicit SymExprVal(const SymExpr *SE)
298 : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
300 const SymExpr *getSymbolicExpression() const {
301 return reinterpret_cast<const SymExpr*>(Data);
304 static inline bool classof(const SVal* V) {
305 return V->getBaseKind() == NonLocKind &&
306 V->getSubKind() == SymExprValKind;
309 static inline bool classof(const NonLoc* V) {
310 return V->getSubKind() == SymExprValKind;
314 class ConcreteInt : public NonLoc {
316 explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
318 const llvm::APSInt& getValue() const {
319 return *static_cast<const llvm::APSInt*>(Data);
322 // Transfer functions for binary/unary operations on ConcreteInts.
323 SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
324 const ConcreteInt& R) const;
326 ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
328 ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
330 // Implement isa<T> support.
331 static inline bool classof(const SVal* V) {
332 return V->getBaseKind() == NonLocKind &&
333 V->getSubKind() == ConcreteIntKind;
336 static inline bool classof(const NonLoc* V) {
337 return V->getSubKind() == ConcreteIntKind;
341 class LocAsInteger : public NonLoc {
342 friend class ento::SValBuilder;
344 explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
345 NonLoc(LocAsIntegerKind, &data) {
346 assert (isa<Loc>(data.first));
352 return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
355 const Loc& getPersistentLoc() const {
356 const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
360 unsigned getNumBits() const {
361 return ((std::pair<SVal, unsigned>*) Data)->second;
364 // Implement isa<T> support.
365 static inline bool classof(const SVal* V) {
366 return V->getBaseKind() == NonLocKind &&
367 V->getSubKind() == LocAsIntegerKind;
370 static inline bool classof(const NonLoc* V) {
371 return V->getSubKind() == LocAsIntegerKind;
375 class CompoundVal : public NonLoc {
376 friend class ento::SValBuilder;
378 explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
381 const CompoundValData* getValue() const {
382 return static_cast<const CompoundValData*>(Data);
385 typedef llvm::ImmutableList<SVal>::iterator iterator;
386 iterator begin() const;
387 iterator end() const;
389 static bool classof(const SVal* V) {
390 return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
393 static bool classof(const NonLoc* V) {
394 return V->getSubKind() == CompoundValKind;
398 class LazyCompoundVal : public NonLoc {
399 friend class ento::SValBuilder;
401 explicit LazyCompoundVal(const LazyCompoundValData *D)
402 : NonLoc(LazyCompoundValKind, D) {}
404 const LazyCompoundValData *getCVData() const {
405 return static_cast<const LazyCompoundValData*>(Data);
407 const void *getStore() const;
408 const TypedRegion *getRegion() const;
410 static bool classof(const SVal *V) {
411 return V->getBaseKind() == NonLocKind &&
412 V->getSubKind() == LazyCompoundValKind;
414 static bool classof(const NonLoc *V) {
415 return V->getSubKind() == LazyCompoundValKind;
419 } // end namespace ento::nonloc
421 //==------------------------------------------------------------------------==//
422 // Subclasses of Loc.
423 //==------------------------------------------------------------------------==//
427 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
429 class GotoLabel : public Loc {
431 explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
433 const LabelDecl *getLabel() const {
434 return static_cast<const LabelDecl*>(Data);
437 static inline bool classof(const SVal* V) {
438 return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
441 static inline bool classof(const Loc* V) {
442 return V->getSubKind() == GotoLabelKind;
447 class MemRegionVal : public Loc {
449 explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
451 const MemRegion* getRegion() const {
452 return static_cast<const MemRegion*>(Data);
455 const MemRegion* stripCasts() const;
457 template <typename REGION>
458 const REGION* getRegionAs() const {
459 return llvm::dyn_cast<REGION>(getRegion());
462 inline bool operator==(const MemRegionVal& R) const {
463 return getRegion() == R.getRegion();
466 inline bool operator!=(const MemRegionVal& R) const {
467 return getRegion() != R.getRegion();
470 // Implement isa<T> support.
471 static inline bool classof(const SVal* V) {
472 return V->getBaseKind() == LocKind &&
473 V->getSubKind() == MemRegionKind;
476 static inline bool classof(const Loc* V) {
477 return V->getSubKind() == MemRegionKind;
481 class ConcreteInt : public Loc {
483 explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
485 const llvm::APSInt& getValue() const {
486 return *static_cast<const llvm::APSInt*>(Data);
489 // Transfer functions for binary/unary operations on ConcreteInts.
490 SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
491 const ConcreteInt& R) const;
493 // Implement isa<T> support.
494 static inline bool classof(const SVal* V) {
495 return V->getBaseKind() == LocKind &&
496 V->getSubKind() == ConcreteIntKind;
499 static inline bool classof(const Loc* V) {
500 return V->getSubKind() == ConcreteIntKind;
504 /// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
505 /// "store" of an ObjC property for the dot syntax.
506 class ObjCPropRef : public Loc {
508 explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
509 : Loc(ObjCPropRefKind, E) {}
511 const ObjCPropertyRefExpr *getPropRefExpr() const {
512 return static_cast<const ObjCPropertyRefExpr *>(Data);
515 // Implement isa<T> support.
516 static inline bool classof(const SVal* V) {
517 return V->getBaseKind() == LocKind &&
518 V->getSubKind() == ObjCPropRefKind;
521 static inline bool classof(const Loc* V) {
522 return V->getSubKind() == ObjCPropRefKind;
526 } // end ento::loc namespace
527 } // end GR namespace
529 } // end clang namespace
532 static inline raw_ostream &operator<<(raw_ostream &os,
533 clang::ento::SVal V) {
538 } // end llvm namespace