[clang] c310bf8 - [Sema] Comparison of pointers to complete and incomplete types
Eli Friedman via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 19 17:03:06 PDT 2020
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);
+}
More information about the cfe-commits
mailing list