diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 7 | ||||
-rw-r--r-- | clang/test/Analysis/cfg.cpp | 37 |
2 files changed, 42 insertions, 2 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 5e03f4377d3..191c324b3c6 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1899,9 +1899,12 @@ CFGBlock *CFGBuilder::VisitReturnStmt(ReturnStmt *R) { // 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). diff --git a/clang/test/Analysis/cfg.cpp b/clang/test/Analysis/cfg.cpp index 243e1aed99c..660d1f26469 100644 --- a/clang/test/Analysis/cfg.cpp +++ b/clang/test/Analysis/cfg.cpp @@ -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; + } +} |