diff options
author | Bill Wendling <isanbard@gmail.com> | 2013-05-08 09:20:56 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2013-05-08 09:20:56 +0000 |
commit | 6acf861cfca57327d2bb91027f75e3e6f73249b5 (patch) | |
tree | 0890d2178878359a2c5fd6aab07dcc5506f1bc2f | |
parent | 4066c53654fa11fc2e72e4b3b7f4be9153fadc08 (diff) |
Merging r181368:
------------------------------------------------------------------------
r181368 | rsmith | 2013-05-07 14:53:22 -0700 (Tue, 07 May 2013) | 3 lines
Don't crash in IRGen if a conditional with 'throw' in one of its branches is
used as a branch condition.
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_33@181401 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGException.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/throw-expressions.cpp | 27 |
4 files changed, 45 insertions, 6 deletions
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 36642bcc48..a088d78641 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -419,14 +419,16 @@ llvm::Value *CodeGenFunction::getSelectorFromSlot() { return Builder.CreateLoad(getEHSelectorSlot(), "sel"); } -void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { +void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E, + bool KeepInsertionPoint) { if (!E->getSubExpr()) { EmitNoreturnRuntimeCallOrInvoke(getReThrowFn(CGM), ArrayRef<llvm::Value*>()); // throw is an expression, and the expression emitters expect us // to leave ourselves at a valid insertion point. - EmitBlock(createBasicBlock("throw.cont")); + if (KeepInsertionPoint) + EmitBlock(createBasicBlock("throw.cont")); return; } @@ -440,7 +442,8 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { CGM.getObjCRuntime().EmitThrowStmt(*this, S, false); // This will clear insertion point which was not cleared in // call to EmitThrowStmt. - EmitBlock(createBasicBlock("throw.cont")); + if (KeepInsertionPoint) + EmitBlock(createBasicBlock("throw.cont")); return; } @@ -478,7 +481,8 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { // throw is an expression, and the expression emitters expect us // to leave ourselves at a valid insertion point. - EmitBlock(createBasicBlock("throw.cont")); + if (KeepInsertionPoint) + EmitBlock(createBasicBlock("throw.cont")); } void CodeGenFunction::EmitStartEHSpec(const Decl *D) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 791c1a8152..75c60edbba 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -928,6 +928,16 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, return; } + if (const CXXThrowExpr *Throw = dyn_cast<CXXThrowExpr>(Cond)) { + // Conditional operator handling can give us a throw expression as a + // condition for a case like: + // br(c ? throw x : y, t, f) -> br(c, br(throw x, t, f), br(y, t, f) + // Fold this to: + // br(c, throw x, br(y, t, f)) + EmitCXXThrowExpr(Throw, /*KeepInsertionPoint*/false); + return; + } + // Emit the code with the fully general case. llvm::Value *CondV = EvaluateExprAsBool(Cond); Builder.CreateCondBr(CondV, TrueBlock, FalseBlock); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 08e60c43ce..ff74c15c38 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2708,7 +2708,7 @@ public: } void enterNonTrivialFullExpression(const ExprWithCleanups *E); - void EmitCXXThrowExpr(const CXXThrowExpr *E); + void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true); void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest); diff --git a/test/CodeGenCXX/throw-expressions.cpp b/test/CodeGenCXX/throw-expressions.cpp index f04185b23f..22d7841065 100644 --- a/test/CodeGenCXX/throw-expressions.cpp +++ b/test/CodeGenCXX/throw-expressions.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -emit-llvm-only -verify %s -Wno-unreachable-code +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -Wno-unreachable-code -Werror -emit-llvm -o - %s | FileCheck %s // expected-no-diagnostics int val = 42; @@ -19,3 +19,28 @@ void test3() { int test4() { return 1 ? throw val : val; } + +// PR15923 +int test5(bool x, bool y, int z) { + return (x ? throw 1 : y) ? z : throw 2; +} +// CHECK: define i32 @_Z5test5bbi( +// CHECK: br i1 +// +// x.true: +// CHECK: call void @__cxa_throw( +// CHECK-NEXT: unreachable +// +// x.false: +// CHECK: br i1 +// +// y.true: +// CHECK: load i32* +// CHECK: br label +// +// y.false: +// CHECK: call void @__cxa_throw( +// CHECK-NEXT: unreachable +// +// end: +// CHECK: ret i32 |