]> granicus.if.org Git - clang/commitdiff
Problem with gnu conditional extension with missing
authorFariborz Jahanian <fjahanian@apple.com>
Sat, 18 Sep 2010 19:38:38 +0000 (19:38 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Sat, 18 Sep 2010 19:38:38 +0000 (19:38 +0000)
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

include/clang/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
test/CodeGen/conditional-gnu-ext.c
test/CodeGenCXX/gnu-conditional-scalar-ext.cpp

index 1ef14a2284b999190bbb831238eea3f2e5b7d266..7708731947813e303b88955a651e7b0b7c02cc1f 100644 (file)
@@ -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);
 
index c65db7e835edcc6636253fd39e0df74ef1aa49c8..4bd596b6728508eeb1193253841862be0812fa66 100644 (file)
@@ -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();
 
index 30ac6189f74496b9c2d95b093e3022389657b15e..80dbe459ce97b205fe015c2b7dd7082c4565bd8e 100644 (file)
@@ -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();
   }
index f4ac81bf5934ac100160c17483222d07e06d34b2..5e5801af93c795583df5750a58990b0e873d4b0d 100644 (file)
@@ -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();
+}
index 8c529c30e1783d7d19d3907f73cfde63382d1732..dfd9d41489558ec89aae30c7f786435217536ef7 100644 (file)
@@ -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();
+}
+}