[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