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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
