mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 09:34:42 +01:00
[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
This commit is contained in:
@@ -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">>;
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user