[clang] [clang] Exclude non-template classes when checking if constraint refers to containing template arguments (PR #74265)

via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 3 16:32:51 PST 2023


https://github.com/antangelo created https://github.com/llvm/llvm-project/pull/74265

When checking if the constraint uses any enclosing template parameters for [temp.friend]p9, if a containing record is used as argument, we assume that the constraint depends on enclosing template parameters without checking if the record is templated. The reproducer from the bug is included as a test case.

I would appreciate if someone could double check my interpretation of the standard here as I'm not the most experienced with it.

Fixes #71595

>From a8e841657b9816a78f6eb1520c8513454fe0008b Mon Sep 17 00:00:00 2001
From: Antonio Abbatangelo <contact at antangelo.com>
Date: Tue, 28 Nov 2023 21:19:13 -0500
Subject: [PATCH] [clang] Exclude non-template classes when checking if
 constraint refers to containing template arguments

---
 clang/docs/ReleaseNotes.rst         |  3 +++
 clang/lib/Sema/SemaTemplate.cpp     |  2 ++
 clang/test/SemaTemplate/GH71595.cpp | 34 +++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+)
 create mode 100644 clang/test/SemaTemplate/GH71595.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c7a948fd3fae5..852b908dd1594 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -651,6 +651,9 @@ Bug Fixes in This Version
 - Fixed false positive error emitted by clang when performing qualified name
   lookup and the current class instantiation has dependent bases.
   Fixes (`#13826 <https://github.com/llvm/llvm-project/issues/13826>`_)
+- Fix a ``clang-17`` regression where a templated friend with constraints is not 
+  properly applied when its parameters reference an enclosing non-template class.
+  Fixes (`#71595 <https://github.com/llvm/llvm-project/issues/71595>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 09bbf14d39af5..aec802b289a2d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1714,6 +1714,8 @@ class ConstraintRefersToContainingTemplateChecker
   // Friend, likely because it was referred to without its template arguments.
   void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) {
     CheckingRD = CheckingRD->getMostRecentDecl();
+    if (!CheckingRD->isTemplated())
+      return;
 
     for (const DeclContext *DC = Friend->getLexicalDeclContext();
          DC && !DC->isFileContext(); DC = DC->getParent())
diff --git a/clang/test/SemaTemplate/GH71595.cpp b/clang/test/SemaTemplate/GH71595.cpp
new file mode 100644
index 0000000000000..7d34d1bf054e4
--- /dev/null
+++ b/clang/test/SemaTemplate/GH71595.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+
+template<class T, class U>
+concept C = true;
+
+class non_temp {
+    template<C<non_temp> T>
+    friend void f();
+
+    non_temp();
+};
+
+template<C<non_temp> T>
+void f() {
+    auto v = non_temp();
+}
+
+template<class A>
+class temp {
+    template<C<temp> T>
+    friend void g();
+
+    temp(); // expected-note {{implicitly declared private here}}
+};
+
+template<C<temp<int>> T>
+void g() {
+    auto v = temp<T>(); // expected-error {{calling a private constructor of class 'temp<int>'}}
+}
+
+void h() {
+    f<int>();
+    g<int>(); // expected-note {{in instantiation of function template specialization 'g<int>' requested here}}
+}



More information about the cfe-commits mailing list