[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