r190125 - Avoid double edges when constructing CFGs

Pavel Labath labath at google.com
Fri Sep 6 01:12:48 PDT 2013


Author: labath
Date: Fri Sep  6 03:12:48 2013
New Revision: 190125

URL: http://llvm.org/viewvc/llvm-project?rev=190125&view=rev
Log:
Avoid double edges when constructing CFGs

Summary:
If a noreturn destructor is executed while returning a value from a function,
the resulting CFG has had two edges to the exit block. This crashed the analyzer,
because it expects that blocks with no terminators have only one outgoing edge.
I added code to avoid creating the second edge in this case.

PS: The crashes did not manifest themselves always, as usually the
NoReturnFunctionChecker would stop program evaluation before the analyzer hit
the assertion, but in the case of lifetime extended temporaries, the checker
failed to do that (which is a separate bug in itself).

Reviewers: jordan_rose

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1513

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/test/Analysis/cfg.cpp

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=190125&r1=190124&r2=190125&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Fri Sep  6 03:12:48 2013
@@ -1899,9 +1899,12 @@ CFGBlock *CFGBuilder::VisitReturnStmt(Re
   // Create the new block.
   Block = createBlock(false);
 
-  // The Exit block is the only successor.
   addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
-  addSuccessor(Block, &cfg->getExit());
+
+  // If the one of the destructors does not return, we already have the Exit
+  // block as a successor.
+  if (!Block->hasNoReturnElement())
+    addSuccessor(Block, &cfg->getExit());
 
   // Add the return statement to the block.  This may create new blocks if R
   // contains control-flow (short-circuit operations).

Modified: cfe/trunk/test/Analysis/cfg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cfg.cpp?rev=190125&r1=190124&r2=190125&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/cfg.cpp (original)
+++ cfe/trunk/test/Analysis/cfg.cpp Fri Sep  6 03:12:48 2013
@@ -144,3 +144,40 @@ void test_deleteArraydtor() {
   A *a = new A[5];
   delete[] a;
 }
+
+
+namespace NoReturnSingleSuccessor {
+  struct A {
+    A();
+    ~A();
+  };
+
+  struct B : public A {
+    B();
+    ~B() __attribute__((noreturn));
+  };
+
+// CHECK: ENTRY
+// CHECK: 1: 1
+// CHECK-NEXT: 2: return
+// CHECK-NEXT: ~B() (Implicit destructor)
+// CHECK-NEXT: Preds (1)
+// CHECK-NEXT: Succs (1): B0
+  int test1(int *x) {
+    B b;
+    if (x)
+      return 1;
+  }
+
+// CHECK: ENTRY
+// CHECK: 1: 1
+// CHECK-NEXT: 2: return
+// CHECK-NEXT: destructor
+// CHECK-NEXT: Preds (1)
+// CHECK-NEXT: Succs (1): B0
+  int test2(int *x) {
+    const A& a = B();
+    if (x)
+      return 1;
+  }
+}





More information about the cfe-commits mailing list