[clang] 6c38ffc - [Concepts] Fix friend-checking to include NTTPs

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 16 07:33:20 PST 2022


Author: Erich Keane
Date: 2022-11-16T07:33:15-08:00
New Revision: 6c38ffc7b6f46fda94e29ed6cf34b814aeeaab45

URL: https://github.com/llvm/llvm-project/commit/6c38ffc7b6f46fda94e29ed6cf34b814aeeaab45
DIFF: https://github.com/llvm/llvm-project/commit/6c38ffc7b6f46fda94e29ed6cf34b814aeeaab45.diff

LOG: [Concepts] Fix friend-checking to include NTTPs

More work for temp.friend p9, this fixes a previous bug where we didn't
properly consider a friend to depend on the enclosing template if it
only did so via an NTTP.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index b04458687ac02..08ff4f4aecb5e 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1707,6 +1707,18 @@ class ConstraintRefersToContainingTemplateChecker
           Result = true;
   }
 
+  void CheckNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+    assert(D->getDepth() <= TemplateDepth &&
+           "Nothing should reference a value below the actual template depth, "
+           "depth is likely wrong");
+    if (D->getDepth() != TemplateDepth)
+      Result = true;
+
+    // Necessary because the type of the NTTP might be what refers to the parent
+    // constriant.
+    TransformType(D->getType());
+  }
+
 public:
   using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>;
 
@@ -1742,6 +1754,8 @@ class ConstraintRefersToContainingTemplateChecker
     // unreachable should catch future instances/cases.
     if (auto *TD = dyn_cast<TypedefNameDecl>(D))
       TransformType(TD->getUnderlyingType());
+    else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D))
+      CheckNonTypeTemplateParmDecl(NTTPD);
     else if (auto *VD = dyn_cast<ValueDecl>(D))
       TransformType(VD->getType());
     else if (auto *TD = dyn_cast<TemplateDecl>(D))

diff  --git a/clang/test/SemaTemplate/concepts-friends.cpp b/clang/test/SemaTemplate/concepts-friends.cpp
index 6aa461841f9ca..3a9b308a65c5d 100644
--- a/clang/test/SemaTemplate/concepts-friends.cpp
+++ b/clang/test/SemaTemplate/concepts-friends.cpp
@@ -411,3 +411,33 @@ namespace RefersToParentInConstraint {
     S<long> y;
   }
 } // namespace RefersToParentInConstraint
+
+namespace NTTP {
+  struct Base{};
+  template<int N>
+  struct S : Base {
+    // N is from the parent template.
+    template<typename T>
+      friend int templ_func(Base&) requires(N > 0)
+      { return 10; }
+  };
+
+  template<typename T>
+  struct U : Base {
+    template<T N>
+      friend int templ_func(Base&) requires(N>0)
+      { return 10; }
+  };
+
+  void use() {
+    S<1> s1;
+    templ_func<float>(s1);
+    S<2> s2;
+    templ_func<float>(s2);
+
+    U<int> u1;
+    templ_func<1>(u1);
+    U<short> u2;
+    templ_func<1>(u2);
+  }
+}


        


More information about the cfe-commits mailing list