[cfe-commits] r111076 - in /cfe/trunk: include/clang/Checker/PathSensitive/Checker.h include/clang/Checker/PathSensitive/SymbolManager.h include/clang/Checker/PathSensitive/ValueManager.h lib/Checker/GRExprEngine.cpp lib/Checker/SymbolManager.cpp

Jordy Rose jediknil at belkadan.com
Sat Aug 14 13:18:46 PDT 2010


Author: jrose
Date: Sat Aug 14 15:18:45 2010
New Revision: 111076

URL: http://llvm.org/viewvc/llvm-project?rev=111076&view=rev
Log:
Add a new metadata symbol type for checkers to use. Metadata symbols must be associated with a region and will be collected if the region dies or its checker fails to mark it as in use.

Modified:
    cfe/trunk/include/clang/Checker/PathSensitive/Checker.h
    cfe/trunk/include/clang/Checker/PathSensitive/SymbolManager.h
    cfe/trunk/include/clang/Checker/PathSensitive/ValueManager.h
    cfe/trunk/lib/Checker/GRExprEngine.cpp
    cfe/trunk/lib/Checker/SymbolManager.cpp

Modified: cfe/trunk/include/clang/Checker/PathSensitive/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/Checker.h?rev=111076&r1=111075&r2=111076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Checker/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/Checker/PathSensitive/Checker.h Sat Aug 14 15:18:45 2010
@@ -270,6 +270,8 @@
   virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
                            GRExprEngine &Eng) {}
 
+  virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
+
   virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
                                     GRExprEngine &Eng,
                                     const Stmt *Condition, void *tag) {}

Modified: cfe/trunk/include/clang/Checker/PathSensitive/SymbolManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/SymbolManager.h?rev=111076&r1=111075&r2=111076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Checker/PathSensitive/SymbolManager.h (original)
+++ cfe/trunk/include/clang/Checker/PathSensitive/SymbolManager.h Sat Aug 14 15:18:45 2010
@@ -40,6 +40,7 @@
 public:
   enum Kind { BEGIN_SYMBOLS,
               RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
+              MetadataKind,
               END_SYMBOLS,
               SymIntKind, SymSymKind };
 private:
@@ -190,6 +191,9 @@
   }
 };
 
+/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
+///  Clients should not ask the SymbolManager for a region's extent. Always use
+///  SubRegion::getExtent instead -- the value returned may not be a symbol.
 class SymbolExtent : public SymbolData {
   const SubRegion *R;
   
@@ -218,6 +222,51 @@
   }
 };
 
+/// SymbolMetadata - Represents path-dependent metadata about a specific region.
+///  Metadata symbols remain live as long as they are marked as in use before
+///  dead-symbol sweeping AND their associated regions are still alive.
+///  Intended for use by checkers.
+class SymbolMetadata : public SymbolData {
+  const MemRegion* R;
+  const Stmt* S;
+  QualType T;
+  unsigned Count;
+  const void* Tag;
+public:
+  SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t,
+                 unsigned count, const void* tag)
+  : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+
+  const MemRegion *getRegion() const { return R; }
+  const Stmt* getStmt() const { return S; }
+  unsigned getCount() const { return Count; }
+  const void* getTag() const { return Tag; }
+
+  QualType getType(ASTContext&) const;
+
+  void dumpToStream(llvm::raw_ostream &os) const;
+
+  static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
+                      const Stmt *S, QualType T, unsigned Count,
+                      const void *Tag) {
+    profile.AddInteger((unsigned) MetadataKind);
+    profile.AddPointer(R);
+    profile.AddPointer(S);
+    profile.Add(T);
+    profile.AddInteger(Count);
+    profile.AddPointer(Tag);
+  }
+
+  virtual void Profile(llvm::FoldingSetNodeID& profile) {
+    Profile(profile, R, S, T, Count, Tag);
+  }
+
+  // Implement isa<T> support.
+  static inline bool classof(const SymExpr* SE) {
+    return SE->getKind() == MetadataKind;
+  }
+};
+
 // SymIntExpr - Represents symbolic expression like 'x' + 3.
 class SymIntExpr : public SymExpr {
   const SymExpr *LHS;
@@ -336,6 +385,10 @@
 
   const SymbolExtent *getExtentSymbol(const SubRegion *R);
 
+  const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
+                                          QualType T, unsigned VisitCount,
+                                          const void* SymbolTag = 0);
+
   const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
                                   const llvm::APSInt& rhs, QualType t);
 
@@ -359,6 +412,7 @@
   typedef llvm::DenseSet<SymbolRef> SetTy;
 
   SetTy TheLiving;
+  SetTy MetadataInUse;
   SetTy TheDead;
   const LocationContext *LCtx;
   const Stmt *Loc;
@@ -374,12 +428,24 @@
   const Stmt *getCurrentStatement() const { return Loc; }
 
   bool isLive(SymbolRef sym);
-
   bool isLive(const Stmt *ExprVal) const;
-
   bool isLive(const VarRegion *VR) const;
-  
+
+  // markLive - Unconditionally marks a symbol as live. This should never be
+  //  used by checkers, only by the state infrastructure such as the store and
+  //  environment. Checkers should instead use metadata symbols and markInUse.
   void markLive(SymbolRef sym);
+
+  // markInUse - Marks a symbol as important to a checker. For metadata symbols,
+  //  this will keep the symbol alive as long as its associated region is also
+  //  live. For other symbols, this has no effect; checkers are not permitted
+  //  to influence the life of other symbols. This should be used before any
+  //  symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
+  void markInUse(SymbolRef sym);
+
+  // maybeDead - If a symbol is known to be live, marks the symbol as live.
+  //  Otherwise, if the symbol cannot be proven live, it is marked as dead.
+  //  Returns true if the symbol is dead, false if live.
   bool maybeDead(SymbolRef sym);
 
   typedef SetTy::const_iterator dead_iterator;
@@ -389,6 +455,13 @@
   bool hasDeadSymbols() const {
     return !TheDead.empty();
   }
+
+  /// isDead - Returns whether or not a symbol has been confirmed dead. This
+  ///  should only be called once all marking of dead symbols has completed.
+  ///  (For checkers, this means only in the EvalDeadSymbols callback.)
+  bool isDead(SymbolRef sym) const {
+    return TheDead.count(sym);
+  }
 };
 
 class SymbolVisitor {

Modified: cfe/trunk/include/clang/Checker/PathSensitive/ValueManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/ValueManager.h?rev=111076&r1=111075&r2=111076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Checker/PathSensitive/ValueManager.h (original)
+++ cfe/trunk/include/clang/Checker/PathSensitive/ValueManager.h Sat Aug 14 15:18:45 2010
@@ -106,6 +106,9 @@
   DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
                                                       const TypedRegion *R);
 
+  DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR,
+                                   const Expr *E, QualType T, unsigned Count);
+
   DefinedSVal getFunctionPointer(const FunctionDecl *FD);
   
   DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,

Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=111076&r1=111075&r2=111076&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Sat Aug 14 15:18:45 2010
@@ -578,15 +578,23 @@
     Builder->setAuditor(BatchAuditor.get());
 
   // Create the cleaned state.
-  const ExplodedNode *BasePred = Builder->getBasePredecessor();
+  const LocationContext *LC = EntryNode->getLocationContext();
+  SymbolReaper SymReaper(LC, CurrentStmt, SymMgr);
 
-  SymbolReaper SymReaper(BasePred->getLocationContext(), CurrentStmt, SymMgr);
+  if (AMgr.shouldPurgeDead()) {
+    const GRState *St = EntryNode->getState();
 
-  CleanedState = AMgr.shouldPurgeDead()
-    ? StateMgr.RemoveDeadBindings(EntryNode->getState(), 
-                         BasePred->getLocationContext()->getCurrentStackFrame(),
-                                  SymReaper)
-    : EntryNode->getState();
+    for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+         I != E; ++I) {
+      Checker *checker = I->second;
+      checker->MarkLiveSymbols(St, SymReaper);
+    }
+
+    const StackFrameContext *SFC = LC->getCurrentStackFrame();
+    CleanedState = StateMgr.RemoveDeadBindings(St, SFC, SymReaper);
+  } else {
+    CleanedState = EntryNode->getState();
+  }
 
   // Process any special transfer function for dead symbols.
   ExplodedNodeSet Tmp;

Modified: cfe/trunk/lib/Checker/SymbolManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/SymbolManager.cpp?rev=111076&r1=111075&r2=111076&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/SymbolManager.cpp (original)
+++ cfe/trunk/lib/Checker/SymbolManager.cpp Sat Aug 14 15:18:45 2010
@@ -78,6 +78,11 @@
   os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
 }
 
+void SymbolMetadata::dumpToStream(llvm::raw_ostream& os) const {
+  os << "meta_$" << getSymbolID() << '{'
+     << getRegion() << ',' << T.getAsString() << '}';
+}
+
 void SymbolRegionValue::dumpToStream(llvm::raw_ostream& os) const {
   os << "reg_$" << getSymbolID() << "<" << R << ">";
 }
@@ -150,6 +155,24 @@
   return cast<SymbolExtent>(SD);
 }
 
+const SymbolMetadata*
+SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt* S, QualType T,
+                                 unsigned Count, const void* SymbolTag) {
+
+  llvm::FoldingSetNodeID profile;
+  SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
+  void* InsertPos;
+  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+  if (!SD) {
+    SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
+    new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+    DataSet.InsertNode(SD, InsertPos);
+    ++SymbolCounter;
+  }
+
+  return cast<SymbolMetadata>(SD);
+}
+
 const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
                                                BinaryOperator::Opcode op,
                                                const llvm::APSInt& v,
@@ -198,6 +221,10 @@
   return Ctx.getSizeType();
 }
 
+QualType SymbolMetadata::getType(ASTContext&) const {
+  return T;
+}
+
 QualType SymbolRegionValue::getType(ASTContext& C) const {
   return R->getValueType();
 }
@@ -222,6 +249,11 @@
   TheDead.erase(sym);
 }
 
+void SymbolReaper::markInUse(SymbolRef sym) {
+  if (isa<SymbolMetadata>(sym))
+    MetadataInUse.insert(sym);
+}
+
 bool SymbolReaper::maybeDead(SymbolRef sym) {
   if (isLive(sym))
     return false;
@@ -230,6 +262,31 @@
   return true;
 }
 
+static bool IsLiveRegion(SymbolReaper &Reaper, const MemRegion *MR) {
+  MR = MR->getBaseRegion();
+
+  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+    return Reaper.isLive(SR->getSymbol());
+
+  if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
+    return Reaper.isLive(VR);
+
+  // FIXME: This is a gross over-approximation. What we really need is a way to
+  // tell if anything still refers to this region. Unlike SymbolicRegions,
+  // AllocaRegions don't have associated symbols, though, so we don't actually
+  // have a way to track their liveness.
+  if (isa<AllocaRegion>(MR))
+    return true;
+
+  if (isa<CXXThisRegion>(MR))
+    return true;
+
+  if (isa<MemSpaceRegion>(MR))
+    return true;
+
+  return false;
+}
+
 bool SymbolReaper::isLive(SymbolRef sym) {
   if (TheLiving.count(sym))
     return true;
@@ -243,11 +300,21 @@
   }
 
   if (const SymbolExtent *extent = dyn_cast<SymbolExtent>(sym)) {
-    const MemRegion *Base = extent->getRegion()->getBaseRegion();
-    if (const VarRegion *VR = dyn_cast<VarRegion>(Base))
-      return isLive(VR);
-    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Base))
-      return isLive(SR->getSymbol());
+    if (IsLiveRegion(*this, extent->getRegion())) {
+      markLive(sym);
+      return true;
+    }
+    return false;
+  }
+
+  if (const SymbolMetadata *metadata = dyn_cast<SymbolMetadata>(sym)) {
+    if (MetadataInUse.count(sym)) {
+      if (IsLiveRegion(*this, metadata->getRegion())) {
+        markLive(sym);
+        MetadataInUse.erase(sym);
+        return true;
+      }
+    }
     return false;
   }
 
@@ -261,12 +328,13 @@
 }
 
 bool SymbolReaper::isLive(const VarRegion *VR) const {
-  const StackFrameContext *SFC = VR->getStackFrame();
+  const StackFrameContext *VarContext = VR->getStackFrame();
+  const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
 
-  if (SFC == LCtx->getCurrentStackFrame())
+  if (VarContext == CurrentContext)
     return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl());
-  else
-    return SFC->isParentOf(LCtx->getCurrentStackFrame());
+
+  return VarContext->isParentOf(CurrentContext);
 }
 
 SymbolVisitor::~SymbolVisitor() {}





More information about the cfe-commits mailing list