diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 38322cbbc761..2063fb45228b 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -904,6 +904,8 @@ DIAG(err_typecheck_call_invalid_ordered_compare, ERROR, "ordered compare requires two args of floating point type ('%0' and '%1')") DIAG(err_typecheck_cond_expect_scalar, ERROR, "used type '%0' where arithmetic or pointer type is required") +DIAG(ext_typecheck_cond_one_void, EXTENSION, + "C99 forbids conditional expressions with only one void side") DIAG(err_typecheck_expect_scalar_operand, ERROR, "operand of type '%0' where arithmetic or pointer type is required") DIAG(err_typecheck_cond_incompatible_operands, ERROR, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5341ee7faa3f..68a3f8d59365 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -856,9 +856,16 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 } // C99 6.5.15p5: "If both operands have void type, the result has void type." - if (lexT->isVoidType() && rexT->isVoidType()) + // The following || allows only one side to be void (a GCC-ism). + if (lexT->isVoidType() || rexT->isVoidType()) { + if (!lexT->isVoidType()) + Diag(rex->getLocStart(), diag::ext_typecheck_cond_one_void, + rex->getSourceRange()); + if (!rexT->isVoidType()) + Diag(lex->getLocStart(), diag::ext_typecheck_cond_one_void, + lex->getSourceRange()); return lexT.getUnqualifiedType(); - + } // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has // the type of the other operand." if (lexT->isPointerType() && rex->isNullPointerConstant(Context)) { diff --git a/clang/test/Sema/conditional-expr.c b/clang/test/Sema/conditional-expr.c index a21914c6d5cc..ae973d6b2b84 100644 --- a/clang/test/Sema/conditional-expr.c +++ b/clang/test/Sema/conditional-expr.c @@ -36,3 +36,7 @@ void foo() { *(0 ? (asdf) 0 : &x) = 10; } +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}} +}