Sema::CheckConditionalOperands(): Soften pointer/integer mismatch from error->warning.
Fixes <rdar://problem/6762239> [sema] gcc incompatibility; error on incompatible operand types in ?:.
llvm-svn: 68617
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4dbd12d..3245323 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1207,6 +1207,8 @@
"incompatible operand types (%0 and %1)">;
def warn_typecheck_cond_incompatible_pointers : Warning<
"pointer type mismatch (%0 and %1)">;
+def warn_typecheck_cond_pointer_integer_mismatch : Warning<
+ "pointer/integer type mismatch in conditional expression (%0 and %1)">;
def err_typecheck_choose_expr_requires_constant : Error<
"'__builtin_choose_expr' requires a constant expression">;
def ext_typecheck_expression_not_constant_but_accepted : Extension<
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index d442b1f..4f8ad5b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2714,6 +2714,20 @@
}
}
+ // GCC compatibility: soften pointer/integer mismatch.
+ if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
+ Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ ImpCastExprToType(LHS, RHSTy); // promote the integer to a pointer.
+ return RHSTy;
+ }
+ if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
+ Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
+ << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
+ ImpCastExprToType(RHS, LHSTy); // promote the integer to a pointer.
+ return LHSTy;
+ }
+
// Selection between block pointer types is ok as long as they are the same.
if (LHSTy->isBlockPointerType() && RHSTy->isBlockPointerType() &&
Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy))
diff --git a/clang/test/Sema/conditional-expr.c b/clang/test/Sema/conditional-expr.c
index c068113..1f0a9de 100644
--- a/clang/test/Sema/conditional-expr.c
+++ b/clang/test/Sema/conditional-expr.c
@@ -40,3 +40,12 @@
char x;
return ((((&x) != ((void *) 0)) ? (*(&x) = ((char) 1)) : (void) ((void *) 0)), (unsigned long) ((void *) 0)); // expected-warning {{C99 forbids conditional expressions with only one void side}}
}
+
+#define nil ((void*) 0)
+
+extern int f1(void);
+
+int f0(int a) {
+ // GCC considers this a warning.
+ return a ? f1() : nil; // expected-warning {{pointer/integer type mismatch in conditional expression ('int' and 'void *')}} expected-warning {{incompatible pointer to integer conversion returning 'void *', expected 'int'}}
+}