diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-08-23 00:27:47 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-08-23 00:27:47 +0000 |
commit | 16c209610c8b1a271c51c892920ffc4bc2db08ab (patch) | |
tree | 6b4c7b9b1f970898c02e0103a0954e8be0155a77 | |
parent | 79ba8f2edc35a01535dcece188d5d2de65dcb144 (diff) | |
download | bcm5719-llvm-16c209610c8b1a271c51c892920ffc4bc2db08ab.tar.gz bcm5719-llvm-16c209610c8b1a271c51c892920ffc4bc2db08ab.zip |
Catch a few more cases of illegal comparisons.
llvm-svn: 79793
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 50 | ||||
-rw-r--r-- | clang/test/Sema/compare.c | 10 |
3 files changed, 31 insertions, 31 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d0a6cd308fb..8b717c5a7b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 59202912259..2f1438c2c3e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/test/Sema/compare.c b/clang/test/Sema/compare.c index 6b64bac37da..395a1a9ef96 100644 --- a/clang/test/Sema/compare.c +++ b/clang/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; } |