[clang] [Clang] Avoid crash when expression requirements are substitution failures (PR #176896)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 20 03:18:19 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: General_K1ng (GeneralK1ng)
<details>
<summary>Changes</summary>
## What
Clang could assert in `clang::concepts::ExprRequirement::getExpr()` when an expression requirement becomes a substitution failure during template instantiation.
## Why
Substitution-failure `ExprRequirements` intentionally do not have an associated expression. Calling `getExpr()` in this case violates the API contract and triggers an assertion.
## Where
This occurred while checking requirements in `RequirementContainsError` during `RequiresExpr` construction.
## Fix
Guard `RequirementContainsError` against substitution-failure `ExprRequirements` and avoid calling `getExpr()` in that case.
## Tests
- `clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp`
Fixes #<!-- -->176402
> This is my first contribution to LLVM/Clang — feedback and suggestions are very welcome.
---
Full diff: https://github.com/llvm/llvm-project/pull/176896.diff
2 Files Affected:
- (modified) clang/lib/AST/ExprConcepts.cpp (+7-2)
- (added) clang/test/SemaTemplate/concepts-crash-expr-requirement.cpp (+19)
``````````diff
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:
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/176896
More information about the cfe-commits
mailing list