Skip to content

[clang] Allow relational comparisons between unequal pointers to void in constant expressions #89449

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13510,7 +13510,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
// 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)
// This only applies until C++14; in C++17 a "cv void*" value can "point to
// an object" and is not treated specially in [expr.rel].
if (!Info.getLangOpts().CPlusPlus17 &&
LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && IsRelational)
Info.CCEDiag(E, diag::note_constexpr_void_comparison);

// C++11 [expr.rel]p2:
Expand Down
10 changes: 5 additions & 5 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-vla -fms-extensions -std=c++11 -verify=expected,both %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-vla -fms-extensions -std=c++20 -verify=expected,both %s
// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-vla -verify=ref,both %s
// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-vla -verify=ref,ref-cxx11,both %s
// RUN: %clang_cc1 -std=c++20 -fms-extensions -Wno-vla -verify=ref,both %s

#define INT_MIN (~__INT_MAX__)
Expand Down Expand Up @@ -193,10 +193,10 @@ namespace PointerComparison {

/// 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; // ref-cxx11-error {{constant expression}} \
// ref-cxx11-note {{unequal pointers to void}}
constexpr bool v8 = qv > (void*)&s.a; // ref-cxx11-error {{constant expression}} \
// ref-cxx11-note {{unequal pointers to void}}
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}}

Expand Down
1 change: 1 addition & 0 deletions clang/test/CXX/drs/dr25xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ using ::cwg2521::operator""_div;
#endif
} // namespace cwg2521

// cwg2526: sup 2749

#if __cplusplus >= 202302L
namespace cwg2553 { // cwg2553: 18 review 2023-07-14
Expand Down
2 changes: 2 additions & 0 deletions clang/test/CXX/drs/dr26xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,5 @@ void test() {
}
}
#endif

// cwg2696: dup 2749
22 changes: 22 additions & 0 deletions clang/test/CXX/drs/dr27xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@
// expected-no-diagnostics
#endif

namespace cwg2749 { // cwg2749: 19
#if __cplusplus >= 201703L

constexpr bool f() {
int arr[2] {};
return (void*)arr < arr + 1;
}
static_assert(f());

constexpr bool g() {
struct {
char c;
short s;
int i;
} s {};
return (void*)&s.c < &s.i;
}
static_assert(g());

#endif
}

namespace cwg2759 { // cwg2759: 19
#if __cplusplus >= 201103L

Expand Down
23 changes: 13 additions & 10 deletions clang/test/CXX/expr/expr.const/p2-0x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,18 +571,21 @@ 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.
struct S { int a, b; } s;
struct S { int a, b; static int c; } s;
constexpr void *null = 0;
constexpr void *pv = (void*)&s.a;
constexpr void *qv = (void*)&s.b;
constexpr void *av = (void*)&s.a;
constexpr void *bv = (void*)&s.b;
constexpr void *cv = (void*)&s.c;
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 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 v2 = null < av; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
constexpr bool v3 = null == av; // ok
constexpr bool v4 = bv == av; // ok
constexpr bool v5 = bv >= av; // cxx11-error {{constant expression}} cxx11-note {{unequal pointers to void}}
constexpr bool v6 = bv > null; // expected-error {{constant expression}} expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
constexpr bool v7 = bv <= (void*)&s.b; // ok
constexpr bool v8 = bv > (void*)&s.a; // cxx11-error {{constant expression}} cxx11-note {{unequal pointers to void}}
constexpr bool v9 = cv > bv; // expected-error {{constant expression}} expected-note {{comparison between '&c' and '&s.b' has unspecified value}}
constexpr bool v10 = cv <= (void*)&s; // expected-error {{constant expression}} expected-note {{comparison between '&c' and '&s' has unspecified value}}
}

// - an assignment or a compound assignment (5.17); or
Expand Down
6 changes: 3 additions & 3 deletions clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -14964,7 +14964,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2526.html">2526</a></td>
<td>C++23</td>
<td>Relational comparison of <TT>void*</TT> pointers</td>
<td class="unknown" align="center">Unknown</td>
<td class="unreleased" align="center">Superseded by <a href="#2749">2749</a></td>
</tr>
<tr id="2527">
<td><a href="https://cplusplus.github.io/CWG/issues/2527.html">2527</a></td>
Expand Down Expand Up @@ -15984,7 +15984,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2696.html">2696</a></td>
<td>dup</td>
<td>Relational comparisons of pointers to <TT>void</TT></td>
<td class="unknown" align="center">Unknown</td>
<td class="unreleased" align="center">Duplicate of <a href="#2749">2749</a></td>
</tr>
<tr id="2697">
<td><a href="https://cplusplus.github.io/CWG/issues/2697.html">2697</a></td>
Expand Down Expand Up @@ -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>DR</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>
Expand Down