diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 11 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.param/p9-0x.cpp | 38 |
4 files changed, 57 insertions, 5 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4777bca4b86..026930dabfe 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9c4fdc99f27..88c3a770c27 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f7060f03a3b..e867354273f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/test/CXX/temp/temp.param/p9-0x.cpp b/clang/test/CXX/temp/temp.param/p9-0x.cpp index 1980bc6eaa1..c9d5bfb0173 100644 --- a/clang/test/CXX/temp/temp.param/p9-0x.cpp +++ b/clang/test/CXX/temp/temp.param/p9-0x.cpp @@ -12,3 +12,41 @@ template<typename T> struct vector; template<template<class> class ...Templates = vector> // expected-error{{template parameter pack cannot have a default argument}} struct X2; + +struct X3 { + template<typename T = int> // expected-error{{default template argument not permitted on a friend template}} + friend void f0(X3); + + template<typename T = int> + friend void f1(X3) { + } +}; + +namespace PR8747 { + // Testcase 1 + struct A0 { template<typename U> struct B; }; + template<typename U = int> struct A0::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + // Testcase 2 + template<typename T> struct A1 { template<typename U> struct B; }; + template<typename T> template<typename U = int> struct A1<T>::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + // Testcase 3 + template<typename T> + struct X2 { + void f0(); + template<typename U> void f1(); + }; + + template<typename T = int> void X2<T>::f0() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + template<typename T> template<typename U = int> void X2<T>::f1() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + namespace Inner { + template<typename T> struct X3; + template<typename T> void f2(); + } + + // Okay; not class members. + template<typename T = int> struct Inner::X3 { }; + template<typename T = int> void Inner::f2() {} +} |

