diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 50 | ||||
-rw-r--r-- | test/Sema/compare.c | 10 |
3 files changed, 31 insertions, 31 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d0a6cd308f..8b717c5a7b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1352,6 +1352,8 @@ def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension< "ordered comparison between pointer and zero (%0 and %1) is an extension">; def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< "ordered comparison of function pointers (%0 and %1)">; +def ext_typecheck_comparison_of_fptr_to_void : Extension< + "equality comparison between function pointer and void pointer (%0 and %1)">; def ext_typecheck_comparison_of_pointer_integer : ExtWarn< "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 5920291225..2f1438c2c3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4237,28 +4237,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, QualType RCanPointeeTy = Context.getCanonicalType(rType->getAs<PointerType>()->getPointeeType()); - if (isRelational) { - if (lType->isFunctionPointerType() || rType->isFunctionPointerType()) { - Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - } - if (LCanPointeeTy->isVoidType() != RCanPointeeTy->isVoidType()) { - Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - } - } else { - if (lType->isFunctionPointerType() != rType->isFunctionPointerType()) { - if (!LHSIsNull && !RHSIsNull) - Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - } - } - - // Simple check: if the pointee types are identical, we're done. - if (LCanPointeeTy == RCanPointeeTy) - return ResultTy; - if (getLangOptions().CPlusPlus) { + if (LCanPointeeTy == RCanPointeeTy) + return ResultTy; + // C++ [expr.rel]p2: // [...] Pointer conversions (4.10) and qualification // conversions (4.4) are performed on pointer operands (or on @@ -4278,15 +4260,29 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, ImpCastExprToType(rex, T); return ResultTy; } - - if (!LHSIsNull && !RHSIsNull && // C99 6.5.9p2 - !LCanPointeeTy->isVoidType() && !RCanPointeeTy->isVoidType() && - !Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), - RCanPointeeTy.getUnqualifiedType())) { + // C99 6.5.9p2 and C99 6.5.8p2 + if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), + RCanPointeeTy.getUnqualifiedType())) { + // Valid unless a relational comparison of function pointers + if (isRelational && LCanPointeeTy->isFunctionType()) { + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } + } else if (!isRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } + } else { + // Invalid Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); } - ImpCastExprToType(rex, lType); // promote the pointer to pointer + if (LCanPointeeTy != RCanPointeeTy) + ImpCastExprToType(rex, lType); // promote the pointer to pointer return ResultTy; } // C++ allows comparison of pointers with null pointer constants. diff --git a/test/Sema/compare.c b/test/Sema/compare.c index 6b64bac37d..395a1a9ef9 100644 --- a/test/Sema/compare.c +++ b/test/Sema/compare.c @@ -24,13 +24,15 @@ int pointers(int *a) { return a > (void *)0; // expected-warning {{comparison of distinct pointer types}} } -int function_pointers(int (*a)(int), int (*b)(int)) { +int function_pointers(int (*a)(int), int (*b)(int), void (*c)(int)) { return a > b; // expected-warning {{ordered comparison of function pointers}} return function_pointers > function_pointers; // expected-warning {{ordered comparison of function pointers}} + return a > c; // expected-warning {{comparison of distinct pointer types}} return a == (void *) 0; - return a == (void *) 1; // expected-warning {{comparison of distinct pointer types}} + return a == (void *) 1; // expected-warning {{equality comparison between function pointer and void pointer}} } -int void_pointers(void *foo) { - return foo == NULL; +int void_pointers(void* foo) { + return foo == (void*) 0; + return foo == (void*) 1; } |