[clang] 98ea471 - Properly Propagate RecoveryExpr through RequiresExpr

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 29 09:05:05 PDT 2023


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 at -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 at +1 {{unknown type name 'ErrorRequires'}}
+  concept ErrorRequires = requires (ErrorRequires auto x) {
+    x;
+  };
+  static_assert(ErrorRequires<int>);
+  // expected-error at -1{{static assertion failed}}
+  // expected-note at -2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
+
+  template<typename T>
+  // expected-error at +2 {{unknown type name 'NestedErrorInRequires'}}
+  concept NestedErrorInRequires = requires (T x) {
+    requires requires (NestedErrorInRequires auto y) {
+      y;
+    };
+  };
+  static_assert(NestedErrorInRequires<int>);
+  // expected-error at -1{{static assertion failed}}
+  // expected-note at -2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
+
 }


        


More information about the cfe-commits mailing list