[clang] [Clang] Fix a crash when checking the constraints of a self-referential concept (PR #208465)
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 9 08:16:03 PDT 2026
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/208465
>From 07835592f82e6a7ca9f68a5a0566ef174133bbec Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Thu, 9 Jul 2026 15:52:10 +0200
Subject: [PATCH 1/2] [Clang] Fix a crash when checking the constraints of a
self-referential concept.
Fixes #206336
---
clang/lib/Sema/SemaTemplate.cpp | 1 +
clang/test/SemaTemplate/concepts.cpp | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1591cea9286ae..d2e22b0e63146 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -9306,6 +9306,7 @@ bool Sema::CheckConceptUseInDefinition(NamedDecl *Concept, SourceLocation Loc) {
CE && !CE->isInvalidDecl() && !CE->hasDefinition()) {
Diag(Loc, diag::err_recursive_concept) << CE;
Diag(CE->getLocation(), diag::note_declared_at);
+ CE->setInvalidDecl();
return true;
}
// Concept template parameters don't have a definition and can't
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 6f7f00bf12e61..f690768476e7c 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -2064,3 +2064,19 @@ auto x = quantity<reference<int>{}, int>{};
} // namespace CannotResolve1
} // namespace GH175831
+
+
+namespace GH206336 {
+class Dim;
+struct S;
+template <class T> concept foo = true;
+template <class T> concept SS = false; // expected-note {{because 'false' evaluated to false}}
+template <class X> concept _Dim = _Dim<X>; // expected-error {{a concept definition cannot refer to itself}} \
+ // expected-note {{declared here}}
+template <SS, _Dim Dim, foo<> E> auto bar(Dim, E) {}; // expected-note {{candidate template ignored: constraints not satisfied}} \
+ // expected-note {{because 'GH206336::S' does not satisfy 'SS'}}
+
+void baz() {
+ auto qux = bar<S>(true, [] {}); // expected-error {{no matching function for call to 'bar'}}
+}
+}
>From 0a9f35d9d863b6518265872e56e666011d7388ef Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Thu, 9 Jul 2026 17:15:44 +0200
Subject: [PATCH 2/2] fix tests
---
clang/test/CXX/drs/cwg25xx.cpp | 6 ------
clang/test/SemaTemplate/concepts.cpp | 12 ++++++------
2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp
index d5219bcd74756..6b4b167d8f07f 100644
--- a/clang/test/CXX/drs/cwg25xx.cpp
+++ b/clang/test/CXX/drs/cwg25xx.cpp
@@ -247,9 +247,6 @@ namespace cwg2565 { // cwg2565: 16 open 2023-06-07
x;
};
static_assert(ErrorRequires<int>);
- // since-cxx20-error at -1 {{static assertion failed}} \
- // since-cxx20-note at -1 {{because 'int' does not satisfy 'ErrorRequires'}} \
- // since-cxx20-note@#cwg2565-expr {{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
template<typename T>
concept NestedErrorInRequires = requires (T x) { // #cwg2565-NEIR
@@ -261,9 +258,6 @@ namespace cwg2565 { // cwg2565: 16 open 2023-06-07
};
};
static_assert(NestedErrorInRequires<int>);
- // since-cxx20-error at -1 {{static assertion failed}} \
- // since-cxx20-note at -1 {{because 'int' does not satisfy 'NestedErrorInRequires'}} \
- // since-cxx20-note-re@#cwg2565-NEIR-inner {{because {{.*}} would be invalid: constraint depends on a previously diagnosed expression}}
#endif
} // namespace cwg2565
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index f690768476e7c..f2478e1a22a6a 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -997,7 +997,7 @@ template<class>
concept True = true;
template<class>
-concept False = false; // expected-note 9 {{'false' evaluated to false}}
+concept False = false; // expected-note 8 {{'false' evaluated to false}}
template<class>
concept Irrelevant = false;
@@ -1009,8 +1009,8 @@ concept ErrorRequires = requires(ErrorRequires auto x) { x; }; //#GH54678-ill-fo
// expected-note at -1 {{declared here}}
template<typename T> concept C1 = C1<T> && []<C1>(C1 auto) -> C1 auto {};
-//expected-error at -1 4{{a concept definition cannot refer to itself}} \
-//expected-note at -1 4{{declared here}}
+//expected-error at -1 {{a concept definition cannot refer to itself}} \
+//expected-note at -1 {{declared here}}
template<class T> void aaa(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
requires (False<T> || False<T>) || False<T> {} // expected-note 3 {{'int' does not satisfy 'False'}}
@@ -1023,15 +1023,15 @@ requires (Irrelevant<T> || True<T>) && False<T> {} // expected-note {{'int' does
template<class T> void eee(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
requires (Irrelevant<T> || Irrelevant<T> || True<T>) && False<T> {} // expected-note {{'long' does not satisfy 'False'}}
-template<class T> void fff(T t) // expected-note {{candidate template ignored: constraints not satisfied}}
-requires((ErrorRequires<T> || False<T> || True<T>) && False<T>) {} // expected-note {{because 'unsigned long' does not satisfy 'False'}}
+template<class T> void fff(T t)
+requires((ErrorRequires<T> || False<T> || True<T>) && False<T>) {}
void test() {
aaa(42); // expected-error {{no matching function}}
bbb(42L); // expected-error{{no matching function}}
ccc(42UL); // expected-error {{no matching function}}
ddd(42); // expected-error {{no matching function}}
eee(42L); // expected-error {{no matching function}}
- fff(42UL); // expected-error {{no matching function}}
+ fff(42UL);
}
}
More information about the cfe-commits
mailing list