[cfe-commits] r47038 - in /cfe/trunk: Analysis/GRConstants.cpp Analysis/GREngine.cpp include/clang/Analysis/PathSensitive/ExplodedGraph.h include/clang/Analysis/PathSensitive/GREngine.h include/clang/Analysis/ProgramPoint.h
Ted Kremenek
kremenek at apple.com
Tue Feb 12 16:24:46 PST 2008
Author: kremenek
Date: Tue Feb 12 18:24:44 2008
New Revision: 47038
URL: http://llvm.org/viewvc/llvm-project?rev=47038&view=rev
Log:
Added support to GREngine/GRConstants for handling computed gotos.
Modified:
cfe/trunk/Analysis/GRConstants.cpp
cfe/trunk/Analysis/GREngine.cpp
cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
cfe/trunk/include/clang/Analysis/ProgramPoint.h
Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=47038&r1=47037&r2=47038&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Tue Feb 12 18:24:44 2008
@@ -67,6 +67,7 @@
typedef ValueStateManager::StateTy StateTy;
typedef GRStmtNodeBuilder<GRConstants> StmtNodeBuilder;
typedef GRBranchNodeBuilder<GRConstants> BranchNodeBuilder;
+ typedef GRIndirectGotoNodeBuilder<GRConstants> IndirectGotoNodeBuilder;
typedef ExplodedGraph<GRConstants> GraphTy;
typedef GraphTy::NodeTy NodeTy;
@@ -192,6 +193,10 @@
/// nodes by processing the 'effects' of a branch condition.
void ProcessBranch(Expr* Condition, Stmt* Term, BranchNodeBuilder& builder);
+ /// ProcessIndirectGoto - Called by GREngine. Used to generate successor
+ /// nodes by processing the 'effects' of a computed goto jump.
+ void ProcessIndirectGoto(IndirectGotoNodeBuilder& builder);
+
/// RemoveDeadBindings - Return a new state that is the same as 'St' except
/// that all subexpression mappings are removed and that any
/// block-level expressions that are not live at 'S' also have their
@@ -424,6 +429,52 @@
builder.markInfeasible(false);
}
+/// ProcessIndirectGoto - Called by GREngine. Used to generate successor
+/// nodes by processing the 'effects' of a computed goto jump.
+void GRConstants::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
+
+ StateTy St = builder.getState();
+ LValue V = cast<LValue>(GetValue(St, builder.getTarget()));
+
+ // Three possibilities:
+ //
+ // (1) We know the computed label.
+ // (2) The label is NULL (or some other constant), or Uninitialized.
+ // (3) We have no clue about the label. Dispatch to all targets.
+ //
+
+ typedef IndirectGotoNodeBuilder::iterator iterator;
+
+ if (isa<lval::GotoLabel>(V)) {
+ LabelStmt* L = cast<lval::GotoLabel>(V).getLabel();
+
+ for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {
+ IndirectGotoNodeBuilder::Destination D = *I;
+
+ if (D.getLabel() == L) {
+ builder.generateNode(D, St);
+ return;
+ }
+ }
+
+ assert (false && "No block with label.");
+ return;
+ }
+
+ if (isa<lval::ConcreteInt>(V) || isa<UninitializedVal>(V)) {
+ // Dispatch to the first target and mark it as a sink.
+ NodeTy* N = builder.generateNode(*builder.begin(), St, true);
+ UninitBranches.insert(N);
+ return;
+ }
+
+ // This is really a catch-all. We don't support symbolics yet.
+
+ assert (isa<UnknownVal>(V));
+
+ for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
+ builder.generateNode(*I, St);
+}
void GRConstants::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
NodeSet& Dst) {
@@ -1305,7 +1356,7 @@
Out << "\\|Terminator: ";
E.getSrc()->printTerminator(Out);
- if (isa<SwitchStmt>(T)) {
+ if (isa<SwitchStmt>(T) || isa<IndirectGotoStmt>(T)) {
// FIXME
}
else {
Modified: cfe/trunk/Analysis/GREngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GREngine.cpp?rev=47038&r1=47037&r2=47038&view=diff
==============================================================================
--- cfe/trunk/Analysis/GREngine.cpp (original)
+++ cfe/trunk/Analysis/GREngine.cpp Tue Feb 12 18:24:44 2008
@@ -198,6 +198,18 @@
case Stmt::IfStmtClass:
HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
return;
+
+ case Stmt::IndirectGotoStmtClass: {
+ // Only 1 successor: the indirect goto dispatch block.
+ assert (B->succ_size() == 1);
+
+ GRIndirectGotoNodeBuilderImpl
+ builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
+ *(B->succ_begin()), this);
+
+ ProcessIndirectGoto(builder);
+ return;
+ }
case Stmt::WhileStmtClass:
HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
@@ -346,3 +358,46 @@
for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
}
+
+GRIndirectGotoNodeBuilderImpl::Destination
+GRIndirectGotoNodeBuilderImpl::Iterator::operator*() {
+ CFGBlock* B = *I;
+ assert (!B->empty());
+ LabelStmt* L = cast<LabelStmt>(B->getLabel());
+ return Destination(L, *I);
+}
+
+GRIndirectGotoNodeBuilderImpl::Iterator
+GRIndirectGotoNodeBuilderImpl::begin() {
+ return Iterator(DispatchBlock.succ_begin());
+}
+
+GRIndirectGotoNodeBuilderImpl::Iterator
+GRIndirectGotoNodeBuilderImpl::end() {
+ return Iterator(DispatchBlock.succ_end());
+}
+
+ExplodedNodeImpl*
+GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Destination& D,
+ void* St,
+ bool isSink) {
+ bool IsNew;
+
+ ExplodedNodeImpl* Succ =
+ Eng.G->getNodeImpl(BlockEdge(Eng.getCFG(), Src, D.getBlock(), true),
+ St, &IsNew);
+
+ Succ->addPredecessor(Pred);
+
+ if (IsNew) {
+
+ if (isSink)
+ Succ->markAsSink();
+ else
+ Eng.WList->Enqueue(Succ);
+
+ return Succ;
+ }
+
+ return NULL;
+}
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h?rev=47038&r1=47037&r2=47038&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h Tue Feb 12 18:24:44 2008
@@ -30,6 +30,7 @@
class ExplodedNodeImpl;
class GRStmtNodeBuilderImpl;
class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
class CFG;
class ASTContext;
class FunctionDecl;
@@ -41,6 +42,7 @@
friend class GREngineImpl;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
class NodeGroup {
enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
@@ -195,6 +197,7 @@
friend class GREngineImpl;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
// Type definitions.
typedef llvm::DenseMap<ProgramPoint,void*> EdgeNodeSetMap;
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h?rev=47038&r1=47037&r2=47038&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h Tue Feb 12 18:24:44 2008
@@ -24,12 +24,15 @@
class GRStmtNodeBuilderImpl;
class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
class GRWorkList;
+class LabelStmt;
class GREngineImpl {
protected:
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
@@ -78,6 +81,7 @@
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& Builder) = 0;
+ virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
private:
GREngineImpl(const GREngineImpl&); // Do not implement.
@@ -246,6 +250,87 @@
}
};
+class GRIndirectGotoNodeBuilderImpl {
+ GREngineImpl& Eng;
+ CFGBlock* Src;
+ CFGBlock& DispatchBlock;
+ Expr* E;
+ ExplodedNodeImpl* Pred;
+public:
+ GRIndirectGotoNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
+ Expr* e, CFGBlock* dispatch,
+ GREngineImpl* eng)
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+
+ class Iterator;
+
+ class Destination {
+ LabelStmt* L;
+ CFGBlock* B;
+
+ friend class Iterator;
+ Destination(LabelStmt* l, CFGBlock* b) : L(l), B(b) {}
+
+ public:
+ CFGBlock* getBlock() const { return B; }
+ LabelStmt* getLabel() const { return L; }
+ };
+
+ class Iterator {
+ CFGBlock::succ_iterator I;
+
+ friend class GRIndirectGotoNodeBuilderImpl;
+ Iterator(CFGBlock::succ_iterator i) : I(i) {}
+ public:
+
+ Iterator& operator++() { ++I; return *this; }
+ bool operator!=(const Iterator& X) const { return I != X.I; }
+
+ Destination operator*();
+ };
+
+ Iterator begin();
+ Iterator end();
+
+ ExplodedNodeImpl* generateNodeImpl(const Destination& D, void* State,
+ bool isSink);
+
+ inline Expr* getTarget() const { return E; }
+ inline void* getState() const { return Pred->State; }
+};
+
+template<typename CHECKER>
+class GRIndirectGotoNodeBuilder {
+ typedef CHECKER CheckerTy;
+ typedef typename CheckerTy::StateTy StateTy;
+ typedef ExplodedGraph<CheckerTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+ GRIndirectGotoNodeBuilderImpl& NB;
+
+public:
+ GRIndirectGotoNodeBuilder(GRIndirectGotoNodeBuilderImpl& nb) : NB(nb) {}
+
+ typedef GRIndirectGotoNodeBuilderImpl::Iterator iterator;
+ typedef GRIndirectGotoNodeBuilderImpl::Destination Destination;
+
+ inline iterator begin() { return NB.begin(); }
+ inline iterator end() { return NB.end(); }
+
+ inline Expr* getTarget() const { return NB.getTarget(); }
+
+ inline NodeTy* generateNode(const Destination& D, StateTy St,
+ bool isSink = false) {
+
+ void *state = GRTrait<StateTy>::toPtr(St);
+ return static_cast<NodeTy*>(NB.generateNodeImpl(D, state, isSink));
+ }
+
+ inline StateTy getState() const {
+ return GRTrait<StateTy>::toState(NB.getState());
+ }
+};
+
template<typename CHECKER>
class GREngine : public GREngineImpl {
@@ -274,13 +359,16 @@
Checker->ProcessStmt(S, Builder);
}
-
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& BuilderImpl) {
GRBranchNodeBuilder<CHECKER> Builder(BuilderImpl);
Checker->ProcessBranch(Condition, Terminator, Builder);
}
+ virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
+ GRIndirectGotoNodeBuilder<CHECKER> Builder(BuilderImpl);
+ Checker->ProcessIndirectGoto(Builder);
+ }
public:
/// Construct a GREngine object to analyze the provided CFG using
Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=47038&r1=47037&r2=47038&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original)
+++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Tue Feb 12 18:24:44 2008
@@ -104,6 +104,15 @@
typedef std::pair<CFGBlock*,CFGBlock*> BPair;
public:
BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2);
+
+ /// This ctor forces the BlockEdge to be constructed using an explicitly
+ /// allocated pair object that is stored in the CFG. This is usually
+ /// used to construct edges representing jumps using computed gotos.
+ BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2, bool) {
+ Data = reinterpret_cast<uintptr_t>(cfg.getBlockEdgeImpl(B1, B2))
+ | BlockEdgeAuxKind;
+ }
+
CFGBlock* getSrc() const;
CFGBlock* getDst() const;
More information about the cfe-commits
mailing list