diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -8971,14 +8971,14 @@ cast(TPL->getParam(0))->getTypeConstraint() ->getImmediatelyDeclaredConstraint(); ExprResult Constraint = SubstExpr(IDC, MLTAL); - assert(!Constraint.isInvalid() && - "Substitution cannot fail as it is simply putting a type template " - "argument into a concept specialization expression's parameter."); - - SubstitutedConstraintExpr = - cast(Constraint.get()); - if (!SubstitutedConstraintExpr->isSatisfied()) - Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied; + if (Constraint.isInvalid()) { + Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure; + } else { + SubstitutedConstraintExpr = + cast(Constraint.get()); + if (!SubstitutedConstraintExpr->isSatisfied()) + Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied; + } } return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc, ReturnTypeRequirement, Status, diff --git a/clang/test/SemaCXX/concept-fatal-error.cpp b/clang/test/SemaCXX/concept-fatal-error.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/concept-fatal-error.cpp @@ -0,0 +1,11 @@ +// RUN: not %clang_cc1 -fsyntax-only -std=c++20 -ferror-limit 1 %s 2>&1 | FileCheck %s + +template +concept f = requires { 42; }; +struct h { + // The missing semicolon will trigger an error and -ferror-limit=1 will make it fatal + // We test that we do not crash in such cases (#55401) + int i = requires { { i } f } // expected-error {{expected ';' at end of declaration list}} + + // CHECK: fatal error: too many errors emitted, stopping now +};