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.vladis...@gmail.com> Co-authored-by: cor3ntin <corentinja...@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@-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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits