forked from OSchip/llvm-project
Don't crash in IRGen if a conditional with 'throw' in one of its branches is
used as a branch condition. llvm-svn: 181368
This commit is contained in:
parent
78f05f13ad
commit
ea85232c40
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue