https://github.com/GeneralK1ng updated https://github.com/llvm/llvm-project/pull/176896
>From 962a9ef62e3be3bca293d5a176a90c47b97cef21 Mon Sep 17 00:00:00 2001 From: General_K1ng <[email protected]> Date: Tue, 20 Jan 2026 19:03:18 +0800 Subject: [PATCH 1/3] [Clang] Avoid crashing on substitution failure in expression requirements --- clang/lib/AST/ExprConcepts.cpp | 9 +++++++-- .../concepts-crash-expr-requirement.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp index 36f910da49bfb..b2e4d6b00a647 100644 --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -101,8 +101,13 @@ concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { // Search through the requirements, and see if any have a RecoveryExpr in it, // which means this RequiresExpr ALSO needs to be invalid. static bool RequirementContainsError(concepts::Requirement *R) { - if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R)) - return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors(); + if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R)) { + if (ExprReq->isExprSubstitutionFailure()) + return true; + if (auto *E = ExprReq->getExpr()) + return E->containsErrors(); + return false; + } if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R)) return !NestedReq->hasInvalidConstraint() && diff --git a/clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp b/clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp new file mode 100644 index 0000000000000..9e6474371a245 --- /dev/null +++ b/clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp @@ -0,0 +1,19 @@ +// RUN: not %clang_cc1 -std=c++23 -fsyntax-only %s 2>&1 | FileCheck %s +// Regression test: don't crash when an expression requirement becomes a +// substitution failure during template instantiation (see #176402). + +void f() { + auto recursiveLambda = [](auto self, int depth) -> void { + struct MyClass; + auto testConcept = []<typename T> { + return requires(T) { &MyClass::operator0 } + }; + }; + recursiveLambda(recursiveLambda, 5); +} + +// CHECK: error: +// CHECK: expected ';' at end of requirement +// CHECK-NOT: Assertion failed +// CHECK-NOT: Stack dump: + >From 6eb6b066cbc481a4f3d58d406fa487883d79e693 Mon Sep 17 00:00:00 2001 From: General_K1ng <[email protected]> Date: Tue, 20 Jan 2026 22:32:54 +0800 Subject: [PATCH 2/3] refactor(concepts): consolidate concept requirement tests --- .../concepts-crash-expr-requirement.cpp | 19 ------------------- clang/test/SemaTemplate/concepts.cpp | 13 +++++++++++++ 2 files changed, 13 insertions(+), 19 deletions(-) delete mode 100644 clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp diff --git a/clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp b/clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp deleted file mode 100644 index 9e6474371a245..0000000000000 --- a/clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// RUN: not %clang_cc1 -std=c++23 -fsyntax-only %s 2>&1 | FileCheck %s -// Regression test: don't crash when an expression requirement becomes a -// substitution failure during template instantiation (see #176402). - -void f() { - auto recursiveLambda = [](auto self, int depth) -> void { - struct MyClass; - auto testConcept = []<typename T> { - return requires(T) { &MyClass::operator0 } - }; - }; - recursiveLambda(recursiveLambda, 5); -} - -// CHECK: error: -// CHECK: expected ';' at end of requirement -// CHECK-NOT: Assertion failed -// CHECK-NOT: Stack dump: - diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index d93391baf9926..2701c16f56fc0 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1713,3 +1713,16 @@ template<C<void, bool> T> int f(); void main() { f<int>(); } } + +namespace GH176402 { + void f() { + auto recursiveLambda = [](auto self, int depth) -> void { + struct MyClass; + auto testConcept = []<typename T> { + return requires(T) { &MyClass::operator0 } + // expected-error {{expected ';' at end of requirement}} + }; + }; + recursiveLambda(recursiveLambda, 5); + } +} >From 2cc0b9b9a6de60aea7b2944315165b76e6966251 Mon Sep 17 00:00:00 2001 From: General_K1ng <[email protected]> Date: Tue, 20 Jan 2026 22:40:40 +0800 Subject: [PATCH 3/3] doc: add release note --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bde3bb1e81210..611e3fba2bc2b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -137,6 +137,7 @@ Bug Fixes to Attribute Support Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
