]> granicus.if.org Git - clang/blob - include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
[analyzer] Make the entries in 'Environment' context-sensitive by making entries...
[clang] / include / clang / StaticAnalyzer / Core / PathSensitive / SymbolManager.h
1 //== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
11 //  created for use by ExprEngine and related classes.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_GR_SYMMGR_H
16 #define LLVM_CLANG_GR_SYMMGR_H
17
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/Analysis/AnalysisContext.h"
21 #include "clang/Basic/LLVM.h"
22 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
23 #include "llvm/Support/DataTypes.h"
24 #include "llvm/ADT/FoldingSet.h"
25 #include "llvm/ADT/DenseSet.h"
26 #include "llvm/ADT/DenseMap.h"
27
28 namespace llvm {
29 class BumpPtrAllocator;
30 }
31
32 namespace clang {
33   class ASTContext;
34   class StackFrameContext;
35
36 namespace ento {
37   class BasicValueFactory;
38   class MemRegion;
39   class SubRegion;
40   class TypedValueRegion;
41   class VarRegion;
42
43 /// \brief Symbolic value. These values used to capture symbolic execution of
44 /// the program.
45 class SymExpr : public llvm::FoldingSetNode {
46   virtual void anchor();
47 public:
48   enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
49               MetadataKind,
50               BEGIN_SYMBOLS = RegionValueKind,
51               END_SYMBOLS = MetadataKind,
52               SymIntKind, IntSymKind, SymSymKind, CastSymbolKind };
53 private:
54   Kind K;
55
56 protected:
57   SymExpr(Kind k) : K(k) {}
58
59 public:
60   virtual ~SymExpr() {}
61
62   Kind getKind() const { return K; }
63
64   void dump() const;
65
66   virtual void dumpToStream(raw_ostream &os) const = 0;
67
68   virtual QualType getType(ASTContext&) const = 0;
69   virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
70
71   // Implement isa<T> support.
72   static inline bool classof(const SymExpr*) { return true; }
73
74   /// \brief Iterator over symbols that the current symbol depends on.
75   ///
76   /// For SymbolData, it's the symbol itself; for expressions, it's the
77   /// expression symbol and all the operands in it. Note, SymbolDerived is
78   /// treated as SymbolData - the iterator will NOT visit the parent region.
79   class symbol_iterator {
80     SmallVector<const SymExpr*, 5> itr;
81     void expand();
82   public:
83     symbol_iterator() {}
84     symbol_iterator(const SymExpr *SE);
85
86     symbol_iterator &operator++();
87     const SymExpr* operator*();
88
89     bool operator==(const symbol_iterator &X) const;
90     bool operator!=(const symbol_iterator &X) const;
91   };
92
93   symbol_iterator symbol_begin() const {
94     return symbol_iterator(this);
95   }
96   static symbol_iterator symbol_end() { return symbol_iterator(); }
97 };
98
99 typedef const SymExpr* SymbolRef;
100 typedef llvm::SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
101
102 typedef unsigned SymbolID;
103 /// \brief A symbol representing data which can be stored in a memory location
104 /// (region).
105 class SymbolData : public SymExpr {
106   virtual void anchor();
107   const SymbolID Sym;
108
109 protected:
110   SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
111
112 public:
113   virtual ~SymbolData() {}
114
115   SymbolID getSymbolID() const { return Sym; }
116
117   // Implement isa<T> support.
118   static inline bool classof(const SymExpr *SE) {
119     Kind k = SE->getKind();
120     return k >= BEGIN_SYMBOLS && k <= END_SYMBOLS;
121   }
122 };
123
124 ///\brief A symbol representing the value stored at a MemRegion.
125 class SymbolRegionValue : public SymbolData {
126   const TypedValueRegion *R;
127
128 public:
129   SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
130     : SymbolData(RegionValueKind, sym), R(r) {}
131
132   const TypedValueRegion* getRegion() const { return R; }
133
134   static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
135     profile.AddInteger((unsigned) RegionValueKind);
136     profile.AddPointer(R);
137   }
138
139   virtual void Profile(llvm::FoldingSetNodeID& profile) {
140     Profile(profile, R);
141   }
142
143   void dumpToStream(raw_ostream &os) const;
144
145   QualType getType(ASTContext&) const;
146
147   // Implement isa<T> support.
148   static inline bool classof(const SymExpr *SE) {
149     return SE->getKind() == RegionValueKind;
150   }
151 };
152
153 /// A symbol representing the result of an expression in the case when we do
154 /// not know anything about what the expression is.
155 class SymbolConjured : public SymbolData {
156   const Stmt *S;
157   QualType T;
158   unsigned Count;
159   const void *SymbolTag;
160
161 public:
162   SymbolConjured(SymbolID sym, const Stmt *s, QualType t, unsigned count,
163                  const void *symbolTag)
164     : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
165       SymbolTag(symbolTag) {}
166
167   const Stmt *getStmt() const { return S; }
168   unsigned getCount() const { return Count; }
169   const void *getTag() const { return SymbolTag; }
170
171   QualType getType(ASTContext&) const;
172
173   void dumpToStream(raw_ostream &os) const;
174
175   static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
176                       QualType T, unsigned Count, const void *SymbolTag) {
177     profile.AddInteger((unsigned) ConjuredKind);
178     profile.AddPointer(S);
179     profile.Add(T);
180     profile.AddInteger(Count);
181     profile.AddPointer(SymbolTag);
182   }
183
184   virtual void Profile(llvm::FoldingSetNodeID& profile) {
185     Profile(profile, S, T, Count, SymbolTag);
186   }
187
188   // Implement isa<T> support.
189   static inline bool classof(const SymExpr *SE) {
190     return SE->getKind() == ConjuredKind;
191   }
192 };
193
194 /// A symbol representing the value of a MemRegion whose parent region has
195 /// symbolic value.
196 class SymbolDerived : public SymbolData {
197   SymbolRef parentSymbol;
198   const TypedValueRegion *R;
199
200 public:
201   SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
202     : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
203
204   SymbolRef getParentSymbol() const { return parentSymbol; }
205   const TypedValueRegion *getRegion() const { return R; }
206
207   QualType getType(ASTContext&) const;
208
209   void dumpToStream(raw_ostream &os) const;
210
211   static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
212                       const TypedValueRegion *r) {
213     profile.AddInteger((unsigned) DerivedKind);
214     profile.AddPointer(r);
215     profile.AddPointer(parent);
216   }
217
218   virtual void Profile(llvm::FoldingSetNodeID& profile) {
219     Profile(profile, parentSymbol, R);
220   }
221
222   // Implement isa<T> support.
223   static inline bool classof(const SymExpr *SE) {
224     return SE->getKind() == DerivedKind;
225   }
226 };
227
228 /// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
229 ///  Clients should not ask the SymbolManager for a region's extent. Always use
230 ///  SubRegion::getExtent instead -- the value returned may not be a symbol.
231 class SymbolExtent : public SymbolData {
232   const SubRegion *R;
233   
234 public:
235   SymbolExtent(SymbolID sym, const SubRegion *r)
236   : SymbolData(ExtentKind, sym), R(r) {}
237
238   const SubRegion *getRegion() const { return R; }
239
240   QualType getType(ASTContext&) const;
241
242   void dumpToStream(raw_ostream &os) const;
243
244   static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
245     profile.AddInteger((unsigned) ExtentKind);
246     profile.AddPointer(R);
247   }
248
249   virtual void Profile(llvm::FoldingSetNodeID& profile) {
250     Profile(profile, R);
251   }
252
253   // Implement isa<T> support.
254   static inline bool classof(const SymExpr *SE) {
255     return SE->getKind() == ExtentKind;
256   }
257 };
258
259 /// SymbolMetadata - Represents path-dependent metadata about a specific region.
260 ///  Metadata symbols remain live as long as they are marked as in use before
261 ///  dead-symbol sweeping AND their associated regions are still alive.
262 ///  Intended for use by checkers.
263 class SymbolMetadata : public SymbolData {
264   const MemRegion* R;
265   const Stmt *S;
266   QualType T;
267   unsigned Count;
268   const void *Tag;
269 public:
270   SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
271                  unsigned count, const void *tag)
272   : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
273
274   const MemRegion *getRegion() const { return R; }
275   const Stmt *getStmt() const { return S; }
276   unsigned getCount() const { return Count; }
277   const void *getTag() const { return Tag; }
278
279   QualType getType(ASTContext&) const;
280
281   void dumpToStream(raw_ostream &os) const;
282
283   static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
284                       const Stmt *S, QualType T, unsigned Count,
285                       const void *Tag) {
286     profile.AddInteger((unsigned) MetadataKind);
287     profile.AddPointer(R);
288     profile.AddPointer(S);
289     profile.Add(T);
290     profile.AddInteger(Count);
291     profile.AddPointer(Tag);
292   }
293
294   virtual void Profile(llvm::FoldingSetNodeID& profile) {
295     Profile(profile, R, S, T, Count, Tag);
296   }
297
298   // Implement isa<T> support.
299   static inline bool classof(const SymExpr *SE) {
300     return SE->getKind() == MetadataKind;
301   }
302 };
303
304 /// \brief Represents a cast expression.
305 class SymbolCast : public SymExpr {
306   const SymExpr *Operand;
307   /// Type of the operand.
308   QualType FromTy;
309   /// The type of the result.
310   QualType ToTy;
311
312 public:
313   SymbolCast(const SymExpr *In, QualType From, QualType To) :
314     SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
315
316   QualType getType(ASTContext &C) const { return ToTy; }
317
318   const SymExpr *getOperand() const { return Operand; }
319
320   void dumpToStream(raw_ostream &os) const;
321
322   static void Profile(llvm::FoldingSetNodeID& ID,
323                       const SymExpr *In, QualType From, QualType To) {
324     ID.AddInteger((unsigned) CastSymbolKind);
325     ID.AddPointer(In);
326     ID.Add(From);
327     ID.Add(To);
328   }
329
330   void Profile(llvm::FoldingSetNodeID& ID) {
331     Profile(ID, Operand, FromTy, ToTy);
332   }
333
334   // Implement isa<T> support.
335   static inline bool classof(const SymExpr *SE) {
336     return SE->getKind() == CastSymbolKind;
337   }
338 };
339
340 /// SymIntExpr - Represents symbolic expression like 'x' + 3.
341 class SymIntExpr : public SymExpr {
342   const SymExpr *LHS;
343   BinaryOperator::Opcode Op;
344   const llvm::APSInt& RHS;
345   QualType T;
346
347 public:
348   SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
349              const llvm::APSInt& rhs, QualType t)
350     : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
351
352   // FIXME: We probably need to make this out-of-line to avoid redundant
353   // generation of virtual functions.
354   QualType getType(ASTContext &C) const { return T; }
355
356   BinaryOperator::Opcode getOpcode() const { return Op; }
357
358   void dumpToStream(raw_ostream &os) const;
359
360   const SymExpr *getLHS() const { return LHS; }
361   const llvm::APSInt &getRHS() const { return RHS; }
362
363   static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
364                       BinaryOperator::Opcode op, const llvm::APSInt& rhs,
365                       QualType t) {
366     ID.AddInteger((unsigned) SymIntKind);
367     ID.AddPointer(lhs);
368     ID.AddInteger(op);
369     ID.AddPointer(&rhs);
370     ID.Add(t);
371   }
372
373   void Profile(llvm::FoldingSetNodeID& ID) {
374     Profile(ID, LHS, Op, RHS, T);
375   }
376
377   // Implement isa<T> support.
378   static inline bool classof(const SymExpr *SE) {
379     return SE->getKind() == SymIntKind;
380   }
381 };
382
383 /// IntSymExpr - Represents symbolic expression like 3 - 'x'.
384 class IntSymExpr : public SymExpr {
385   const llvm::APSInt& LHS;
386   BinaryOperator::Opcode Op;
387   const SymExpr *RHS;
388   QualType T;
389
390 public:
391   IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
392              const SymExpr *rhs, QualType t)
393     : SymExpr(IntSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
394
395   QualType getType(ASTContext &C) const { return T; }
396
397   BinaryOperator::Opcode getOpcode() const { return Op; }
398
399   void dumpToStream(raw_ostream &os) const;
400
401   const SymExpr *getRHS() const { return RHS; }
402   const llvm::APSInt &getLHS() const { return LHS; }
403
404   static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
405                       BinaryOperator::Opcode op, const SymExpr *rhs,
406                       QualType t) {
407     ID.AddInteger((unsigned) IntSymKind);
408     ID.AddPointer(&lhs);
409     ID.AddInteger(op);
410     ID.AddPointer(rhs);
411     ID.Add(t);
412   }
413
414   void Profile(llvm::FoldingSetNodeID& ID) {
415     Profile(ID, LHS, Op, RHS, T);
416   }
417
418   // Implement isa<T> support.
419   static inline bool classof(const SymExpr *SE) {
420     return SE->getKind() == IntSymKind;
421   }
422 };
423
424 /// SymSymExpr - Represents symbolic expression like 'x' + 'y'.
425 class SymSymExpr : public SymExpr {
426   const SymExpr *LHS;
427   BinaryOperator::Opcode Op;
428   const SymExpr *RHS;
429   QualType T;
430
431 public:
432   SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
433              QualType t)
434     : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {}
435
436   BinaryOperator::Opcode getOpcode() const { return Op; }
437   const SymExpr *getLHS() const { return LHS; }
438   const SymExpr *getRHS() const { return RHS; }
439
440   // FIXME: We probably need to make this out-of-line to avoid redundant
441   // generation of virtual functions.
442   QualType getType(ASTContext &C) const { return T; }
443
444   void dumpToStream(raw_ostream &os) const;
445
446   static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
447                     BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
448     ID.AddInteger((unsigned) SymSymKind);
449     ID.AddPointer(lhs);
450     ID.AddInteger(op);
451     ID.AddPointer(rhs);
452     ID.Add(t);
453   }
454
455   void Profile(llvm::FoldingSetNodeID& ID) {
456     Profile(ID, LHS, Op, RHS, T);
457   }
458
459   // Implement isa<T> support.
460   static inline bool classof(const SymExpr *SE) {
461     return SE->getKind() == SymSymKind;
462   }
463 };
464
465 class SymbolManager {
466   typedef llvm::FoldingSet<SymExpr> DataSetTy;
467   typedef llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy*> SymbolDependTy;
468
469   DataSetTy DataSet;
470   /// Stores the extra dependencies between symbols: the data should be kept
471   /// alive as long as the key is live.
472   SymbolDependTy SymbolDependencies;
473   unsigned SymbolCounter;
474   llvm::BumpPtrAllocator& BPAlloc;
475   BasicValueFactory &BV;
476   ASTContext &Ctx;
477
478 public:
479   SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
480                 llvm::BumpPtrAllocator& bpalloc)
481     : SymbolDependencies(16), SymbolCounter(0),
482       BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
483
484   ~SymbolManager();
485
486   static bool canSymbolicate(QualType T);
487
488   /// \brief Make a unique symbol for MemRegion R according to its kind.
489   const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
490
491   const SymbolConjured* getConjuredSymbol(const Stmt *E, QualType T,
492                                           unsigned VisitCount,
493                                           const void *SymbolTag = 0);
494
495   const SymbolConjured* getConjuredSymbol(const Expr *E, unsigned VisitCount,
496                                           const void *SymbolTag = 0) {
497     return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag);
498   }
499
500   const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
501                                         const TypedValueRegion *R);
502
503   const SymbolExtent *getExtentSymbol(const SubRegion *R);
504
505   /// \brief Creates a metadata symbol associated with a specific region.
506   ///
507   /// VisitCount can be used to differentiate regions corresponding to
508   /// different loop iterations, thus, making the symbol path-dependent.
509   const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt *S,
510                                           QualType T, unsigned VisitCount,
511                                           const void *SymbolTag = 0);
512
513   const SymbolCast* getCastSymbol(const SymExpr *Operand,
514                                   QualType From, QualType To);
515
516   const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
517                                   const llvm::APSInt& rhs, QualType t);
518
519   const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
520                                   const llvm::APSInt& rhs, QualType t) {
521     return getSymIntExpr(&lhs, op, rhs, t);
522   }
523
524   const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs,
525                                   BinaryOperator::Opcode op,
526                                   const SymExpr *rhs, QualType t);
527
528   const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
529                                   const SymExpr *rhs, QualType t);
530
531   QualType getType(const SymExpr *SE) const {
532     return SE->getType(Ctx);
533   }
534
535   /// \brief Add artificial symbol dependency.
536   ///
537   /// The dependent symbol should stay alive as long as the primary is alive.
538   void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
539
540   const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary);
541
542   ASTContext &getContext() { return Ctx; }
543   BasicValueFactory &getBasicVals() { return BV; }
544 };
545
546 class SymbolReaper {
547   enum SymbolStatus {
548     NotProcessed,
549     HaveMarkedDependents
550   };
551
552   typedef llvm::DenseSet<SymbolRef> SymbolSetTy;
553   typedef llvm::DenseMap<SymbolRef, SymbolStatus> SymbolMapTy;
554   typedef llvm::DenseSet<const MemRegion *> RegionSetTy;
555
556   SymbolMapTy TheLiving;
557   SymbolSetTy MetadataInUse;
558   SymbolSetTy TheDead;
559
560   RegionSetTy RegionRoots;
561   
562   const LocationContext *LCtx;
563   const Stmt *Loc;
564   SymbolManager& SymMgr;
565   StoreRef reapedStore;
566   llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
567
568 public:
569   SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr,
570                StoreManager &storeMgr)
571    : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {}
572
573   ~SymbolReaper() {}
574
575   const LocationContext *getLocationContext() const { return LCtx; }
576   const Stmt *getCurrentStatement() const { return Loc; }
577
578   bool isLive(SymbolRef sym);
579   bool isLiveRegion(const MemRegion *region);
580   bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
581   bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
582
583   /// \brief Unconditionally marks a symbol as live.
584   ///
585   /// This should never be
586   /// used by checkers, only by the state infrastructure such as the store and
587   /// environment. Checkers should instead use metadata symbols and markInUse.
588   void markLive(SymbolRef sym);
589
590   /// \brief Marks a symbol as important to a checker.
591   ///
592   /// For metadata symbols,
593   /// this will keep the symbol alive as long as its associated region is also
594   /// live. For other symbols, this has no effect; checkers are not permitted
595   /// to influence the life of other symbols. This should be used before any
596   /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
597   void markInUse(SymbolRef sym);
598
599   /// \brief If a symbol is known to be live, marks the symbol as live.
600   ///
601   ///  Otherwise, if the symbol cannot be proven live, it is marked as dead.
602   ///  Returns true if the symbol is dead, false if live.
603   bool maybeDead(SymbolRef sym);
604
605   typedef SymbolSetTy::const_iterator dead_iterator;
606   dead_iterator dead_begin() const { return TheDead.begin(); }
607   dead_iterator dead_end() const { return TheDead.end(); }
608
609   bool hasDeadSymbols() const {
610     return !TheDead.empty();
611   }
612   
613   typedef RegionSetTy::const_iterator region_iterator;
614   region_iterator region_begin() const { return RegionRoots.begin(); }
615   region_iterator region_end() const { return RegionRoots.end(); }
616
617   /// \brief Returns whether or not a symbol has been confirmed dead.
618   ///
619   /// This should only be called once all marking of dead symbols has completed.
620   /// (For checkers, this means only in the evalDeadSymbols callback.)
621   bool isDead(SymbolRef sym) const {
622     return TheDead.count(sym);
623   }
624   
625   void markLive(const MemRegion *region);
626   
627   /// \brief Set to the value of the symbolic store after
628   /// StoreManager::removeDeadBindings has been called.
629   void setReapedStore(StoreRef st) { reapedStore = st; }
630
631 private:
632   /// Mark the symbols dependent on the input symbol as live.
633   void markDependentsLive(SymbolRef sym);
634 };
635
636 class SymbolVisitor {
637 public:
638   /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
639   ///
640   /// The method returns \c true if symbols should continue be scanned and \c
641   /// false otherwise.
642   virtual bool VisitSymbol(SymbolRef sym) = 0;
643   virtual bool VisitMemRegion(const MemRegion *region) { return true; }
644   virtual ~SymbolVisitor();
645 };
646
647 } // end GR namespace
648
649 } // end clang namespace
650
651 namespace llvm {
652 static inline raw_ostream &operator<<(raw_ostream &os,
653                                             const clang::ento::SymExpr *SE) {
654   SE->dumpToStream(os);
655   return os;
656 }
657 } // end llvm namespace
658 #endif