From ea4c780da19e11edc9d13a09b51a6eb6b7446e11 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Wed, 8 Apr 2009 17:05:15 +0000 Subject: [PATCH] Sema::CheckConditionalOperands(): Soften pointer/integer mismatch from error->warning. Fixes [sema] gcc incompatibility; error on incompatible operand types in ?:. llvm-svn: 68617 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaExpr.cpp | 14 ++++++++++++++ clang/test/Sema/conditional-expr.c | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4dbd12dd9fd0..3245323a74ba 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1207,6 +1207,8 @@ def err_typecheck_cond_incompatible_operands : Error< "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 d442b1fc5837..4f8ad5b4a5e8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2714,6 +2714,20 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, } } + // 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 c068113e9b8a..1f0a9deb5e47 100644 --- a/clang/test/Sema/conditional-expr.c +++ b/clang/test/Sema/conditional-expr.c @@ -40,3 +40,12 @@ int Postgresql() { 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'}} +}