Author: Benson Chu Date: 2020-06-19T17:01:03-07:00 New Revision: c310bf8256f83f365921562cebc5e4c9aec8e87e
URL: https://github.com/llvm/llvm-project/commit/c310bf8256f83f365921562cebc5e4c9aec8e87e DIFF: https://github.com/llvm/llvm-project/commit/c310bf8256f83f365921562cebc5e4c9aec8e87e.diff LOG: [Sema] Comparison of pointers to complete and incomplete types Clang is missing one of the conditions for C99 6.5.9p2, where comparison between pointers must either both point to incomplete types or both point to complete types. This patch adds an extra check to the clause where two pointers are of compatible types. This only applies to C89/C99; the relevant part of the standard was rewritten for C11. Differential Revision: https://reviews.llvm.org/D79945 Added: clang/test/Sema/complete-incomplete-pointer-relational-c99.c Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaExpr.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a7b8a992f745..7c72eba8c2c1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6446,6 +6446,12 @@ def err_typecheck_ordered_comparison_of_pointer_and_zero : Error< "ordered comparison between pointer and zero (%0 and %1)">; def err_typecheck_three_way_comparison_of_pointer_and_zero : Error< "three-way comparison between pointer and zero">; +def ext_typecheck_compare_complete_incomplete_pointers : Extension< + "pointer comparisons before C11 " + "need to be between two complete or two incomplete types; " + "%0 is %select{|in}2complete and " + "%1 is %select{|in}3complete">, + InGroup<C11>; def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< "ordered comparison of function pointers (%0 and %1)">, InGroup<DiagGroup<"ordered-compare-function-pointers">>; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 59e7d88b7691..fdc050603188 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11584,11 +11584,22 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, // 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) - << LHSType << RHSType << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); + if (IsRelational) { + // Pointers both need to point to complete or incomplete types + if ((LCanPointeeTy->isIncompleteType() != + RCanPointeeTy->isIncompleteType()) && + !getLangOpts().C11) { + Diag(Loc, diag::ext_typecheck_compare_complete_incomplete_pointers) + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange() + << LHSType << RHSType << LCanPointeeTy->isIncompleteType() + << RCanPointeeTy->isIncompleteType(); + } + if (LCanPointeeTy->isFunctionType()) { + // Valid unless a relational comparison of function pointers + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) + << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + } } } else if (!IsRelational && (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { diff --git a/clang/test/Sema/complete-incomplete-pointer-relational-c99.c b/clang/test/Sema/complete-incomplete-pointer-relational-c99.c new file mode 100644 index 000000000000..ea6e4055eb52 --- /dev/null +++ b/clang/test/Sema/complete-incomplete-pointer-relational-c99.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c99 -Wc11-extensions %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c89 -Wc11-extensions %s + +int incomplete[]; // expected-warning {{tentative array definition assumed to have one element}} +int complete[6]; + +int test_comparison_between_incomplete_and_complete_pointer() { + return (&incomplete < &complete) && // expected-warning {{pointer comparisons before C11 need to be between two complete or two incomplete types; 'int (*)[]' is incomplete and 'int (*)[6]' is complete}} + (&incomplete <= &complete) && // expected-warning {{pointer comparisons before C11 need to be between two complete or two incomplete types; 'int (*)[]' is incomplete and 'int (*)[6]' is complete}} + (&incomplete > &complete) && // expected-warning {{pointer comparisons before C11 need to be between two complete or two incomplete types; 'int (*)[]' is incomplete and 'int (*)[6]' is complete}} + (&incomplete >= &complete) && // expected-warning {{pointer comparisons before C11 need to be between two complete or two incomplete types; 'int (*)[]' is incomplete and 'int (*)[6]' is complete}} + (&incomplete == &complete) && + (&incomplete != &complete); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits