Make explicit specializations at class scope work

for non-type template parameters in microsoft mode.
PR12709.

llvm-svn: 159147
This commit is contained in:
Nico Weber 2012-06-25 17:21:05 +00:00
parent 07594cba7c
commit 7b5a716f3d
6 changed files with 62 additions and 12 deletions

View File

@ -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 *

View File

@ -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, { })

View File

@ -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());
}

View File

@ -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<CXXMethodDecl>(NewFD));
Context, CurContext, SourceLocation(),
cast<CXXMethodDecl>(NewFD),
HasExplicitTemplateArgs, TemplateArgs);
CurContext->addDecl(NewSpec);
AddToScope = false;
}

View File

@ -1952,13 +1952,22 @@ Decl * TemplateDeclInstantiator
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
ClassScopeFunctionSpecializationDecl *Decl) {
CXXMethodDecl *OldFD = Decl->getSpecialization();
CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, 0, true));
CXXMethodDecl *NewFD = cast<CXXMethodDecl>(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;
}

View File

@ -69,3 +69,24 @@ void test2()
b.f(100);
}
namespace PR12709 {
template<class T>
class TemplateClass {
void member_function() {
specialized_member_template<false>();
}
template<bool b>
void specialized_member_template() {}
template<>
void specialized_member_template<false>() {} // expected-warning{{explicit specialization of 'specialized_member_template' within class scope is a Microsoft extension}}
};
void f() {
TemplateClass<int> t;
}
}