aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-11-26 01:40:58 +0000
committerChris Lattner <sabre@nondot.org>2007-11-26 01:40:58 +0000
commita21ddb30e56026967d58e26c5212744e1831305b (patch)
tree51d4a01a7dbdea82e7448fe68e8e3772ee7336a1
parent09376fd7f7ea9b4a4846c3d9cd1bfade17e5ac8d (diff)
Fix sema support for the gnu ?: expression with a
missing middle expression, and fix a codegen bug where we didn't correctly promote the condition to the right result type. This fixes PR1824. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44322 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--CodeGen/CGExprScalar.cpp16
-rw-r--r--Sema/SemaExpr.cpp15
-rw-r--r--test/CodeGen/conditional-gnu-ext.c6
3 files changed, 31 insertions, 6 deletions
diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp
index 669928b6f0..f0a75dbf13 100644
--- a/CodeGen/CGExprScalar.cpp
+++ b/CodeGen/CGExprScalar.cpp
@@ -884,13 +884,23 @@ VisitConditionalOperator(const ConditionalOperator *E) {
llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:");
llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont");
- Value *Cond = CGF.EvaluateExprAsBool(E->getCond());
- Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
+ // Evaluate the conditional, then convert it to bool. We do this explicitly
+ // because we need the unconverted value if this is a GNU ?: expression with
+ // missing middle value.
+ Value *CondVal = CGF.EmitScalarExpr(E->getCond());
+ Value *CondBoolVal = CGF.EmitScalarConversion(CondVal, E->getCond()->getType(),
+ CGF.getContext().BoolTy);
+ Builder.CreateCondBr(CondBoolVal, LHSBlock, RHSBlock);
CGF.EmitBlock(LHSBlock);
// Handle the GNU extension for missing LHS.
- Value *LHS = E->getLHS() ? Visit(E->getLHS()) : Cond;
+ Value *LHS;
+ if (E->getLHS())
+ LHS = Visit(E->getLHS());
+ else // Perform promotions, to handle cases like "short ?: int"
+ LHS = EmitScalarConversion(CondVal, E->getCond()->getType(), E->getType());
+
Builder.CreateBr(ContBlock);
LHSBlock = Builder.GetInsertBlock();
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index a9cd41580b..dcec7253ea 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -738,6 +738,8 @@ static void promoteExprToType(Expr *&expr, QualType type) {
return;
}
+/// Note that lex is not null here, even if this is the gnu "x ?: y" extension.
+/// In that case, lex = cond.
inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
Expr *&cond, Expr *&lex, Expr *&rex, SourceLocation questionLoc) {
UsualUnaryConversions(cond);
@@ -760,8 +762,7 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15
}
if (const RecordType *LHSRT = lexT->getAsRecordType()) { // C99 6.5.15p3
if (const RecordType *RHSRT = rexT->getAsRecordType()) {
-
- if (LHSRT->getDecl()->getIdentifier() ==RHSRT->getDecl()->getIdentifier())
+ if (LHSRT->getDecl() == RHSRT->getDecl())
return lexT;
Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
@@ -826,11 +827,19 @@ Action::ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ExprTy *RHS) {
Expr *CondExpr = (Expr *) Cond;
Expr *LHSExpr = (Expr *) LHS, *RHSExpr = (Expr *) RHS;
+
+ // If this is the gnu "x ?: y" extension, analyze the types as though the LHS
+ // was the condition.
+ bool isLHSNull = LHSExpr == 0;
+ if (isLHSNull)
+ LHSExpr = CondExpr;
+
QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
RHSExpr, QuestionLoc);
if (result.isNull())
return true;
- return new ConditionalOperator(CondExpr, LHSExpr, RHSExpr, result);
+ return new ConditionalOperator(CondExpr, isLHSNull ? 0 : LHSExpr,
+ RHSExpr, result);
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
diff --git a/test/CodeGen/conditional-gnu-ext.c b/test/CodeGen/conditional-gnu-ext.c
new file mode 100644
index 0000000000..5b2eb3f3d5
--- /dev/null
+++ b/test/CodeGen/conditional-gnu-ext.c
@@ -0,0 +1,6 @@
+// RUN: clang -emit-llvm %s
+// PR1824
+
+int foo(int x, short y) {
+ return x ?: y;
+}