Added support to GREngine/GRConstants for handling computed gotos.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47038 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp
index 86ac5ef..c239551 100644
--- a/Analysis/GRConstants.cpp
+++ b/Analysis/GRConstants.cpp
@@ -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 {