[clang] 853df5e - [Concepts] Fix friend duplicate detection when referencing containing Record

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 7 06:14:24 PDT 2022


Author: Erich Keane
Date: 2022-10-07T06:14:11-07:00
New Revision: 853df5e1d63684cbf3bf3da63d3e467003262282

URL: https://github.com/llvm/llvm-project/commit/853df5e1d63684cbf3bf3da63d3e467003262282
DIFF: https://github.com/llvm/llvm-project/commit/853df5e1d63684cbf3bf3da63d3e467003262282.diff

LOG: [Concepts] Fix friend duplicate detection when referencing containing Record

As another regression from the Deferred Concepts Instantiation patch, we
weren't properly detecting that a friend referenced its containing
Record when it referred to it without its template parameters.  This
patch makes sure that we do.

Added: 
    

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaConcept.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/SemaTemplate/concepts-friends.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 37fcfd2940d7..a6acdf6b4952 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3686,8 +3686,10 @@ class Sema final {
   // template, or just the current friend function. A 'lower' TemplateDepth in
   // the AST refers to a 'containing' template. As the constraint is
   // uninstantiated, this is relative to the 'top' of the TU.
-  bool ConstraintExpressionDependsOnEnclosingTemplate(unsigned TemplateDepth,
-                                                      const Expr *Constraint);
+  bool
+  ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend,
+                                                 unsigned TemplateDepth,
+                                                 const Expr *Constraint);
 
   // Calculates whether the friend function depends on an enclosing template for
   // the purposes of [temp.friend] p9.

diff  --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d8dadb38758b..f3301a67d227 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -657,7 +657,7 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
 
   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
   for (const Expr *Constraint : ACs)
-    if (ConstraintExpressionDependsOnEnclosingTemplate(OldTemplateDepth,
+    if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
                                                        Constraint))
       return true;
 

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e07ad3a72b4b..9fa821ea6bde 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1691,14 +1691,28 @@ namespace {
 class ConstraintRefersToContainingTemplateChecker
     : public TreeTransform<ConstraintRefersToContainingTemplateChecker> {
   bool Result = false;
+  const FunctionDecl *Friend = nullptr;
   unsigned TemplateDepth = 0;
 
+  // Check a record-decl that we've seen to see if it is a lexical parent of the
+  // Friend, likely because it was referred to without its template arguments.
+  void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) {
+    CheckingRD = CheckingRD->getMostRecentDecl();
+
+    for (const DeclContext *DC = Friend->getLexicalDeclContext();
+         DC && !DC->isFileContext(); DC = DC->getParent())
+      if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
+        if (CheckingRD == RD->getMostRecentDecl())
+          Result = true;
+  }
+
 public:
   using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>;
 
   ConstraintRefersToContainingTemplateChecker(Sema &SemaRef,
+                                              const FunctionDecl *Friend,
                                               unsigned TemplateDepth)
-      : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
+      : inherited(SemaRef), Friend(Friend), TemplateDepth(TemplateDepth) {}
   bool getResult() const { return Result; }
 
   // This should be the only template parm type that we have to deal with.
@@ -1728,6 +1742,8 @@ class ConstraintRefersToContainingTemplateChecker
       TransformType(VD->getType());
     else if (auto *TD = dyn_cast<TemplateDecl>(D))
       TransformTemplateParameterList(TD->getTemplateParameters());
+    else if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+      CheckIfContainingRecord(RD);
     else if (isa<NamedDecl>(D)) {
       // No direct types to visit here I believe.
     } else
@@ -1738,8 +1754,11 @@ class ConstraintRefersToContainingTemplateChecker
 } // namespace
 
 bool Sema::ConstraintExpressionDependsOnEnclosingTemplate(
-    unsigned TemplateDepth, const Expr *Constraint) {
-  ConstraintRefersToContainingTemplateChecker Checker(*this, TemplateDepth);
+    const FunctionDecl *Friend, unsigned TemplateDepth,
+    const Expr *Constraint) {
+  assert(Friend->getFriendObjectKind() && "Only works on a friend");
+  ConstraintRefersToContainingTemplateChecker Checker(*this, Friend,
+                                                      TemplateDepth);
   Checker.TransformExpr(const_cast<Expr *>(Constraint));
   return Checker.getResult();
 }

diff  --git a/clang/test/SemaTemplate/concepts-friends.cpp b/clang/test/SemaTemplate/concepts-friends.cpp
index 3db12b560588..6aa461841f9c 100644
--- a/clang/test/SemaTemplate/concepts-friends.cpp
+++ b/clang/test/SemaTemplate/concepts-friends.cpp
@@ -394,3 +394,20 @@ namespace NamedDeclRefs {
     // expected-note@#NOREFOUTER{{previous definition is here}}
   }
 } // namespace NamedDeclRefs
+
+namespace RefersToParentInConstraint {
+  // No diagnostic, these aren't duplicates.
+  template<typename T, typename U>
+  concept similar = true;
+
+  template <typename X>
+  struct S{
+    friend void f(similar<S> auto && self){}
+    friend void f2(similar<S<X>> auto && self){}
+  };
+
+  void use() {
+    S<int> x;
+    S<long> y;
+  }
+} // namespace RefersToParentInConstraint


        


More information about the cfe-commits mailing list