[clang] b515e11 - [Clang] Avoid crash when expression requirements are substitution failures (#176896)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 20 08:35:54 PST 2026
Author: General_K1ng
Date: 2026-01-20T16:35:49Z
New Revision: b515e1182560f91a7c7a459186dea5299f62534a
URL: https://github.com/llvm/llvm-project/commit/b515e1182560f91a7c7a459186dea5299f62534a
DIFF: https://github.com/llvm/llvm-project/commit/b515e1182560f91a7c7a459186dea5299f62534a.diff
LOG: [Clang] Avoid crash when expression requirements are substitution failures (#176896)
Clang could assert in `clang::concepts::ExprRequirement::getExpr()` when
an expression requirement becomes a substitution failure during template
instantiation.
Substitution-failure `ExprRequirements` intentionally do not have an
associated expression. Calling `getExpr()` in this case violates the API
contract and triggers an assertion.
This occurred while checking requirements in `RequirementContainsError`
during `RequiresExpr` construction.
Guard `RequirementContainsError` against substitution-failure
`ExprRequirements` and avoid calling `getExpr()` in that case.
Fixes #176402
Fixes #115513
Fixes #130620
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/AST/ExprConcepts.cpp
clang/test/SemaTemplate/concepts.cpp
Removed:
################################################################################
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
^^^^^^^^^^^^^^^^^^^^^^^^^
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.cpp b/clang/test/SemaTemplate/concepts.cpp
index d93391baf9926..cbb7e6dfb96d7 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1713,3 +1713,15 @@ 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);
+ }
+}
More information about the cfe-commits
mailing list