[clang] [Clang] Ensure correct parameters are in the scope for constraint equivalence checking (PR #149264)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 17 00:09:05 PDT 2025
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/149264
>From 728de4d995079208605879a0ec30e8f76fe5220c Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Thu, 17 Jul 2025 14:17:02 +0800
Subject: [PATCH 1/2] [Clang] Ensure correct parameters are in the scope for
constraint equivalence checking
This is another case where untransformed constraint expressions led to
inconsistent transforms.
We did fix some of those issues by looking at parent scopes, however
the parent instantiation scope is not always available because we could
also reach here after the parents get instantiated.
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Sema/SemaConcept.cpp | 5 ++++-
.../test/SemaTemplate/concepts-using-decl.cpp | 21 +++++++++++++++++++
3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fcd3887ec7a09..6f55d14fd0aa5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -808,6 +808,7 @@ Bug Fixes in This Version
nested scopes. (#GH147495)
- Fixed a failed assertion with an operator call expression which comes from a
macro expansion when performing analysis for nullability attributes. (#GH138371)
+- Fixed a concept equivalent checking crash due to untransformed constraint expressions. (#GH146614)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 834417f8e15ac..fbb2b8e650630 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -923,8 +923,11 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
std::optional<LocalInstantiationScope> ScopeForParameters;
if (const NamedDecl *ND = DeclInfo.getDecl();
ND && ND->isFunctionOrFunctionTemplate()) {
- ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
+ ScopeForParameters.emplace(S);
const FunctionDecl *FD = ND->getAsFunction();
+ if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate();
+ Template && Template->getInstantiatedFromMemberTemplate())
+ FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
for (auto *PVD : FD->parameters()) {
if (!PVD->isParameterPack()) {
ScopeForParameters->InstantiatedLocal(PVD, PVD);
diff --git a/clang/test/SemaTemplate/concepts-using-decl.cpp b/clang/test/SemaTemplate/concepts-using-decl.cpp
index fca69dea5c88f..41f7b6d2f8faa 100644
--- a/clang/test/SemaTemplate/concepts-using-decl.cpp
+++ b/clang/test/SemaTemplate/concepts-using-decl.cpp
@@ -176,3 +176,24 @@ void func() {
f.foo<10, 10>(); // expected-error {{no matching member function for call to 'foo'}}
}
} // namespace heads_without_concepts.
+
+namespace GH146614 {
+
+template <typename T>
+struct base {
+ template <typename A>
+ void foo(A x)
+ requires (requires{x;})
+ {}
+};
+
+
+struct child : base<int> {
+ using base<int>::foo;
+ template <typename A>
+ void foo(A x)
+ requires (false)
+ {}
+};
+
+}
>From f777409dce7d80a59ab348c6582ce7533939f2c3 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Thu, 17 Jul 2025 15:08:23 +0800
Subject: [PATCH 2/2] Fix the original case - we have to look at the outer
scope!
---
clang/lib/Sema/SemaConcept.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index fbb2b8e650630..5205ca0bca6fa 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -923,12 +923,14 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
std::optional<LocalInstantiationScope> ScopeForParameters;
if (const NamedDecl *ND = DeclInfo.getDecl();
ND && ND->isFunctionOrFunctionTemplate()) {
- ScopeForParameters.emplace(S);
+ ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
const FunctionDecl *FD = ND->getAsFunction();
if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate();
Template && Template->getInstantiatedFromMemberTemplate())
FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
for (auto *PVD : FD->parameters()) {
+ if (ScopeForParameters->getInstantiationOfIfExists(PVD))
+ continue;
if (!PVD->isParameterPack()) {
ScopeForParameters->InstantiatedLocal(PVD, PVD);
continue;
More information about the cfe-commits
mailing list