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
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);
/// 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();
LHSExpr = SAVEExpr = CondExpr;
}
- QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
- RHSExpr, QuestionLoc);
+ QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr,
+ SAVEExpr, QuestionLoc);
if (result.isNull())
return ExprError();
/// 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.
// 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();
}
return Y != 0 ? : x;
}
+// rdar://8446940
+extern void abort();
+void test1 () {
+ char x[1];
+ char *y = x ? : 0;
+
+ if (x != y)
+ abort();
+}
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();
+}
+}