From d89d86fe4acaa4782b0ed8a684bbc1b32cb48b70 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 4 Feb 2011 04:20:44 +0000 Subject: [PATCH] Tighten up the semantics of default template arguments, per C++0x [temp.param]p9 and C++ DR226. Fixes PR8747. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124856 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++- lib/Sema/SemaDecl.cpp | 10 ++++++-- lib/Sema/SemaTemplate.cpp | 11 +++++++-- test/CXX/temp/temp.param/p9-0x.cpp | 38 ++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4777bca4b8..026930dabf 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2914,7 +2914,8 @@ public: TPC_ClassTemplate, TPC_FunctionTemplate, TPC_ClassTemplateMember, - TPC_FriendFunctionTemplate + TPC_FriendFunctionTemplate, + TPC_FriendFunctionTemplateDefinition }; bool CheckTemplateParameterList(TemplateParameterList *NewParams, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9c4fdc99f2..88c3a770c2 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3967,8 +3967,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration(); CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), PrevTemplate? PrevTemplate->getTemplateParameters() : 0, - D.getDeclSpec().isFriendSpecified()? TPC_FriendFunctionTemplate - : TPC_FunctionTemplate); + D.getDeclSpec().isFriendSpecified() + ? (IsFunctionDefinition + ? TPC_FriendFunctionTemplateDefinition + : TPC_FriendFunctionTemplate) + : (D.getCXXScopeSpec().isSet() && + DC && DC->isRecord()) + ? TPC_ClassTemplateMember + : TPC_FunctionTemplate); } if (NewFD->isInvalidDecl()) { diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f7060f03a3..e867354273 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -946,7 +946,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // template declaration. if (CheckTemplateParameterList(TemplateParams, PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0, - TPC_ClassTemplate)) + (SS.isSet() && SemanticContext && + SemanticContext->isRecord()) + ? TPC_ClassTemplateMember + : TPC_ClassTemplate)) Invalid = true; if (SS.isSet()) { @@ -1045,11 +1048,15 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, return false; case Sema::TPC_FunctionTemplate: + case Sema::TPC_FriendFunctionTemplateDefinition: // C++ [temp.param]p9: // A default template-argument shall not be specified in a // function template declaration or a function template // definition [...] - // (This sentence is not in C++0x, per DR226). + // If a friend function template declaration specifies a default + // template-argument, that declaration shall be a definition and shall be + // the only declaration of the function template in the translation unit. + // (C++98/03 doesn't have this wording; see DR226). if (!S.getLangOptions().CPlusPlus0x) S.Diag(ParamLoc, diag::ext_template_parameter_default_in_function_template) diff --git a/test/CXX/temp/temp.param/p9-0x.cpp b/test/CXX/temp/temp.param/p9-0x.cpp index 1980bc6eaa..c9d5bfb017 100644 --- a/test/CXX/temp/temp.param/p9-0x.cpp +++ b/test/CXX/temp/temp.param/p9-0x.cpp @@ -12,3 +12,41 @@ template struct vector; template class ...Templates = vector> // expected-error{{template parameter pack cannot have a default argument}} struct X2; + +struct X3 { + template // expected-error{{default template argument not permitted on a friend template}} + friend void f0(X3); + + template + friend void f1(X3) { + } +}; + +namespace PR8747 { + // Testcase 1 + struct A0 { template struct B; }; + template struct A0::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + // Testcase 2 + template struct A1 { template struct B; }; + template template struct A1::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + // Testcase 3 + template + struct X2 { + void f0(); + template void f1(); + }; + + template void X2::f0() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + template template void X2::f1() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + namespace Inner { + template struct X3; + template void f2(); + } + + // Okay; not class members. + template struct Inner::X3 { }; + template void Inner::f2() {} +} -- 2.40.0