From: Chris Lattner Date: Fri, 12 Dec 2008 05:35:08 +0000 (+0000) Subject: Fix rdar://6095061 - gcc allows __builtin_choose_expr as an lvalue X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=670a62cd1d51042ea076cda5e93f26a1d8327fb3;p=clang Fix rdar://6095061 - gcc allows __builtin_choose_expr as an lvalue git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60924 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index b5f966d862..728b13534a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -467,6 +467,13 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { } case CompoundLiteralExprClass: // C99 6.5.2.5p5 return LV_Valid; + case ChooseExprClass: + // __builtin_choose_expr is an lvalue if the selected operand is. + if (cast(this)->isConditionTrue(Ctx)) + return cast(this)->getLHS()->isLvalue(Ctx); + else + return cast(this)->getRHS()->isLvalue(Ctx); + case ExtVectorElementExprClass: if (cast(this)->containsDuplicateElements()) return LV_DuplicateVectorComponents; @@ -476,7 +483,7 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { case ObjCPropertyRefExprClass: // FIXME: check if read-only property. return LV_Valid; case ObjCKVCRefExprClass: // FIXME: check if read-only property. - return LV_Valid; + return LV_Valid; case PredefinedExprClass: return LV_Valid; case VAArgExprClass: @@ -1213,8 +1220,7 @@ bool ChooseExpr::isConditionTrue(ASTContext &C) const { return getCond()->getIntegerConstantExprValue(C) != 0; } -static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E) -{ +static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E) { if (const MemberExpr *ME = dyn_cast(E)) { QualType Ty = ME->getBase()->getType(); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index bdbd5caa08..a7a64e3860 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -146,6 +146,12 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::MemberExprClass: return EmitMemberExpr(cast(E)); case Expr::CompoundLiteralExprClass: return EmitCompoundLiteralLValue(cast(E)); + case Expr::ChooseExprClass: + // __builtin_choose_expr is the lvalue of the selected operand. + if (cast(E)->isConditionTrue(getContext())) + return EmitLValue(cast(E)->getLHS()); + else + return EmitLValue(cast(E)->getRHS()); } } diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c index db252b8d9d..1b8e13405f 100644 --- a/test/Sema/exprs.c +++ b/test/Sema/exprs.c @@ -38,3 +38,10 @@ void test7(int *P, _Complex float Gamma) { P = (P-42) + Gamma*4; // expected-error {{invalid operands to binary expression ('int *' and '_Complex float')}} } + +// rdar://6095061 +int test8(void) { + int i; + __builtin_choose_expr (0, 42, i) = 10; + return i; +}