Author: Erich Keane Date: 2023-03-29T09:04:59-07:00 New Revision: 98ea4712828b0802c99b3e8a6808cdc908f5b5b9
URL: https://github.com/llvm/llvm-project/commit/98ea4712828b0802c99b3e8a6808cdc908f5b5b9 DIFF: https://github.com/llvm/llvm-project/commit/98ea4712828b0802c99b3e8a6808cdc908f5b5b9.diff LOG: Properly Propagate RecoveryExpr through RequiresExpr Commit 3d7946c58 implemented a DR that allowed us to error in a case where an ill-formedness in a RequiresExpr is diagnosed as a satisfaction failure. However, it failed to cover cases where the RequiresExpr had Requirements that failed for similar reasons. This patch propagates the RecoveryExpr "containsErrors" correctly through RequiresExpr. Fixes: #61776 Added: Modified: clang/lib/AST/ExprConcepts.cpp clang/test/CXX/drs/dr25xx.cpp Removed: ################################################################################ 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<concepts::ExprRequirement>(R)) + return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors(); + + if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R)) + return !NestedReq->hasInvalidConstraint() && + NestedReq->getConstraintExpr() && + NestedReq->getConstraintExpr()->containsErrors(); + return false; +} + RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> 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<ParmVarDecl *>()); 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<void, int, char, double>' evaluated to false}} // expected-note@#VC{{because 'b' would be invalid: argument may not have 'void' type}} + + template<typename T> + // expected-error@+1 {{unknown type name 'ErrorRequires'}} + concept ErrorRequires = requires (ErrorRequires auto x) { + x; + }; + static_assert(ErrorRequires<int>); + // expected-error@-1{{static assertion failed}} + // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} + + template<typename T> + // expected-error@+2 {{unknown type name 'NestedErrorInRequires'}} + concept NestedErrorInRequires = requires (T x) { + requires requires (NestedErrorInRequires auto y) { + y; + }; + }; + static_assert(NestedErrorInRequires<int>); + // expected-error@-1{{static assertion failed}} + // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} + } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits