[clang] 84cf3a5 - [Clang] CWG2749: relational operators involving pointers to void (#93046)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 5 05:23:12 PDT 2024
Author: Mital Ashok
Date: 2024-09-05T14:23:08+02:00
New Revision: 84cf3a573e89b18ce79ff32a7646c0a99729029c
URL: https://github.com/llvm/llvm-project/commit/84cf3a573e89b18ce79ff32a7646c0a99729029c
DIFF: https://github.com/llvm/llvm-project/commit/84cf3a573e89b18ce79ff32a7646c0a99729029c.diff
LOG: [Clang] CWG2749: relational operators involving pointers to void (#93046)
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.
---------
Co-authored-by: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Co-authored-by: cor3ntin <corentinjabot at gmail.com>
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticASTKinds.td
clang/lib/AST/ExprConstant.cpp
clang/test/AST/ByteCode/literals.cpp
clang/test/CXX/drs/cwg27xx.cpp
clang/test/CXX/expr/expr.const/p2-0x.cpp
clang/www/cxx_dr_status.html
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bd84a2e40fb8bd..dc103aceebc362 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -154,6 +154,10 @@ Resolutions to C++ Defect Reports
- Allow ``void{}`` as a prvalue of type ``void``.
(`CWG2351: void{} <https://cplusplus.github.io/CWG/issues/2351.html>`_).
+- 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 45ad84831589b1..91135b18c75716 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 3dc13c14c00343..205cbdf52a6f72 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -13895,16 +13895,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/ByteCode/literals.cpp b/clang/test/AST/ByteCode/literals.cpp
index 2329d4d973f01d..13d6c4feb35002 100644
--- a/clang/test/AST/ByteCode/literals.cpp
+++ b/clang/test/AST/ByteCode/literals.cpp
@@ -199,12 +199,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 406c8ea41f3b2f..b3867696c615b8 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 -pedantic-errors -verify=expected %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -pedantic-errors -verify=expected,cxx98 %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -pedantic-errors -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -pedantic-errors -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -pedantic-errors -verify=expected %s
@@ -6,6 +6,29 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -pedantic-errors -verify=expected,since-cxx23 %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -pedantic-errors -verify=expected,since-cxx23,since-cxx26 %s
+#if __cplusplus == 199711L
+#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
+// cxx98-error at -1 {{variadic macros are a C99 feature}}
+#endif
+
+#if __cplusplus == 199711L
+#define __enable_constant_folding(x) (__builtin_constant_p(x) ? (x) : (x))
+#else
+#define __enable_constant_folding
+#endif
+
+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 std
+
namespace cwg2718 { // cwg2718: 2.7
struct B {};
struct D;
@@ -18,6 +41,27 @@ void f(B b) {
struct D : B {};
} // namespace cwg2718
+namespace cwg2749 { // cwg2749: 20
+
+extern int x[2];
+struct Y {
+ int i;
+ int j;
+};
+extern Y y[2];
+
+static_assert(__enable_constant_folding(static_cast<void*>(&x[0]) < static_cast<void*>(&x[1])), "");
+static_assert(__enable_constant_folding(static_cast<void*>(&y[0].i) < static_cast<void*>(&y[0].j)), "");
+static_assert(__enable_constant_folding(static_cast<void*>(&y[0].j) < static_cast<void*>(&y[1].i)), "");
+
+#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 e3cd057baba75f..767eee1c74f054 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -571,18 +571,19 @@ namespace UnspecifiedRelations {
// [expr.rel]p3: Pointers to void can be compared [...] if both pointers
// represent the same address or are both the null pointer [...]; otherwise
// the result is unspecified.
+ // Same address restriction removed by CWG2749
struct S { int a, b; } s;
constexpr void *null = 0;
constexpr void *pv = (void*)&s.a;
constexpr void *qv = (void*)&s.b;
constexpr bool v1 = null < (int*)0;
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 v3 = null == pv;
+ constexpr bool v4 = qv == pv;
+ 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 v7 = qv <= (void*)&s.b;
+ 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 aa79c3706f32bf..b638f0ff30bcce 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -16341,7 +16341,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 20</td>
</tr>
<tr id="2750">
<td><a href="https://cplusplus.github.io/CWG/issues/2750.html">2750</a></td>
More information about the cfe-commits
mailing list