mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 12:16:06 +00:00
Don't crash when emitting a glvalue conditional where one arm is a
throw-expression. Based on a patch by Marius Wachtler! llvm-svn: 211388
This commit is contained in:
parent
5c4a3d3118
commit
f3076ff2fd
@ -2684,6 +2684,19 @@ LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) {
|
|||||||
return EmitLValue(E->getInit(0));
|
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::
|
LValue CodeGenFunction::
|
||||||
EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
|
EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
|
||||||
if (!expr->isGLValue()) {
|
if (!expr->isGLValue()) {
|
||||||
@ -2721,31 +2734,40 @@ EmitConditionalOperatorLValue(const AbstractConditionalOperator *expr) {
|
|||||||
EmitBlock(lhsBlock);
|
EmitBlock(lhsBlock);
|
||||||
Cnt.beginRegion(Builder);
|
Cnt.beginRegion(Builder);
|
||||||
eval.begin(*this);
|
eval.begin(*this);
|
||||||
LValue lhs = EmitLValue(expr->getTrueExpr());
|
Optional<LValue> lhs =
|
||||||
|
EmitLValueOrThrowExpression(*this, expr->getTrueExpr());
|
||||||
eval.end(*this);
|
eval.end(*this);
|
||||||
|
|
||||||
if (!lhs.isSimple())
|
if (lhs && !lhs->isSimple())
|
||||||
return EmitUnsupportedLValue(expr, "conditional operator");
|
return EmitUnsupportedLValue(expr, "conditional operator");
|
||||||
|
|
||||||
lhsBlock = Builder.GetInsertBlock();
|
lhsBlock = Builder.GetInsertBlock();
|
||||||
Builder.CreateBr(contBlock);
|
if (lhs)
|
||||||
|
Builder.CreateBr(contBlock);
|
||||||
|
|
||||||
// Any temporaries created here are conditional.
|
// Any temporaries created here are conditional.
|
||||||
EmitBlock(rhsBlock);
|
EmitBlock(rhsBlock);
|
||||||
eval.begin(*this);
|
eval.begin(*this);
|
||||||
LValue rhs = EmitLValue(expr->getFalseExpr());
|
Optional<LValue> rhs =
|
||||||
|
EmitLValueOrThrowExpression(*this, expr->getFalseExpr());
|
||||||
eval.end(*this);
|
eval.end(*this);
|
||||||
if (!rhs.isSimple())
|
if (rhs && !rhs->isSimple())
|
||||||
return EmitUnsupportedLValue(expr, "conditional operator");
|
return EmitUnsupportedLValue(expr, "conditional operator");
|
||||||
rhsBlock = Builder.GetInsertBlock();
|
rhsBlock = Builder.GetInsertBlock();
|
||||||
|
|
||||||
EmitBlock(contBlock);
|
EmitBlock(contBlock);
|
||||||
|
|
||||||
llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(), 2,
|
if (lhs && rhs) {
|
||||||
"cond-lvalue");
|
llvm::PHINode *phi = Builder.CreatePHI(lhs->getAddress()->getType(),
|
||||||
phi->addIncoming(lhs.getAddress(), lhsBlock);
|
2, "cond-lvalue");
|
||||||
phi->addIncoming(rhs.getAddress(), rhsBlock);
|
phi->addIncoming(lhs->getAddress(), lhsBlock);
|
||||||
return MakeAddrLValue(phi, expr->getType());
|
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
|
/// EmitCastLValue - Casts are never lvalues unless that cast is to a reference
|
||||||
|
@ -80,3 +80,35 @@ namespace DR1560 {
|
|||||||
// CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN6DR15601AD1Ev {{.*}} @_ZGRN6DR15601rE
|
// CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN6DR15601AD1Ev {{.*}} @_ZGRN6DR15601rE
|
||||||
// CHECK-NOT: call {{.*}}@_ZN6DR15601AD1Ev
|
// 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"));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user