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

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 19 13:22:40 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (offsetof)

<details>
<summary>Changes</summary>

This patch disables the relevant diagnostic in C++17 and later modes.

Fixes #<!-- -->45653

---
Full diff: https://github.com/llvm/llvm-project/pull/89449.diff


7 Files Affected:

- (modified) clang/lib/AST/ExprConstant.cpp (+4-1) 
- (modified) clang/test/AST/Interp/literals.cpp (+5-5) 
- (modified) clang/test/CXX/drs/dr25xx.cpp (+1) 
- (modified) clang/test/CXX/drs/dr26xx.cpp (+2) 
- (modified) clang/test/CXX/drs/dr27xx.cpp (+22) 
- (modified) clang/test/CXX/expr/expr.const/p2-0x.cpp (+13-10) 
- (modified) clang/www/cxx_dr_status.html (+3-3) 


``````````diff
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 73ae8d8efb23a2..2d480edab833c8 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -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:
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 277438d2e63114..91857228fcddc7 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -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__)
@@ -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}}
 
diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp
index 62b2a0a088cc13..672979c2be8ef8 100644
--- a/clang/test/CXX/drs/dr25xx.cpp
+++ b/clang/test/CXX/drs/dr25xx.cpp
@@ -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
diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp
index f7a05b9827a235..de18787bcab96b 100644
--- a/clang/test/CXX/drs/dr26xx.cpp
+++ b/clang/test/CXX/drs/dr26xx.cpp
@@ -238,3 +238,5 @@ void test() {
 }
 }
 #endif
+
+// cwg2696: dup 2749
diff --git a/clang/test/CXX/drs/dr27xx.cpp b/clang/test/CXX/drs/dr27xx.cpp
index 0434427d6c92a3..1f5b9e571079c9 100644
--- a/clang/test/CXX/drs/dr27xx.cpp
+++ b/clang/test/CXX/drs/dr27xx.cpp
@@ -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
 
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index e3cd057baba75f..54e163f05e4524 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -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
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 83b71e7c122d1e..12075b5aa0451e 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -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>
@@ -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>
@@ -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>

``````````

</details>


https://github.com/llvm/llvm-project/pull/89449


More information about the cfe-commits mailing list