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. llvm-svn: 44322
This commit is contained in:
parent
a3ee6fa84f
commit
2ab40a6207
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: clang -emit-llvm %s
|
||||
// PR1824
|
||||
|
||||
int foo(int x, short y) {
|
||||
return x ?: y;
|
||||
}
|
Loading…
Reference in New Issue