@@ -1722,9 +1722,16 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
1722
1722
// Preserve triviality.
1723
1723
NewMethod->setTrivial(OldMethod->isTrivial());
1724
1724
1725
+ // MSVC allows explicit template specialization at class scope:
1726
+ // 2 CXMethodDecls referring to the same function will be injected.
1727
+ // We don't want a redeclartion error.
1728
+ bool IsClassScopeExplicitSpecialization =
1729
+ OldMethod->isFunctionTemplateSpecialization() &&
1730
+ NewMethod->isFunctionTemplateSpecialization();
1725
1731
bool isFriend = NewMethod->getFriendObjectKind();
1726
1732
1727
- if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) {
1733
+ if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() &&
1734
+ !IsClassScopeExplicitSpecialization) {
1728
1735
// -- Member function declarations with the same name and the
1729
1736
// same parameter types cannot be overloaded if any of them
1730
1737
// is a static member function declaration.
@@ -3226,6 +3233,7 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
3226
3233
Previous.clear();
3227
3234
3228
3235
bool Redeclaration = false;
3236
+ bool AddToScope = true;
3229
3237
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
3230
3238
if (TemplateParamLists.size()) {
3231
3239
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
@@ -3236,7 +3244,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
3236
3244
} else if (R->isFunctionType()) {
3237
3245
New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous,
3238
3246
move(TemplateParamLists),
3239
- IsFunctionDefinition, Redeclaration);
3247
+ IsFunctionDefinition, Redeclaration,
3248
+ AddToScope);
3240
3249
} else {
3241
3250
New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous,
3242
3251
move(TemplateParamLists),
@@ -3248,7 +3257,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
3248
3257
3249
3258
// If this has an identifier and is not an invalid redeclaration or
3250
3259
// function template specialization, add it to the scope stack.
3251
- if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl()))
3260
+ if (New->getDeclName() && AddToScope &&
3261
+ !(Redeclaration && New->isInvalidDecl()))
3252
3262
PushOnScopeChains(New, S);
3253
3263
3254
3264
return New;
@@ -4201,7 +4211,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
4201
4211
QualType R, TypeSourceInfo *TInfo,
4202
4212
LookupResult &Previous,
4203
4213
MultiTemplateParamsArg TemplateParamLists,
4204
- bool IsFunctionDefinition, bool &Redeclaration) {
4214
+ bool IsFunctionDefinition, bool &Redeclaration,
4215
+ bool &AddToScope) {
4205
4216
assert(R.getTypePtr()->isFunctionType());
4206
4217
4207
4218
// TODO: consider using NameInfo for diagnostic.
@@ -4266,6 +4277,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
4266
4277
FunctionTemplateDecl *FunctionTemplate = 0;
4267
4278
bool isExplicitSpecialization = false;
4268
4279
bool isFunctionTemplateSpecialization = false;
4280
+ bool isDependentClassScopeExplicitSpecialization = false;
4269
4281
4270
4282
if (!getLangOptions().CPlusPlus) {
4271
4283
// Determine whether the function was written with a
@@ -4769,10 +4781,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
4769
4781
} else if (isFunctionTemplateSpecialization) {
4770
4782
if (CurContext->isDependentContext() && CurContext->isRecord()
4771
4783
&& !isFriend) {
4772
- Diag(NewFD->getLocation(), diag::err_function_specialization_in_class)
4784
+ isDependentClassScopeExplicitSpecialization = true;
4785
+ Diag(NewFD->getLocation(), getLangOptions().Microsoft ?
4786
+ diag::ext_function_specialization_in_class :
4787
+ diag::err_function_specialization_in_class)
4773
4788
<< NewFD->getDeclName();
4774
- NewFD->setInvalidDecl();
4775
- return 0;
4776
4789
} else if (CheckFunctionTemplateSpecialization(NewFD,
4777
4790
(HasExplicitTemplateArgs ? &TemplateArgs : 0),
4778
4791
Previous))
@@ -4802,8 +4815,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
4802
4815
}
4803
4816
4804
4817
// Perform semantic checking on the function declaration.
4805
- CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
4806
- Redeclaration);
4818
+ if (!isDependentClassScopeExplicitSpecialization)
4819
+ CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
4820
+ Redeclaration);
4807
4821
4808
4822
assert((NewFD->isInvalidDecl() || !Redeclaration ||
4809
4823
Previous.getResultKind() != LookupResult::FoundOverloaded) &&
@@ -4984,6 +4998,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
4984
4998
Context.setcudaConfigureCallDecl(NewFD);
4985
4999
}
4986
5000
}
5001
+
5002
+ // Here we have an function template explicit specialization at class scope.
5003
+ // The actually specialization will be postponed to template instatiation
5004
+ // time via the ClassScopeFunctionSpecializationDecl node.
5005
+ if (isDependentClassScopeExplicitSpecialization) {
5006
+ ClassScopeFunctionSpecializationDecl *NewSpec =
5007
+ ClassScopeFunctionSpecializationDecl::Create(
5008
+ Context, CurContext, SourceLocation(),
5009
+ cast<CXXMethodDecl>(NewFD));
5010
+ CurContext->addDecl(NewSpec);
5011
+ AddToScope = false;
5012
+ }
4987
5013
4988
5014
return NewFD;
4989
5015
}
0 commit comments