Skip to content

Commit 84cf3a5

Browse files
MitalAshokEndilllcor3ntin
authored
[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 <[email protected]> Co-authored-by: cor3ntin <[email protected]>
1 parent 1104056 commit 84cf3a5

File tree

7 files changed

+58
-25
lines changed

7 files changed

+58
-25
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ Resolutions to C++ Defect Reports
154154
- Allow ``void{}`` as a prvalue of type ``void``.
155155
(`CWG2351: void{} <https://cplusplus.github.io/CWG/issues/2351.html>`_).
156156

157+
- Clang now allows comparing unequal object pointers that have been cast to ``void *``
158+
in constant expressions. These comparisons always worked in non-constant expressions.
159+
(`CWG2749: Treatment of "pointer to void" for relational comparisons <https://cplusplus.github.io/CWG/issues/2749.html>`_).
160+
157161
C Language Changes
158162
------------------
159163

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,6 @@ def note_constexpr_var_init_weak : Note<
148148
def note_constexpr_typeid_polymorphic : Note<
149149
"typeid applied to expression of polymorphic type %0 is "
150150
"not allowed in a constant expression in C++ standards before C++20">;
151-
def note_constexpr_void_comparison : Note<
152-
"comparison between unequal pointers to void has unspecified result">;
153151
def note_constexpr_temporary_here : Note<"temporary created here">;
154152
def note_constexpr_dynamic_alloc_here : Note<"heap allocation performed here">;
155153
def note_constexpr_conditional_never_const : Note<

clang/lib/AST/ExprConstant.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13895,16 +13895,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
1389513895
SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator();
1389613896
SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator();
1389713897

13898-
// C++11 [expr.rel]p3:
13899-
// Pointers to void (after pointer conversions) can be compared, with a
13900-
// result defined as follows: If both pointers represent the same
13901-
// address or are both the null pointer value, the result is true if the
13902-
// operator is <= or >= and false otherwise; otherwise the result is
13903-
// unspecified.
13904-
// We interpret this as applying to pointers to *cv* void.
13905-
if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational)
13906-
Info.CCEDiag(E, diag::note_constexpr_void_comparison);
13907-
1390813898
// C++11 [expr.rel]p2:
1390913899
// - If two pointers point to non-static data members of the same object,
1391013900
// or to subobjects or array elements fo such members, recursively, the

clang/test/AST/ByteCode/literals.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,8 @@ namespace PointerComparison {
199199
constexpr bool v3 = null == pv; // ok
200200
constexpr bool v4 = qv == pv; // ok
201201

202-
/// FIXME: These two are rejected by the current interpreter, but
203-
/// accepted by GCC.
204-
constexpr bool v5 = qv >= pv; // ref-error {{constant expression}} \
205-
// ref-note {{unequal pointers to void}}
206-
constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \
207-
// ref-note {{unequal pointers to void}}
202+
constexpr bool v5 = qv >= pv;
203+
constexpr bool v8 = qv > (void*)&s.a;
208204
constexpr bool v6 = qv > null; // both-error {{must be initialized by a constant expression}} \
209205
// both-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
210206

clang/test/CXX/drs/cwg27xx.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,34 @@
1-
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -pedantic-errors -verify=expected %s
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -pedantic-errors -verify=expected,cxx98 %s
22
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -pedantic-errors -verify=expected %s
33
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -pedantic-errors -verify=expected %s
44
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -pedantic-errors -verify=expected %s
55
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -pedantic-errors -verify=expected %s
66
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -pedantic-errors -verify=expected,since-cxx23 %s
77
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -pedantic-errors -verify=expected,since-cxx23,since-cxx26 %s
88

9+
#if __cplusplus == 199711L
10+
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
11+
// cxx98-error@-1 {{variadic macros are a C99 feature}}
12+
#endif
13+
14+
#if __cplusplus == 199711L
15+
#define __enable_constant_folding(x) (__builtin_constant_p(x) ? (x) : (x))
16+
#else
17+
#define __enable_constant_folding
18+
#endif
19+
20+
namespace std {
21+
#if __cplusplus >= 202002L
22+
struct strong_ordering {
23+
int n;
24+
constexpr operator int() const { return n; }
25+
static const strong_ordering less, equal, greater;
26+
};
27+
constexpr strong_ordering strong_ordering::less{-1},
28+
strong_ordering::equal{0}, strong_ordering::greater{1};
29+
#endif
30+
} // namespace std
31+
932
namespace cwg2718 { // cwg2718: 2.7
1033
struct B {};
1134
struct D;
@@ -18,6 +41,27 @@ void f(B b) {
1841
struct D : B {};
1942
} // namespace cwg2718
2043

44+
namespace cwg2749 { // cwg2749: 20
45+
46+
extern int x[2];
47+
struct Y {
48+
int i;
49+
int j;
50+
};
51+
extern Y y[2];
52+
53+
static_assert(__enable_constant_folding(static_cast<void*>(&x[0]) < static_cast<void*>(&x[1])), "");
54+
static_assert(__enable_constant_folding(static_cast<void*>(&y[0].i) < static_cast<void*>(&y[0].j)), "");
55+
static_assert(__enable_constant_folding(static_cast<void*>(&y[0].j) < static_cast<void*>(&y[1].i)), "");
56+
57+
#if __cplusplus >= 202002L
58+
static_assert((static_cast<void*>(&x[0]) <=> static_cast<void*>(&x[1])) == std::strong_ordering::less);
59+
static_assert((static_cast<void*>(&y[0].i) <=> static_cast<void*>(&y[0].j)) == std::strong_ordering::less);
60+
static_assert((static_cast<void*>(&y[0].j) <=> static_cast<void*>(&y[1].i)) == std::strong_ordering::less);
61+
#endif
62+
63+
} // namespace cwg2749
64+
2165
namespace cwg2759 { // cwg2759: 19
2266
#if __cplusplus >= 201103L
2367

clang/test/CXX/expr/expr.const/p2-0x.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -571,18 +571,19 @@ namespace UnspecifiedRelations {
571571
// [expr.rel]p3: Pointers to void can be compared [...] if both pointers
572572
// represent the same address or are both the null pointer [...]; otherwise
573573
// the result is unspecified.
574+
// Same address restriction removed by CWG2749
574575
struct S { int a, b; } s;
575576
constexpr void *null = 0;
576577
constexpr void *pv = (void*)&s.a;
577578
constexpr void *qv = (void*)&s.b;
578579
constexpr bool v1 = null < (int*)0;
579580
constexpr bool v2 = null < pv; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
580-
constexpr bool v3 = null == pv; // ok
581-
constexpr bool v4 = qv == pv; // ok
582-
constexpr bool v5 = qv >= pv; // expected-error {{constant expression}} expected-note {{unequal pointers to void}}
581+
constexpr bool v3 = null == pv;
582+
constexpr bool v4 = qv == pv;
583+
constexpr bool v5 = qv >= pv;
583584
constexpr bool v6 = qv > null; // expected-error {{constant expression}} expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
584-
constexpr bool v7 = qv <= (void*)&s.b; // ok
585-
constexpr bool v8 = qv > (void*)&s.a; // expected-error {{constant expression}} expected-note {{unequal pointers to void}}
585+
constexpr bool v7 = qv <= (void*)&s.b;
586+
constexpr bool v8 = qv > (void*)&s.a;
586587
}
587588

588589
// - an assignment or a compound assignment (5.17); or

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16341,7 +16341,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1634116341
<td><a href="https://cplusplus.github.io/CWG/issues/2749.html">2749</a></td>
1634216342
<td>DRWP</td>
1634316343
<td>Treatment of "pointer to void" for relational comparisons</td>
16344-
<td class="unknown" align="center">Unknown</td>
16344+
<td class="unreleased" align="center">Clang 20</td>
1634516345
</tr>
1634616346
<tr id="2750">
1634716347
<td><a href="https://cplusplus.github.io/CWG/issues/2750.html">2750</a></td>

0 commit comments

Comments
 (0)