From: Fariborz Jahanian Date: Sat, 18 Sep 2010 19:38:38 +0000 (+0000) Subject: Problem with gnu conditional extension with missing X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1fb019bf42f5757c027edb56e5bb70233787a39c;p=clang Problem with gnu conditional extension with missing LHS and when conditional expression is an array. Since it will be decayed, saved expression must be saved with decayed expression. This is necessary to preserve semantics of this extension (and prevent an IRGen crash which expects an array to always be decayed). I am sure there will be other cases in c++ (aggregate conditionals for example) when saving of the expression must happen after some transformation on conditional expression has happened. Doug, please review. Fixes // rdar://8446940 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114296 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1ef14a2284..7708731947 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4113,9 +4113,11 @@ public: QualType CheckCommaOperands( // C99 6.5.17 Expr *lex, Expr *&rex, SourceLocation OpLoc); QualType CheckConditionalOperands( // C99 6.5.15 - Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc); + Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save, + SourceLocation questionLoc); QualType CXXCheckConditionalOperands( // C++ 5.16 - Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc); + Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save, + SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool *NonStandardCompositeType = 0); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c65db7e835..4bd596b672 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4203,13 +4203,18 @@ ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, /// In that case, lhs = cond. /// C99 6.5.15 QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, + Expr *&SAVE, SourceLocation QuestionLoc) { // C++ is sufficiently different to merit its own checker. if (getLangOptions().CPlusPlus) - return CXXCheckConditionalOperands(Cond, LHS, RHS, QuestionLoc); + return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE, QuestionLoc); UsualUnaryConversions(Cond); - UsualUnaryConversions(LHS); + if (SAVE) { + SAVE = LHS = Cond; + } + else + UsualUnaryConversions(LHS); UsualUnaryConversions(RHS); QualType CondTy = Cond->getType(); QualType LHSTy = LHS->getType(); @@ -4534,8 +4539,8 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, LHSExpr = SAVEExpr = CondExpr; } - QualType result = CheckConditionalOperands(CondExpr, LHSExpr, - RHSExpr, QuestionLoc); + QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr, + SAVEExpr, QuestionLoc); if (result.isNull()) return ExprError(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 30ac6189f7..80dbe459ce 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2490,6 +2490,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) { /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y /// extension. In this case, LHS == Cond. (But they're not aliases.) QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, + Expr *&SAVE, SourceLocation QuestionLoc) { // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++ // interface pointers. @@ -2497,6 +2498,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C++0x 5.16p1 // The first expression is contextually converted to bool. if (!Cond->isTypeDependent()) { + if (SAVE && Cond->getType()->isArrayType()) { + QualType CondTy = Cond->getType(); + CondTy = Context.getArrayDecayedType(CondTy); + ImpCastExprToType(Cond, CondTy, CK_ArrayToPointerDecay); + SAVE = LHS = Cond; + } if (CheckCXXBooleanCondition(Cond)) return QualType(); } diff --git a/test/CodeGen/conditional-gnu-ext.c b/test/CodeGen/conditional-gnu-ext.c index f4ac81bf59..5e5801af93 100644 --- a/test/CodeGen/conditional-gnu-ext.c +++ b/test/CodeGen/conditional-gnu-ext.c @@ -10,3 +10,12 @@ float test(float x, int Y) { return Y != 0 ? : x; } +// rdar://8446940 +extern void abort(); +void test1 () { + char x[1]; + char *y = x ? : 0; + + if (x != y) + abort(); +} diff --git a/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp b/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp index 8c529c30e1..dfd9d41489 100644 --- a/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp +++ b/test/CodeGenCXX/gnu-conditional-scalar-ext.cpp @@ -9,3 +9,16 @@ int main(int argc, char **argv) { printf("%p\n", (void *)0xdeadbeef ? : (void *)0xaaaaaa); return 0; } + +// rdar://8446940 +namespace radar8446940 { +extern "C" void abort(); + +int main () { + char x[1]; + char *y = x ? : 0; + + if (x != y) + abort(); +} +}