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