[analyzer] Handle the dot syntax for properties in the ExprEngine.
[clang.git] / include / clang / StaticAnalyzer / PathSensitive / SVals.h
blob721c3598dc2aa73b370571b5f14892feb2b489a2
1 //== SVals.h - Abstract Values for Static Analysis ---------*- 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 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"
22 namespace llvm {
23 class raw_ostream;
26 //==------------------------------------------------------------------------==//
27 // Base SVal types.
28 //==------------------------------------------------------------------------==//
30 namespace clang {
32 namespace ento {
34 class CompoundValData;
35 class LazyCompoundValData;
36 class GRState;
37 class BasicValueFactory;
38 class MemRegion;
39 class TypedRegion;
40 class MemRegionManager;
41 class GRStateManager;
42 class SValBuilder;
44 /// SVal - This represents a symbolic expression, which can be either
45 /// an L-value or an R-value.
46 ///
47 class SVal {
48 public:
49 enum BaseKind {
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
55 // an L-value)
57 enum { BaseBits = 2, BaseMask = 0x3 };
59 protected:
60 const void* Data;
62 /// The lowest 2 bits are a BaseKind (0 -- 3).
63 /// The higher bits are an unsigned "kind" value.
64 unsigned Kind;
66 protected:
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)
71 : Data(D), Kind(k) {}
73 public:
74 explicit SVal() : Data(0), Kind(0) {}
75 ~SVal() {}
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());
86 ID.AddPointer(Data);
89 inline bool operator==(const SVal& R) const {
90 return getRawKind() == R.getRawKind() && Data == R.Data;
93 inline bool operator!=(const SVal& R) const {
94 return !(*this == R);
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;
145 void dump() const;
147 // Iterators.
148 class symbol_iterator {
149 llvm::SmallVector<const SymExpr*, 5> itr;
150 void expand();
151 public:
152 symbol_iterator() {}
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();
164 if (SE)
165 return symbol_iterator(SE);
166 else
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 {
178 public:
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 {
190 private:
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;
196 protected:
197 explicit DefinedOrUnknownSVal(const void* d, bool isLoc, unsigned ValKind)
198 : SVal(d, isLoc, ValKind) {}
200 explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
201 : SVal(k, D) {}
203 public:
204 // Implement isa<T> support.
205 static inline bool classof(const SVal *V) {
206 return !V->isUndef();
210 class UnknownVal : public DefinedOrUnknownSVal {
211 public:
212 explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
214 static inline bool classof(const SVal *V) {
215 return V->getBaseKind() == UnknownKind;
219 class DefinedSVal : public DefinedOrUnknownSVal {
220 private:
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;
226 protected:
227 explicit DefinedSVal(const void* d, bool isLoc, unsigned ValKind)
228 : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
229 public:
230 // Implement isa<T> support.
231 static inline bool classof(const SVal *V) {
232 return !V->isUnknownOrUndef();
236 class NonLoc : public DefinedSVal {
237 protected:
238 explicit NonLoc(unsigned SubKind, const void* d)
239 : DefinedSVal(d, false, SubKind) {}
241 public:
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 {
251 protected:
252 explicit Loc(unsigned SubKind, const void* D)
253 : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
255 public:
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 //==------------------------------------------------------------------------==//
275 namespace nonloc {
277 enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
278 LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
280 class SymbolVal : public NonLoc {
281 public:
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 {
299 public:
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 {
318 public:
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));
352 public:
354 Loc getLoc() const {
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;
360 return cast<Loc>(V);
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) {}
383 public:
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) {}
406 public:
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 //==------------------------------------------------------------------------==//
428 namespace loc {
430 enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
432 class GotoLabel : public Loc {
433 public:
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 {
452 public:
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 {
486 public:
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 {
511 public:
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
535 namespace llvm {
536 static inline llvm::raw_ostream& operator<<(llvm::raw_ostream& os,
537 clang::ento::SVal V) {
538 V.dumpToStream(os);
539 return os;
542 } // end llvm namespace
544 #endif