[clang] [Clang] SubstituteConstraintExpressionWithoutSatisfaction needs an unevaluated context (PR #123883)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 21 23:06:32 PST 2025
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/123883
>From 5427c748811041d0878dc4aec8b7b37c4241af37 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 21 Jan 2025 20:21:20 +0800
Subject: [PATCH 1/3] [Clang] SubstituteConstraintExpressionWithoutSatisfaction
needs an unevaluated context
It turns out that the substitution for expression comparing also needs
an unevaluated context, otherwise any reference to immediate functions
might not be properly handled.
---
clang/docs/ReleaseNotes.rst | 2 +-
clang/lib/Sema/SemaConcept.cpp | 3 +++
.../test/SemaTemplate/concepts-out-of-line-def.cpp | 14 ++++++++++++++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f75c726e2751cf..5a5a97b341881a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -966,7 +966,7 @@ Bug Fixes to C++ Support
constraints are applied. (#GH122134)
- Fixed canonicalization of pack indexing types - Clang did not always recognized identical pack indexing. (#GH123033)
- Fixed a nested lambda substitution issue for constraint evaluation. (#GH123441)
-
+- Fixed various false diagnostics related to the use of immediate functions. (#GH123472)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 6a40a59c977d78..8a77cbf8c9477b 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1027,6 +1027,9 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
/*NewThisContext=*/false);
}
+ EnterExpressionEvaluationContext UnevaluatedContext(
+ S, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
const_cast<clang::Expr *>(ConstrExpr), MLTAL);
if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index 7cb5cfc10b9a7b..6c1a229a9fddab 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -737,3 +737,17 @@ ptr<U> make_item(auto &&args)
ptr<char> p;
} // namespace GH114685
+
+namespace GH123472 {
+
+consteval bool fn() { return true; }
+
+struct S {
+ template <typename T>
+ static consteval void mfn() requires (bool(&fn));
+};
+
+template <typename T>
+consteval void S::mfn() requires (bool(&fn)) {}
+
+}
>From 8dba2df946a367706605572f1f2935f70d6c16a6 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Wed, 22 Jan 2025 11:51:56 +0800
Subject: [PATCH 2/3] Fix a VLA diagnostic regression - BuildArrayType() is
doubly called under unevaluated context
---
clang/lib/Parse/ParseExpr.cpp | 19 +++++++++++++++++++
clang/lib/Sema/SemaExpr.cpp | 5 +++--
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 8dd72db8f5b4a2..bf017a3131b4a7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -248,6 +248,25 @@ ExprResult Parser::ParseArrayBoundExpression() {
// If we parse the bound of a VLA... we parse a non-constant
// constant-expression!
Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true;
+ // For a VLA type inside an unevaluated operator like:
+ //
+ // sizeof(typeof(*(int (*)[N])array))
+ //
+ // in which the expression N is supposed to be ODR-used, as is the `array`.
+ // Initially when encountering `array`, it is deemed unevaluated and non-ODR
+ // used because that occurs before parsing the type cast. Therefore we use
+ // Sema::TransformToPotentiallyEvaluated() to rebuild the expression to ensure
+ // it's actually ODR-used.
+ //
+ // However, in other unevaluated contexts as in constraint substitution, it
+ // would end up rebuilding the type twice which is unnecessary. So we push up
+ // a flag to help distinguish these cases.
+ for (auto Iter = Actions.ExprEvalContexts.rbegin() + 1;
+ Iter != Actions.ExprEvalContexts.rend(); ++Iter) {
+ if (!Iter->isUnevaluated())
+ break;
+ Iter->InConditionallyConstantEvaluateContext = true;
+ }
return ParseConstantExpressionInExprEvalContext(NotTypeCast);
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ae40895980d90a..444640b27de1fe 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4630,8 +4630,9 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
// Adds overload of TransformToPotentiallyEvaluated for TypeSourceInfo to
// properly deal with VLAs in nested calls of sizeof and typeof.
- if (isUnevaluatedContext() && ExprKind == UETT_SizeOf &&
- TInfo->getType()->isVariablyModifiedType())
+ if (currentEvaluationContext().isUnevaluated() &&
+ currentEvaluationContext().InConditionallyConstantEvaluateContext &&
+ ExprKind == UETT_SizeOf && TInfo->getType()->isVariablyModifiedType())
TInfo = TransformToPotentiallyEvaluated(TInfo);
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
>From a217b5fdc47ba87a21370c5cb5f70dcfe9d7957f Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Wed, 22 Jan 2025 15:06:24 +0800
Subject: [PATCH 3/3] Apply comment
Co-authored-by: cor3ntin <corentinjabot at gmail.com>
---
clang/lib/Parse/ParseExpr.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index bf017a3131b4a7..aa8b3870a188c6 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -252,7 +252,7 @@ ExprResult Parser::ParseArrayBoundExpression() {
//
// sizeof(typeof(*(int (*)[N])array))
//
- // in which the expression N is supposed to be ODR-used, as is the `array`.
+ // N and array are supposed to be ODR-used.
// Initially when encountering `array`, it is deemed unevaluated and non-ODR
// used because that occurs before parsing the type cast. Therefore we use
// Sema::TransformToPotentiallyEvaluated() to rebuild the expression to ensure
More information about the cfe-commits
mailing list