-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang] CWG2749: relational operators involving pointers to void #93046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Mital Ashok (MitalAshok) ChangesThis DR's effects are backported to C++98. Does not affect C where integral constant expressions cannot involve pointers. Full diff: https://github.com/llvm/llvm-project/pull/93046.diff 7 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2899bc5ed35ad..4d9313f4c7ca5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,10 @@ Resolutions to C++ Defect Reports
- P0522 implementation is enabled by default in all language versions, and
provisional wording for CWG2398 is implemented.
+- Clang now allows comparing unequal object pointers that have been cast to ``void *``
+ in constant expressions. These comparisons always worked in non-constant expressions.
+ (`CWG2749: Treatment of "pointer to void" for relational comparisons <https://cplusplus.github.io/CWG/issues/2749.html>`_).
+
C Language Changes
------------------
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index a024f9b2a9f8c..b7aae9395e635 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -148,8 +148,6 @@ def note_constexpr_var_init_weak : Note<
def note_constexpr_typeid_polymorphic : Note<
"typeid applied to expression of polymorphic type %0 is "
"not allowed in a constant expression in C++ standards before C++20">;
-def note_constexpr_void_comparison : Note<
- "comparison between unequal pointers to void has unspecified result">;
def note_constexpr_temporary_here : Note<"temporary created here">;
def note_constexpr_dynamic_alloc_here : Note<"heap allocation performed here">;
def note_constexpr_conditional_never_const : Note<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f1aa19e4409e1..d5a47a071e2cd 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13627,16 +13627,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
- // C++11 [expr.rel]p3:
- // Pointers to void (after pointer conversions) can be compared, with a
- // result defined as follows: If both pointers represent the same
- // address or are both the null pointer value, the result is true if the
- // operator is <= or >= and false otherwise; otherwise the result is
- // unspecified.
- // We interpret this as applying to pointers to *cv* void.
- if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational)
- Info.CCEDiag(E, diag::note_constexpr_void_comparison);
-
// C++11 [expr.rel]p2:
// - If two pointers point to non-static data members of the same object,
// or to subobjects or array elements fo such members, recursively, the
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index c160be06dd241..ae7942aca39e6 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -191,12 +191,8 @@ namespace PointerComparison {
constexpr bool v3 = null == pv; // ok
constexpr bool v4 = qv == pv; // ok
- /// FIXME: These two are rejected by the current interpreter, but
- /// accepted by GCC.
- constexpr bool v5 = qv >= pv; // ref-error {{constant expression}} \
- // ref-note {{unequal pointers to void}}
- constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \
- // ref-note {{unequal pointers to void}}
+ constexpr bool v5 = qv >= pv;
+ constexpr bool v8 = qv > (void*)&s.a;
constexpr bool v6 = qv > null; // both-error {{must be initialized by a constant expression}} \
// both-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index 53ddd566b7dbf..f0c3c6dbdf97b 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -verify=expected %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -Wgnu-folding-constant -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -verify=expected %s
@@ -6,6 +6,18 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -verify=expected,since-cxx23 %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s
+namespace std {
+#if __cplusplus >= 202002L
+ struct strong_ordering {
+ int n;
+ constexpr operator int() const { return n; }
+ static const strong_ordering less, equal, greater;
+ };
+ constexpr strong_ordering strong_ordering::less{-1},
+ strong_ordering::equal{0}, strong_ordering::greater{1};
+#endif
+}
+
namespace cwg2718 { // cwg2718: 2.7
struct B {};
struct D;
@@ -18,6 +30,38 @@ void f(B b) {
struct D : B {};
} // namespace cwg2718
+namespace cwg2749 { // cwg2749: 19
+
+extern int x[2];
+struct Y {
+ int i;
+ int j;
+};
+extern Y y[2];
+
+#if __cplusplus >= 201103L
+static_assert(static_cast<void*>(x + 0) < static_cast<void*>(x + 1), "");
+static_assert(static_cast<void*>(&y[0].i) < static_cast<void*>(&y[0].j), "");
+static_assert(static_cast<void*>(&y[0].j) < static_cast<void*>(&y[1].i), "");
+#else
+enum X {
+ a = static_cast<void*>(x + 0) < static_cast<void*>(x + 1),
+// expected-warning@-1 {{expression is not an integral constant expression; folding it to a constant is a GNU extension}}
+ b = static_cast<void*>(&y[0].i) < static_cast<void*>(&y[0].j),
+// expected-warning@-1 {{expression is not an integral constant expression; folding it to a constant is a GNU extension}}
+ c = static_cast<void*>(&y[0].j) < static_cast<void*>(&y[1].i)
+// expected-warning@-1 {{expression is not an integral constant expression; folding it to a constant is a GNU extension}}
+};
+#endif
+
+#if __cplusplus >= 202002L
+static_assert((static_cast<void*>(x + 0) <=> static_cast<void*>(x + 1)) == std::strong_ordering::less);
+static_assert((static_cast<void*>(&y[0].i) <=> static_cast<void*>(&y[0].j)) == std::strong_ordering::less);
+static_assert((static_cast<void*>(&y[0].j) <=> static_cast<void*>(&y[1].i)) == std::strong_ordering::less);
+#endif
+
+} // namespace cwg2749
+
namespace cwg2759 { // cwg2759: 19
#if __cplusplus >= 201103L
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index e3cd057baba75..16e9329cccd4b 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -579,10 +579,10 @@ namespace UnspecifiedRelations {
constexpr bool v2 = null < pv; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
constexpr bool v3 = null == pv; // ok
constexpr bool v4 = qv == pv; // ok
- constexpr bool v5 = qv >= pv; // expected-error {{constant expression}} expected-note {{unequal pointers to void}}
+ constexpr bool v5 = qv >= pv;
constexpr bool v6 = qv > null; // expected-error {{constant expression}} expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
constexpr bool v7 = qv <= (void*)&s.b; // ok
- constexpr bool v8 = qv > (void*)&s.a; // expected-error {{constant expression}} expected-note {{unequal pointers to void}}
+ constexpr bool v8 = qv > (void*)&s.a;
}
// - an assignment or a compound assignment (5.17); or
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 9d458330f5376..26f2f60025e8e 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -16302,7 +16302,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2749.html">2749</a></td>
<td>DRWP</td>
<td>Treatment of "pointer to void" for relational comparisons</td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 19</td>
</tr>
<tr id="2750">
<td><a href="https://cplusplus.github.io/CWG/issues/2750.html">2750</a></td>
|
https://cplusplus.github.io/CWG/issues/2749.html This DR's effects are backported to C++98. Does not affect C where integral constant expressions cannot involve pointers.
aa5e7f7
to
e117295
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but you should wait for @tbaederr
Co-authored-by: Vlad Serebrennikov <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
I guess we should close #89449 after merging this.
@MitalAshok can you fix the conflicts and ping me so i can merge? |
@cor3ntin Done! |
@MitalAshok there is a test failure! |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/123/builds/4974 Here is the relevant piece of the build log for the reference
|
https://cplusplus.github.io/CWG/issues/2749.html
This DR's effects are backported to C++98.
Does not affect C where integral constant expressions cannot involve pointers.
Closes #45653