vsk created this revision.
vsk added reviewers: ygao, rsmith.
vsk added a subscriber: cfe-commits.

When partially initializing a global, exception-handling code in the frontend 
emits a placeholder `%invoke.cont` block with no terminator. This commit adds a 
suitable BranchInst to the block to prevent "malformed BasicBlock" errors.
    
A test case is included.

Note: I have been struggling to understand why throwing an error in a 
destructor causes exception-handling code to be generated when invoking the 
constructor [esp. when the constructor does not throw anything]. This patch is 
meant as a workaround until the 'real' issue can be addressed.

http://reviews.llvm.org/D12412

Files:
  lib/CodeGen/CGExprAgg.cpp
  test/CodeGenCXX/partial-init.cpp

Index: test/CodeGenCXX/partial-init.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/partial-init.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-obj -std=c++11 -x c++ \
+// RUN: -fcxx-exceptions -fexceptions -S -emit-llvm -o - %s | FileCheck %s
+
+namespace std {
+  struct string {
+    const char *p;
+    string(const char *s) : p(s) {}
+    ~string() { throw 0; }
+  };
+}
+
+struct Bar {
+  int a;
+};
+
+struct Foo {
+  int b;
+  std::string c;
+  Bar d[32];
+};
+
+static Foo table[] = {
+  { 0, "blerg" },
+};
+
+// CHECK-NOT: does not have terminator
+// CHECK-NOT: Broken function found, compilation aborted
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -493,6 +493,12 @@
     llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
     llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body");
 
+    // The exception-handling code in VisitInitListExpr may mark entryBB as
+    // a placeholder with an UnreachableInst. Branch to bodyBB as intended.
+    if (dyn_cast_or_null<llvm::UnreachableInst>(entryBB->getTerminator())) {
+      llvm::BranchInst::Create(bodyBB, entryBB);
+    }
+
     // Jump into the body.
     CGF.EmitBlock(bodyBB);
     llvm::PHINode *currentElement =


Index: test/CodeGenCXX/partial-init.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/partial-init.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-obj -std=c++11 -x c++ \
+// RUN: -fcxx-exceptions -fexceptions -S -emit-llvm -o - %s | FileCheck %s
+
+namespace std {
+  struct string {
+    const char *p;
+    string(const char *s) : p(s) {}
+    ~string() { throw 0; }
+  };
+}
+
+struct Bar {
+  int a;
+};
+
+struct Foo {
+  int b;
+  std::string c;
+  Bar d[32];
+};
+
+static Foo table[] = {
+  { 0, "blerg" },
+};
+
+// CHECK-NOT: does not have terminator
+// CHECK-NOT: Broken function found, compilation aborted
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -493,6 +493,12 @@
     llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
     llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body");
 
+    // The exception-handling code in VisitInitListExpr may mark entryBB as
+    // a placeholder with an UnreachableInst. Branch to bodyBB as intended.
+    if (dyn_cast_or_null<llvm::UnreachableInst>(entryBB->getTerminator())) {
+      llvm::BranchInst::Create(bodyBB, entryBB);
+    }
+
     // Jump into the body.
     CGF.EmitBlock(bodyBB);
     llvm::PHINode *currentElement =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to