Commit b944f689 authored by Bill Wendling's avatar Bill Wendling
Browse files

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.

------------------------------------------------------------------------

llvm-svn: 181401
parent bd8be40c
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -419,13 +419,15 @@ 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.
    if (KeepInsertionPoint)
      EmitBlock(createBasicBlock("throw.cont"));

    return;
@@ -440,6 +442,7 @@ 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.
    if (KeepInsertionPoint)
      EmitBlock(createBasicBlock("throw.cont"));
    return;
  }
@@ -478,6 +481,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {

  // throw is an expression, and the expression emitters expect us
  // to leave ourselves at a valid insertion point.
  if (KeepInsertionPoint)
    EmitBlock(createBasicBlock("throw.cont"));
}

+10 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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);

+26 −1
Original line number Diff line number Diff line
// 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