[clang] [clang] Fix const eval of constexpr-unknown relational comparisons. (PR #150088)

Eli Friedman via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 24 10:00:40 PDT 2025


https://github.com/efriedma-quic updated https://github.com/llvm/llvm-project/pull/150088

>From 51b5621d471142437641740b97eda2a24c7af82e Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Tue, 22 Jul 2025 12:09:28 -0700
Subject: [PATCH 1/3] [clang] Fix const eval of constexpr-unknown relational
 comparisons.

Like in other places, ignore the reference type of the base.  (It might
make sense to refactor this at some point.)

Fixes #150015.
---
 clang/lib/AST/ExprConstant.cpp                     |  7 ++++---
 clang/test/SemaCXX/constant-expression-p2280r4.cpp | 13 +++++++++++++
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8797eaddd0e18..106ad30adf1e5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14631,8 +14631,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
     // - Otherwise pointer comparisons are unspecified.
     if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
       bool WasArrayIndex;
-      unsigned Mismatch = FindDesignatorMismatch(
-          getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex);
+      unsigned Mismatch =
+          FindDesignatorMismatch(getType(LHSValue.Base).getNonReferenceType(),
+                                 LHSDesignator, RHSDesignator, WasArrayIndex);
       // At the point where the designators diverge, the comparison has a
       // specified value if:
       //  - we are comparing array indices
@@ -14676,7 +14677,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
     // compare pointers within the object in question; otherwise, the result
     // depends on where the object is located in memory.
     if (!LHSValue.Base.isNull() && IsRelational) {
-      QualType BaseTy = getType(LHSValue.Base);
+      QualType BaseTy = getType(LHSValue.Base).getNonReferenceType();
       if (BaseTy->isIncompleteType())
         return Error(E);
       CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
index 16f5f823d26c1..3fb7bf28b1e8b 100644
--- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp
+++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
@@ -383,3 +383,16 @@ namespace enable_if_2 {
   }
 }
 }
+
+namespace GH150015 {
+  extern int (& c)[8]; // interpreter-note {{declared here}}
+  constexpr int x = c <= c+8; // interpreter-error {{constexpr variable 'x' must be initialized by a constant expression}} \
+                              // interpreter-note {{initializer of 'c' is unknown}}
+
+  struct X {};
+  struct Y {};
+  struct Z : X, Y {};
+  extern Z z;
+  constexpr int bases = (void*)(X*)&z <= (Y*)&z; // nointerpreter-error {{constexpr variable 'bases' must be initialized by a constant expression}} \
+                                                 // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}}
+}

>From 9a9e326f824c12d68261bf48be3a990f980b5774 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Tue, 22 Jul 2025 12:21:27 -0700
Subject: [PATCH 2/3] Fix test so it's actually checking constexpr-unknown.

---
 clang/test/SemaCXX/constant-expression-p2280r4.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
index 3fb7bf28b1e8b..312a77830420b 100644
--- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp
+++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
@@ -392,7 +392,8 @@ namespace GH150015 {
   struct X {};
   struct Y {};
   struct Z : X, Y {};
-  extern Z z;
-  constexpr int bases = (void*)(X*)&z <= (Y*)&z; // nointerpreter-error {{constexpr variable 'bases' must be initialized by a constant expression}} \
-                                                 // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}}
+  extern Z &z; // interpreter-note{{declared here}}
+  constexpr int bases = (void*)(X*)&z <= (Y*)&z; // expected-error {{constexpr variable 'bases' must be initialized by a constant expression}} \
+                                                 // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}} \
+                                                 // interpreter-note {{initializer of 'z' is unknown}}
 }

>From 2715f362d2adf42b3ef6ab4bd8d753d3eaad51c1 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Thu, 24 Jul 2025 10:00:10 -0700
Subject: [PATCH 3/3] Fix crash on relational comparison with null.

---
 clang/lib/AST/ExprConstant.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 106ad30adf1e5..d79257648a383 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14631,9 +14631,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
     // - Otherwise pointer comparisons are unspecified.
     if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
       bool WasArrayIndex;
-      unsigned Mismatch =
-          FindDesignatorMismatch(getType(LHSValue.Base).getNonReferenceType(),
-                                 LHSDesignator, RHSDesignator, WasArrayIndex);
+      unsigned Mismatch = FindDesignatorMismatch(
+          LHSValue.Base.isNull() ? QualType()
+                                 : getType(LHSValue.Base).getNonReferenceType(),
+          LHSDesignator, RHSDesignator, WasArrayIndex);
       // At the point where the designators diverge, the comparison has a
       // specified value if:
       //  - we are comparing array indices



More information about the cfe-commits mailing list