diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp index fc8f1eb2abf14..a8a35d73815f9 100644 --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -112,6 +112,19 @@ concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { ->getTypeConstraint(); } +// 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(R)) + return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors(); + + if (auto *NestedReq = dyn_cast(R)) + return !NestedReq->hasInvalidConstraint() && + NestedReq->getConstraintExpr() && + NestedReq->getConstraintExpr()->containsErrors(); + return false; +} + RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, ArrayRef LocalParameters, @@ -138,6 +151,9 @@ RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, if (!RequiresExprBits.IsSatisfied) break; } + + if (RequirementContainsError(R)) + setDependence(getDependence() | ExprDependence::Error); } std::copy(LocalParameters.begin(), LocalParameters.end(), getTrailingObjects()); diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp index 0800adda63928..28ebda22a8017 100644 --- a/clang/test/CXX/drs/dr25xx.cpp +++ b/clang/test/CXX/drs/dr25xx.cpp @@ -75,4 +75,25 @@ namespace dr2565 { // dr2565: 16 open // expected-error@-1{{constraints not satisfied for class template 'VariadicStruct'}} // expected-note@#VSREQ{{because 'Variadic' evaluated to false}} // expected-note@#VC{{because 'b' would be invalid: argument may not have 'void' type}} + + template + // expected-error@+1 {{unknown type name 'ErrorRequires'}} + concept ErrorRequires = requires (ErrorRequires auto x) { + x; + }; + static_assert(ErrorRequires); + // expected-error@-1{{static assertion failed}} + // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} + + template + // expected-error@+2 {{unknown type name 'NestedErrorInRequires'}} + concept NestedErrorInRequires = requires (T x) { + requires requires (NestedErrorInRequires auto y) { + y; + }; + }; + static_assert(NestedErrorInRequires); + // expected-error@-1{{static assertion failed}} + // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} + }