[clang] Fix implementation of [temp.param]p14's first sentence. (PR #83487)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 1 07:26:56 PST 2024


https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/83487

>From 1c443bec9f11c14f8971d5dcb03d12e50c080afc Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Thu, 29 Feb 2024 13:29:02 -0800
Subject: [PATCH 1/3] Fix implementation of [temp.param]p14's first sentence.

The first sentence says:

If a template-parameter of a class template, variable template, or alias
template has a default template-argument, each subsequent
template-parameter shall either have a default template-argument
supplied or be a template parameter pack.

However, we were only testing for "not a function function template",
and referring to an older version of the standard.  As far as I can
tell, CWG2032 added the variable-template, and the alias-template
pre-dates the standard on github.

This patch started as a bug fix for #83461 , but ended up fixing a
number of similar cases, so those are validated as well.
---
 clang/lib/Sema/SemaTemplate.cpp | 14 ++++----
 clang/test/SemaCXX/GH83461.cpp  | 60 +++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/SemaCXX/GH83461.cpp

diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e91033dd886891..a7910bda874c8d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3141,12 +3141,14 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
            diag::note_template_param_prev_default_arg_in_other_module)
           << PrevModuleName;
       Invalid = true;
-    } else if (MissingDefaultArg && TPC != TPC_FunctionTemplate) {
-      // C++ [temp.param]p11:
-      //   If a template-parameter of a class template has a default
-      //   template-argument, each subsequent template-parameter shall either
-      //   have a default template-argument supplied or be a template parameter
-      //   pack.
+    } else if (MissingDefaultArg &&
+               (TPC == TPC_ClassTemplate || TPC == TPC_FriendClassTemplate ||
+                TPC == TPC_VarTemplate || TPC == TPC_TypeAliasTemplate)) {
+      // C++ 23[temp.param]p14:
+      // If a template-parameter of a class template, variable template, or
+      // alias template has a default template argument, each subsequent
+      // template-parameter shall either have a default template argument
+      // supplied or be a template parameter pack.
       Diag((*NewParam)->getLocation(),
            diag::err_template_param_default_arg_missing);
       Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
diff --git a/clang/test/SemaCXX/GH83461.cpp b/clang/test/SemaCXX/GH83461.cpp
new file mode 100644
index 00000000000000..509535e883e6d9
--- /dev/null
+++ b/clang/test/SemaCXX/GH83461.cpp
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+struct S {
+  template<typename Ty = int>
+  friend void foo(auto){}
+
+  template<typename Ty = int, typename Tz>
+  friend void foo2(){}
+};
+
+template<typename T>
+struct TemplS {
+  template<typename Ty = int>
+  friend void foo3(auto){}
+
+  template<typename Ty = int, typename Tz>
+  friend void foo4(){}
+};
+
+void Inst() {
+  TemplS<int>();
+}
+// expected-error at +2{{template parameter missing a default argument}}
+// expected-note at +1{{previous default template argument defined here}}
+template<typename T = int, typename U>
+struct ClassTempl{};
+
+struct HasFriendClassTempl {
+  // expected-error at +1{{default template argument not permitted on a friend template}}
+  template<typename T = int, typename U>
+  friend struct Friend;
+
+  // expected-error at +3{{cannot define a type in a friend declaration}}
+  // expected-error at +1{{default template argument not permitted on a friend template}}
+  template<typename T = int, typename U>
+  friend struct Friend2{};
+};
+
+template<typename Ty>
+struct HasFriendClassTempl2 {
+  // expected-error at +3{{template parameter missing a default argument}}
+  // expected-note at +2{{previous default template argument defined here}}
+  // expected-note@#INST2{{in instantiation of template class}}
+  template<typename T = int, typename U>
+  friend struct Friend;
+};
+
+void Inst2() {
+  HasFriendClassTempl2<int>(); // #INST2
+}
+
+// expected-error at +2{{template parameter missing a default argument}}
+// expected-note at +1{{previous default template argument defined here}}
+template<typename T = int, typename U>
+static constexpr U VarTempl;
+
+// expected-error at +2{{template parameter missing a default argument}}
+// expected-note at +1{{previous default template argument defined here}}
+template<typename T = int, typename U>
+using TypeAlias = U;

>From ccdb3e9316748bd23c5704be961b3985e0c79244 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 1 Mar 2024 07:03:41 -0800
Subject: [PATCH 2/3] add release note.

---
 clang/docs/ReleaseNotes.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f44fef28b9f17f..5368d7603d73c5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -298,6 +298,10 @@ Bug Fixes to C++ Support
   Fixes (`#82941 <https://github.com/llvm/llvm-project/issues/82941>`_),
   (`#42411 <https://github.com/llvm/llvm-project/issues/42411>`_), and
   (`#18121 <https://github.com/llvm/llvm-project/issues/18121>`_).
+- Clang now properly diagnoses missing 'default' template arguments on a variety
+  of templates. Previously we were diagnosing on any non-function template
+  instead of only on class, alias, and variable templates.
+  Fixes (`#83461 <https://github.com/llvm/llvm-project/issues/83461>`_)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

>From a688add27b6ff99c3f61ba50bcaef07b60ed4a69 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Fri, 1 Mar 2024 07:23:28 -0800
Subject: [PATCH 3/3] Add more details to release notes

---
 clang/docs/ReleaseNotes.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5368d7603d73c5..bc59eab4ca798c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -300,7 +300,8 @@ Bug Fixes to C++ Support
   (`#18121 <https://github.com/llvm/llvm-project/issues/18121>`_).
 - Clang now properly diagnoses missing 'default' template arguments on a variety
   of templates. Previously we were diagnosing on any non-function template
-  instead of only on class, alias, and variable templates.
+  instead of only on class, alias, and variable templates, as last updated by
+  CWG2032.
   Fixes (`#83461 <https://github.com/llvm/llvm-project/issues/83461>`_)
 
 Bug Fixes to AST Handling



More information about the cfe-commits mailing list