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/Core/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.
66 explicit SVal(const void* d, bool isLoc, unsigned ValKind)
67 : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
69 explicit SVal(BaseKind k, const void* D = NULL)
73 explicit SVal() : Data(0), Kind(0) {}
76 /// BufferTy - A temporary buffer to hold a set of SVals.
77 typedef llvm::SmallVector<SVal,5> BufferTy;
79 inline unsigned getRawKind() const { return Kind; }
80 inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
81 inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
83 // This method is required for using SVal in a FoldingSetNode. It
84 // extracts a unique signature for this SVal object.
85 inline void Profile(llvm::FoldingSetNodeID& ID) const {
86 ID.AddInteger((unsigned) getRawKind());
90 inline bool operator==(const SVal& R) const {
91 return getRawKind() == R.getRawKind() && Data == R.Data;
94 inline bool operator!=(const SVal& R) const {
98 inline bool isUnknown() const {
99 return getRawKind() == UnknownKind;
102 inline bool isUndef() const {
103 return getRawKind() == UndefinedKind;
106 inline bool isUnknownOrUndef() const {
107 return getRawKind() <= UnknownKind;
110 inline bool isValid() const {
111 return getRawKind() > UnknownKind;
114 bool isConstant() const;
116 bool isConstant(int I) const;
118 bool isZeroConstant() const;
120 /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
121 bool hasConjuredSymbol() const;
123 /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
124 /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
125 /// Otherwise return 0.
126 const FunctionDecl* getAsFunctionDecl() const;
128 /// \brief If this SVal is a MemRegionVal and wraps a VarDecl,
129 /// return that VarDecl. Otherwise return 0.
130 const VarDecl* getAsVarDecl() const;
132 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
133 /// wraps a symbol, return that SymbolRef. Otherwise return NULL.
134 SymbolRef getAsLocSymbol() const;
136 /// Get the symbol in the SVal or its base region.
137 SymbolRef getLocSymbolInBase() const;
139 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
140 /// Otherwise return a SymbolRef where 'isValid()' returns false.
141 SymbolRef getAsSymbol() const;
143 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
144 /// return that expression. Otherwise return NULL.
145 const SymExpr *getAsSymbolicExpression() const;
147 const MemRegion *getAsRegion() const;
149 void dumpToStream(llvm::raw_ostream& OS) const;
153 class symbol_iterator {
154 llvm::SmallVector<const SymExpr*, 5> itr;
158 symbol_iterator(const SymExpr* SE);
160 symbol_iterator& operator++();
161 SymbolRef operator*();
163 bool operator==(const symbol_iterator& X) const;
164 bool operator!=(const symbol_iterator& X) const;
167 symbol_iterator symbol_begin() const {
168 const SymExpr *SE = getAsSymbolicExpression();
170 return symbol_iterator(SE);
172 return symbol_iterator();
175 symbol_iterator symbol_end() const { return symbol_iterator(); }
177 // Implement isa<T> support.
178 static inline bool classof(const SVal*) { return true; }
182 class UndefinedVal : public SVal {
184 UndefinedVal() : SVal(UndefinedKind) {}
185 UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
187 static inline bool classof(const SVal* V) {
188 return V->getBaseKind() == UndefinedKind;
191 const void* getData() const { return Data; }
194 class DefinedOrUnknownSVal : public SVal {
196 // Do not implement. We want calling these methods to be a compiler
197 // error since they are tautologically false.
198 bool isUndef() const;
199 bool isValid() const;
202 explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind)
203 : SVal(d, isLoc, ValKind) {}
205 explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
209 // Implement isa<T> support.
210 static inline bool classof(const SVal *V) {
211 return !V->isUndef();
215 class UnknownVal : public DefinedOrUnknownSVal {
217 explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
219 static inline bool classof(const SVal *V) {
220 return V->getBaseKind() == UnknownKind;
224 class DefinedSVal : public DefinedOrUnknownSVal {
226 // Do not implement. We want calling these methods to be a compiler
227 // error since they are tautologically true/false.
228 bool isUnknown() const;
229 bool isUnknownOrUndef() const;
230 bool isValid() const;
232 explicit DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
233 : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
235 // Implement isa<T> support.
236 static inline bool classof(const SVal *V) {
237 return !V->isUnknownOrUndef();
241 class NonLoc : public DefinedSVal {
243 explicit NonLoc(unsigned SubKind, const void* d)
244 : DefinedSVal(d, false, SubKind) {}
247 void dumpToStream(llvm::raw_ostream& Out) const;
249 // Implement isa<T> support.
250 static inline bool classof(const SVal* V) {
251 return V->getBaseKind() == NonLocKind;
255 class Loc : public DefinedSVal {
257 explicit Loc(unsigned SubKind, const void* D)
258 : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
261 void dumpToStream(llvm::raw_ostream& Out) const;
263 Loc(const Loc& X) : DefinedSVal(X.Data, true, X.getSubKind()) {}
265 // Implement isa<T> support.
266 static inline bool classof(const SVal* V) {
267 return V->getBaseKind() == LocKind;
270 static inline bool isLocType(QualType T) {
271 return T->isAnyPointerType() || T->isBlockPointerType() ||
272 T->isReferenceType();
276 //==------------------------------------------------------------------------==//
277 // Subclasses of NonLoc.
278 //==------------------------------------------------------------------------==//
282 enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
283 LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
285 class SymbolVal : public NonLoc {
287 SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
289 SymbolRef getSymbol() const {
290 return (const SymbolData*) Data;
293 static inline bool classof(const SVal* V) {
294 return V->getBaseKind() == NonLocKind &&
295 V->getSubKind() == SymbolValKind;
298 static inline bool classof(const NonLoc* V) {
299 return V->getSubKind() == SymbolValKind;
303 class SymExprVal : public NonLoc {
305 explicit SymExprVal(const SymExpr *SE)
306 : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
308 const SymExpr *getSymbolicExpression() const {
309 return reinterpret_cast<const SymExpr*>(Data);
312 static inline bool classof(const SVal* V) {
313 return V->getBaseKind() == NonLocKind &&
314 V->getSubKind() == SymExprValKind;
317 static inline bool classof(const NonLoc* V) {
318 return V->getSubKind() == SymExprValKind;
322 class ConcreteInt : public NonLoc {
324 explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
326 const llvm::APSInt& getValue() const {
327 return *static_cast<const llvm::APSInt*>(Data);
330 // Transfer functions for binary/unary operations on ConcreteInts.
331 SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
332 const ConcreteInt& R) const;
334 ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
336 ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
338 // Implement isa<T> support.
339 static inline bool classof(const SVal* V) {
340 return V->getBaseKind() == NonLocKind &&
341 V->getSubKind() == ConcreteIntKind;
344 static inline bool classof(const NonLoc* V) {
345 return V->getSubKind() == ConcreteIntKind;
349 class LocAsInteger : public NonLoc {
350 friend class ento::SValBuilder;
352 explicit LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
353 NonLoc(LocAsIntegerKind, &data) {
354 assert (isa<Loc>(data.first));
360 return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first);
363 const Loc& getPersistentLoc() const {
364 const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first;
368 unsigned getNumBits() const {
369 return ((std::pair<SVal, unsigned>*) Data)->second;
372 // Implement isa<T> support.
373 static inline bool classof(const SVal* V) {
374 return V->getBaseKind() == NonLocKind &&
375 V->getSubKind() == LocAsIntegerKind;
378 static inline bool classof(const NonLoc* V) {
379 return V->getSubKind() == LocAsIntegerKind;
383 class CompoundVal : public NonLoc {
384 friend class ento::SValBuilder;
386 explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
389 const CompoundValData* getValue() const {
390 return static_cast<const CompoundValData*>(Data);
393 typedef llvm::ImmutableList<SVal>::iterator iterator;
394 iterator begin() const;
395 iterator end() const;
397 static bool classof(const SVal* V) {
398 return V->getBaseKind() == NonLocKind && V->getSubKind() == CompoundValKind;
401 static bool classof(const NonLoc* V) {
402 return V->getSubKind() == CompoundValKind;
406 class LazyCompoundVal : public NonLoc {
407 friend class ento::SValBuilder;
409 explicit LazyCompoundVal(const LazyCompoundValData *D)
410 : NonLoc(LazyCompoundValKind, D) {}
412 const LazyCompoundValData *getCVData() const {
413 return static_cast<const LazyCompoundValData*>(Data);
415 const void *getStore() const;
416 const TypedRegion *getRegion() const;
418 static bool classof(const SVal *V) {
419 return V->getBaseKind() == NonLocKind &&
420 V->getSubKind() == LazyCompoundValKind;
422 static bool classof(const NonLoc *V) {
423 return V->getSubKind() == LazyCompoundValKind;
427 } // end namespace ento::nonloc
429 //==------------------------------------------------------------------------==//
430 // Subclasses of Loc.
431 //==------------------------------------------------------------------------==//
435 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
437 class GotoLabel : public Loc {
439 explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
441 const LabelDecl *getLabel() const {
442 return static_cast<const LabelDecl*>(Data);
445 static inline bool classof(const SVal* V) {
446 return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
449 static inline bool classof(const Loc* V) {
450 return V->getSubKind() == GotoLabelKind;
455 class MemRegionVal : public Loc {
457 explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
459 const MemRegion* getRegion() const {
460 return static_cast<const MemRegion*>(Data);
463 const MemRegion* stripCasts() const;
465 template <typename REGION>
466 const REGION* getRegionAs() const {
467 return llvm::dyn_cast<REGION>(getRegion());
470 inline bool operator==(const MemRegionVal& R) const {
471 return getRegion() == R.getRegion();
474 inline bool operator!=(const MemRegionVal& R) const {
475 return getRegion() != R.getRegion();
478 // Implement isa<T> support.
479 static inline bool classof(const SVal* V) {
480 return V->getBaseKind() == LocKind &&
481 V->getSubKind() == MemRegionKind;
484 static inline bool classof(const Loc* V) {
485 return V->getSubKind() == MemRegionKind;
489 class ConcreteInt : public Loc {
491 explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
493 const llvm::APSInt& getValue() const {
494 return *static_cast<const llvm::APSInt*>(Data);
497 // Transfer functions for binary/unary operations on ConcreteInts.
498 SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
499 const ConcreteInt& R) const;
501 // Implement isa<T> support.
502 static inline bool classof(const SVal* V) {
503 return V->getBaseKind() == LocKind &&
504 V->getSubKind() == ConcreteIntKind;
507 static inline bool classof(const Loc* V) {
508 return V->getSubKind() == ConcreteIntKind;
512 /// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or
513 /// "store" of an ObjC property for the dot syntax.
514 class ObjCPropRef : public Loc {
516 explicit ObjCPropRef(const ObjCPropertyRefExpr *E)
517 : Loc(ObjCPropRefKind, E) {}
519 const ObjCPropertyRefExpr *getPropRefExpr() const {
520 return static_cast<const ObjCPropertyRefExpr *>(Data);
523 // Implement isa<T> support.
524 static inline bool classof(const SVal* V) {
525 return V->getBaseKind() == LocKind &&
526 V->getSubKind() == ObjCPropRefKind;
529 static inline bool classof(const Loc* V) {
530 return V->getSubKind() == ObjCPropRefKind;
534 } // end ento::loc namespace
535 } // end GR namespace
537 } // end clang namespace
540 static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
541 clang::ento::SVal V) {
546 } // end llvm namespace