summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-06-20 18:43:47 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-06-20 18:43:47 +0000
commitf3076ff2fd325d7ea74ced48f2e741baceef6460 (patch)
treece1f564f0326917fa13562b1e2c4c8c4326617a5 /clang/lib
parent5c4a3d3118efaa97ea8b98954c4adee222f3fd41 (diff)
downloadbcm5719-llvm-f3076ff2fd325d7ea74ced48f2e741baceef6460.tar.gz
bcm5719-llvm-f3076ff2fd325d7ea74ced48f2e741baceef6460.zip
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
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp42
1 files changed, 32 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index fda04104b6c..62ecc7394ad 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2684,6 +2684,19 @@ LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) {
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 AbstractConditionalOperator *expr) {
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
OpenPOWER on IntegriCloud