Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
------------------

Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Basic/DiagnosticASTKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
10 changes: 0 additions & 10 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 2 additions & 6 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}

Expand Down
46 changes: 45 additions & 1 deletion clang/test/CXX/drs/cwg27xx.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
// 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
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -verify=expected %s
// 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;
Expand All @@ -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

Expand Down
11 changes: 6 additions & 5 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,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
Expand Down
2 changes: 1 addition & 1 deletion clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
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>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>
Expand Down