r211388 - Don't crash when emitting a glvalue conditional where one arm is a

Richard Smith richard-llvm at metafoo.co.uk
Fri Jun 20 11:43:47 PDT 2014


Author: rsmith
Date: Fri Jun 20 13:43:47 2014
New Revision: 211388

URL: http://llvm.org/viewvc/llvm-project?rev=211388&view=rev
Log:
Don't crash when emitting a glvalue conditional where one arm is a
throw-expression. Based on a patch by Marius Wachtler!

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/test/CodeGenCXX/throw-expressions.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=211388&r1=211387&r2=211388&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Jun 20 13:43:47 2014
@@ -2684,6 +2684,19 @@ LValue CodeGenFunction::EmitInitListLVal
   return EmitLValue(E->getInit(0));
 }
 
+/// Emit the operand of a glvalue conditional operator. This is either a glvalue
+/// or a (possibly-parenthesized) throw-expression. If this is a throw, no
+/// LValue is returned and the current block has been terminated.
+static Optional<LValue> EmitLValueOrThrowExpression(CodeGenFunction &CGF,
+                                                    const Expr *Operand) {
+  if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Operand->IgnoreParens())) {
+    CGF.EmitCXXThrowExpr(ThrowExpr, /*KeepInsertionPoint*/false);
+    return None;
+  }
+
+  return CGF.EmitLValue(Operand);
+}
+
 LValue CodeGenFunction::
 EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
   if (!expr->isGLValue()) {
@@ -2721,31 +2734,40 @@ EmitConditionalOperatorLValue(const Abst
   EmitBlock(lhsBlock);
   Cnt.beginRegion(Builder);
   eval.begin(*this);
-  LValue lhs = EmitLValue(expr->getTrueExpr());
+  Optional<LValue> lhs =
+      EmitLValueOrThrowExpression(*this, expr->getTrueExpr());
   eval.end(*this);
 
-  if (!lhs.isSimple())
+  if (lhs && !lhs->isSimple())
     return EmitUnsupportedLValue(expr, "conditional operator");
 
   lhsBlock = Builder.GetInsertBlock();
-  Builder.CreateBr(contBlock);
+  if (lhs)
+    Builder.CreateBr(contBlock);
 
   // Any temporaries created here are conditional.
   EmitBlock(rhsBlock);
   eval.begin(*this);
-  LValue rhs = EmitLValue(expr->getFalseExpr());
+  Optional<LValue> rhs =
+      EmitLValueOrThrowExpression(*this, expr->getFalseExpr());
   eval.end(*this);
-  if (!rhs.isSimple())
+  if (rhs && !rhs->isSimple())
     return EmitUnsupportedLValue(expr, "conditional operator");
   rhsBlock = Builder.GetInsertBlock();
 
   EmitBlock(contBlock);
 
-  llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(), 2,
-                                         "cond-lvalue");
-  phi->addIncoming(lhs.getAddress(), lhsBlock);
-  phi->addIncoming(rhs.getAddress(), rhsBlock);
-  return MakeAddrLValue(phi, expr->getType());
+  if (lhs && rhs) {
+    llvm::PHINode *phi = Builder.CreatePHI(lhs->getAddress()->getType(),
+                                           2, "cond-lvalue");
+    phi->addIncoming(lhs->getAddress(), lhsBlock);
+    phi->addIncoming(rhs->getAddress(), rhsBlock);
+    return MakeAddrLValue(phi, expr->getType());
+  } else {
+    assert((lhs || rhs) &&
+           "both operands of glvalue conditional are throw-expressions?");
+    return lhs ? *lhs : *rhs;
+  }
 }
 
 /// EmitCastLValue - Casts are never lvalues unless that cast is to a reference

Modified: cfe/trunk/test/CodeGenCXX/throw-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/throw-expressions.cpp?rev=211388&r1=211387&r2=211388&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/throw-expressions.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/throw-expressions.cpp Fri Jun 20 13:43:47 2014
@@ -80,3 +80,35 @@ namespace DR1560 {
   // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN6DR15601AD1Ev {{.*}} @_ZGRN6DR15601rE
   // CHECK-NOT: call {{.*}}@_ZN6DR15601AD1Ev
 }
+
+// CHECK-LABEL: define void @_Z5test7b(
+void test7(bool cond) {
+  // CHECK: br i1
+  //
+  // x.true:
+  // CHECK: call void @__cxa_throw(
+  // CHECK-NEXT: unreachable
+  //
+  // x.false:
+  // CHECK: br label
+  //
+  // end:
+  // CHECK: ret void
+  cond ? throw test7 : val;
+}
+
+// CHECK-LABEL: define nonnull i32* @_Z5test8b(
+int &test8(bool cond) {
+  // CHECK: br i1
+  //
+  // x.true:
+  // CHECK: br label
+  //
+  // x.false:
+  // CHECK: call void @__cxa_throw(
+  // CHECK-NEXT: unreachable
+  //
+  // end:
+  // CHECK: ret i32* @val
+  return cond ? val : ((throw "foo"));
+}





More information about the cfe-commits mailing list