Author: Erich Keane Date: 2024-03-01T07:27:06-08:00 New Revision: 06bd74ba4ac5229f01b64772b49e025be5eb7b53
URL: https://github.com/llvm/llvm-project/commit/06bd74ba4ac5229f01b64772b49e025be5eb7b53 DIFF: https://github.com/llvm/llvm-project/commit/06bd74ba4ac5229f01b64772b49e025be5eb7b53.diff LOG: Fix implementation of [temp.param]p14's first sentence. (#83487) 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. Added: clang/test/SemaCXX/GH83461.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplate.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4e5c870e4177fe..1286263700963c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -301,6 +301,12 @@ Bug Fixes to C++ Support - Clang now properly reports supported C++11 attributes when using ``__has_cpp_attribute`` and parses attributes with arguments in C++03 (`#82995 <https://github.com/llvm/llvm-project/issues/82995>`_) +- 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, as last updated by + CWG2032. + Fixes (`#83461 <https://github.com/llvm/llvm-project/issues/83461>`_) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ 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@+2{{template parameter missing a default argument}} +// expected-note@+1{{previous default template argument defined here}} +template<typename T = int, typename U> +struct ClassTempl{}; + +struct HasFriendClassTempl { + // expected-error@+1{{default template argument not permitted on a friend template}} + template<typename T = int, typename U> + friend struct Friend; + + // expected-error@+3{{cannot define a type in a friend declaration}} + // expected-error@+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@+3{{template parameter missing a default argument}} + // expected-note@+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@+2{{template parameter missing a default argument}} +// expected-note@+1{{previous default template argument defined here}} +template<typename T = int, typename U> +static constexpr U VarTempl; + +// expected-error@+2{{template parameter missing a default argument}} +// expected-note@+1{{previous default template argument defined here}} +template<typename T = int, typename U> +using TypeAlias = U; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits