From: Nico Weber Date: Mon, 25 Jun 2012 17:21:05 +0000 (+0000) Subject: Make explicit specializations at class scope work X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b02009359a462ffe633696a4441313b462e6566;p=clang Make explicit specializations at class scope work for non-type template parameters in microsoft mode. PR12709. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159147 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index bafa478886..7affc7e15f 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -2086,23 +2086,33 @@ class ClassScopeFunctionSpecializationDecl : public Decl { virtual void anchor(); ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, - CXXMethodDecl *FD) + CXXMethodDecl *FD, bool Args, + TemplateArgumentListInfo TemplArgs) : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), - Specialization(FD) {} + Specialization(FD), HasExplicitTemplateArgs(Args), + TemplateArgs(TemplArgs) {} ClassScopeFunctionSpecializationDecl(EmptyShell Empty) : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} CXXMethodDecl *Specialization; + bool HasExplicitTemplateArgs; + TemplateArgumentListInfo TemplateArgs; public: CXXMethodDecl *getSpecialization() const { return Specialization; } + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; } static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, - CXXMethodDecl *FD) { - return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD); + CXXMethodDecl *FD, + bool HasExplicitTemplateArgs, + TemplateArgumentListInfo TemplateArgs) { + return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD, + HasExplicitTemplateArgs, + TemplateArgs); } static ClassScopeFunctionSpecializationDecl * diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index d751d556e9..4ad9da30e1 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1283,7 +1283,13 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, { }) DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { - TRY_TO(TraverseDecl(D->getSpecialization())); + TRY_TO(TraverseDecl(D->getSpecialization())); + + if (D->hasExplicitTemplateArgs()) { + const TemplateArgumentListInfo& args = D->templateArgs(); + TRY_TO(TraverseTemplateArgumentLocsHelper( + args.getArgumentArray(), args.size())); + } }) DEF_TRAVERSE_DECL(LinkageSpecDecl, { }) diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 9a338e5ee6..5aebc2b764 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -869,5 +869,6 @@ ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) { void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassScopeFunctionSpecializationDecl)); - return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0); + return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0, + false, TemplateArgumentListInfo()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1b0a0abdb2..40643896fd 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5066,7 +5066,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; + bool isDependentClassScopeExplicitSpecialization = false; + bool HasExplicitTemplateArgs = false; + TemplateArgumentListInfo TemplateArgs; + bool isVirtualOkay = false; FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC, @@ -5509,8 +5513,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } else { // If the declarator is a template-id, translate the parser's template // argument list into our AST format. - bool HasExplicitTemplateArgs = false; - TemplateArgumentListInfo TemplateArgs; if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { TemplateIdAnnotation *TemplateId = D.getName().TemplateId; TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); @@ -5814,8 +5816,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (isDependentClassScopeExplicitSpecialization) { ClassScopeFunctionSpecializationDecl *NewSpec = ClassScopeFunctionSpecializationDecl::Create( - Context, CurContext, SourceLocation(), - cast(NewFD)); + Context, CurContext, SourceLocation(), + cast(NewFD), + HasExplicitTemplateArgs, TemplateArgs); CurContext->addDecl(NewSpec); AddToScope = false; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d4b5ffe517..bbf8f50a3c 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1952,13 +1952,22 @@ Decl * TemplateDeclInstantiator Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *Decl) { CXXMethodDecl *OldFD = Decl->getSpecialization(); - CXXMethodDecl *NewFD = cast(VisitCXXMethodDecl(OldFD, 0, true)); + CXXMethodDecl *NewFD = cast(VisitCXXMethodDecl(OldFD, + 0, true)); LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); + TemplateArgumentListInfo TemplateArgs; + TemplateArgumentListInfo* TemplateArgsPtr = 0; + if (Decl->hasExplicitTemplateArgs()) { + TemplateArgs = Decl->templateArgs(); + TemplateArgsPtr = &TemplateArgs; + } + SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext); - if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, 0, Previous)) { + if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, TemplateArgsPtr, + Previous)) { NewFD->setInvalidDecl(); return NewFD; } diff --git a/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/test/SemaTemplate/ms-function-specialization-class-scope.cpp index bda87f99c9..131922bbfb 100644 --- a/test/SemaTemplate/ms-function-specialization-class-scope.cpp +++ b/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -69,3 +69,24 @@ void test2() b.f(100); } + +namespace PR12709 { + +template +class TemplateClass { + void member_function() { + specialized_member_template(); + } + + template + void specialized_member_template() {} + + template<> + void specialized_member_template() {} // expected-warning{{explicit specialization of 'specialized_member_template' within class scope is a Microsoft extension}} +}; + +void f() { + TemplateClass t; +} + +}