forked from OSchip/llvm-project
Implement C++ DR727, which permits explicit specializations at class scope.
More generally, this permits a template to be specialized in any scope in which it could be defined, so this also supersedes DR44 and DR374 (the latter of which we previously only implemented in C++11 mode onwards due to unclarity as to whether it was a DR). llvm-svn: 327705
This commit is contained in:
parent
8dcf6fa308
commit
c660c8f5d2
|
@ -4144,42 +4144,20 @@ def note_explicit_specialization_declared_here : Note<
|
|||
"explicit specialization declared here">;
|
||||
def err_template_spec_decl_function_scope : Error<
|
||||
"explicit specialization of %0 in function scope">;
|
||||
def err_template_spec_decl_class_scope : Error<
|
||||
"explicit specialization of %0 in class scope">;
|
||||
def err_template_spec_decl_friend : Error<
|
||||
"cannot declare an explicit specialization in a friend">;
|
||||
def err_template_spec_decl_out_of_scope_global : Error<
|
||||
"%select{class template|class template partial|variable template|"
|
||||
"variable template partial|function template|member function|"
|
||||
"static data member|member class|member enumeration}0 "
|
||||
"specialization of %1 must originally be declared in the global scope">;
|
||||
def err_template_spec_decl_out_of_scope : Error<
|
||||
"%select{class template|class template partial|variable template|"
|
||||
"variable template partial|function template|member "
|
||||
"function|static data member|member class|member enumeration}0 "
|
||||
"specialization of %1 must originally be declared in namespace %2">;
|
||||
def ext_template_spec_decl_out_of_scope : ExtWarn<
|
||||
"first declaration of %select{class template|class template partial|"
|
||||
"variable template|variable template partial|"
|
||||
"function template|member function|static data member|member class|"
|
||||
"member enumeration}0 specialization of %1 outside namespace %2 is a "
|
||||
"C++11 extension">, InGroup<CXX11>;
|
||||
def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning<
|
||||
"%select{class template|class template partial|variable template|"
|
||||
"variable template partial|function template|member "
|
||||
"function|static data member|member class|member enumeration}0 "
|
||||
"specialization of %1 outside namespace %2 is incompatible with C++98">,
|
||||
InGroup<CXX98Compat>, DefaultIgnore;
|
||||
def err_template_spec_redecl_out_of_scope : Error<
|
||||
"%select{class template|class template partial|variable template|"
|
||||
"variable template partial|function template|member "
|
||||
"function|static data member|member class|member enumeration}0 "
|
||||
"specialization of %1 not in a namespace enclosing %2">;
|
||||
"specialization of %1 not in %select{a namespace enclosing %2|"
|
||||
"class %2 or an enclosing namespace}3">;
|
||||
def ext_ms_template_spec_redecl_out_of_scope: ExtWarn<
|
||||
"%select{class template|class template partial|variable template|"
|
||||
"variable template partial|function template|member "
|
||||
"function|static data member|member class|member enumeration}0 "
|
||||
"specialization of %1 outside namespace enclosing %2 "
|
||||
"specialization of %1 not in %select{a namespace enclosing %2|"
|
||||
"class %2 or an enclosing namespace}3 "
|
||||
"is a Microsoft extension">, InGroup<MicrosoftTemplate>;
|
||||
def err_template_spec_redecl_global_scope : Error<
|
||||
"%select{class template|class template partial|variable template|"
|
||||
|
@ -4201,11 +4179,6 @@ def err_template_spec_default_arg : Error<
|
|||
def err_not_class_template_specialization : Error<
|
||||
"cannot specialize a %select{dependent template|template template "
|
||||
"parameter}0">;
|
||||
def err_function_specialization_in_class : Error<
|
||||
"cannot specialize a function %0 within class scope">;
|
||||
def ext_function_specialization_in_class : ExtWarn<
|
||||
"explicit specialization of %0 within class scope is a Microsoft extension">,
|
||||
InGroup<MicrosoftTemplate>;
|
||||
def ext_explicit_specialization_storage_class : ExtWarn<
|
||||
"explicit specialization cannot have a storage class">;
|
||||
def err_explicit_specialization_inconsistent_storage_class : Error<
|
||||
|
|
|
@ -1849,8 +1849,8 @@ public:
|
|||
void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
|
||||
bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
|
||||
bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
|
||||
DeclarationName Name,
|
||||
SourceLocation Loc);
|
||||
DeclarationName Name, SourceLocation Loc,
|
||||
bool IsTemplateId);
|
||||
void
|
||||
diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
|
||||
SourceLocation FallbackLoc,
|
||||
|
|
|
@ -1602,7 +1602,7 @@ void ASTDumper::VisitClassTemplatePartialSpecializationDecl(
|
|||
|
||||
void ASTDumper::VisitClassScopeFunctionSpecializationDecl(
|
||||
const ClassScopeFunctionSpecializationDecl *D) {
|
||||
dumpDeclRef(D->getSpecialization());
|
||||
dumpDecl(D->getSpecialization());
|
||||
if (D->hasExplicitTemplateArgs())
|
||||
dumpTemplateArgumentListInfo(D->templateArgs());
|
||||
}
|
||||
|
|
|
@ -5231,10 +5231,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
|
|||
///
|
||||
/// \param Loc The location of the name of the entity being declared.
|
||||
///
|
||||
/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus
|
||||
/// we're declaring an explicit / partial specialization / instantiation.
|
||||
///
|
||||
/// \returns true if we cannot safely recover from this error, false otherwise.
|
||||
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
|
||||
DeclarationName Name,
|
||||
SourceLocation Loc) {
|
||||
SourceLocation Loc, bool IsTemplateId) {
|
||||
DeclContext *Cur = CurContext;
|
||||
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
|
||||
Cur = Cur->getParent();
|
||||
|
@ -5261,8 +5264,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
|
|||
}
|
||||
|
||||
// Check whether the qualifying scope encloses the scope of the original
|
||||
// declaration.
|
||||
if (!Cur->Encloses(DC)) {
|
||||
// declaration. For a template-id, we perform the checks in
|
||||
// CheckTemplateSpecializationScope.
|
||||
if (!Cur->Encloses(DC) && !IsTemplateId) {
|
||||
if (Cur->isRecord())
|
||||
Diag(Loc, diag::err_member_qualification)
|
||||
<< Name << SS.getRange();
|
||||
|
@ -5374,8 +5378,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
|
|||
return nullptr;
|
||||
}
|
||||
if (!D.getDeclSpec().isFriendSpecified()) {
|
||||
if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC,
|
||||
Name, D.getIdentifierLoc())) {
|
||||
if (diagnoseQualifiedDeclaration(
|
||||
D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(),
|
||||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) {
|
||||
if (DC->isRecord())
|
||||
return nullptr;
|
||||
|
||||
|
@ -8828,10 +8833,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
if (CurContext->isDependentContext() && CurContext->isRecord()
|
||||
&& !isFriend) {
|
||||
isDependentClassScopeExplicitSpecialization = true;
|
||||
Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ?
|
||||
diag::ext_function_specialization_in_class :
|
||||
diag::err_function_specialization_in_class)
|
||||
<< NewFD->getDeclName();
|
||||
} else if (!NewFD->isInvalidDecl() &&
|
||||
CheckFunctionTemplateSpecialization(
|
||||
NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
|
||||
|
@ -9117,12 +9118,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
|
||||
// Here we have an function template explicit specialization at class scope.
|
||||
// The actually specialization will be postponed to template instatiation
|
||||
// The actual specialization will be postponed to template instatiation
|
||||
// time via the ClassScopeFunctionSpecializationDecl node.
|
||||
if (isDependentClassScopeExplicitSpecialization) {
|
||||
ClassScopeFunctionSpecializationDecl *NewSpec =
|
||||
ClassScopeFunctionSpecializationDecl::Create(
|
||||
Context, CurContext, SourceLocation(),
|
||||
Context, CurContext, NewFD->getLocation(),
|
||||
cast<CXXMethodDecl>(NewFD),
|
||||
HasExplicitTemplateArgs, TemplateArgs);
|
||||
CurContext->addDecl(NewSpec);
|
||||
|
@ -9633,16 +9634,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
|||
Previous.clear();
|
||||
Previous.addDecl(OldDecl);
|
||||
|
||||
if (FunctionTemplateDecl *OldTemplateDecl
|
||||
= dyn_cast<FunctionTemplateDecl>(OldDecl)) {
|
||||
if (FunctionTemplateDecl *OldTemplateDecl =
|
||||
dyn_cast<FunctionTemplateDecl>(OldDecl)) {
|
||||
auto *OldFD = OldTemplateDecl->getTemplatedDecl();
|
||||
NewFD->setPreviousDeclaration(OldFD);
|
||||
adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
|
||||
FunctionTemplateDecl *NewTemplateDecl
|
||||
= NewFD->getDescribedFunctionTemplate();
|
||||
assert(NewTemplateDecl && "Template/non-template mismatch");
|
||||
if (auto *Method = dyn_cast<CXXMethodDecl>(NewFD)) {
|
||||
Method->setAccess(OldTemplateDecl->getAccess());
|
||||
if (NewFD->isCXXClassMember()) {
|
||||
NewFD->setAccess(OldTemplateDecl->getAccess());
|
||||
NewTemplateDecl->setAccess(OldTemplateDecl->getAccess());
|
||||
}
|
||||
|
||||
|
@ -9668,7 +9669,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
|||
// This needs to happen first so that 'inline' propagates.
|
||||
NewFD->setPreviousDeclaration(OldFD);
|
||||
adjustDeclContextForDeclaratorDecl(NewFD, OldFD);
|
||||
if (isa<CXXMethodDecl>(NewFD))
|
||||
if (NewFD->isCXXClassMember())
|
||||
NewFD->setAccess(OldFD->getAccess());
|
||||
}
|
||||
}
|
||||
|
@ -14310,13 +14311,10 @@ CreateNewDecl:
|
|||
if (SS.isNotEmpty()) {
|
||||
if (SS.isSet()) {
|
||||
// If this is either a declaration or a definition, check the
|
||||
// nested-name-specifier against the current context. We don't do this
|
||||
// for explicit specializations, because they have similar checking
|
||||
// (with more specific diagnostics) in the call to
|
||||
// CheckMemberSpecialization, below.
|
||||
if (!isMemberSpecialization &&
|
||||
(TUK == TUK_Definition || TUK == TUK_Declaration) &&
|
||||
diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc))
|
||||
// nested-name-specifier against the current context.
|
||||
if ((TUK == TUK_Definition || TUK == TUK_Declaration) &&
|
||||
diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc,
|
||||
isMemberSpecialization))
|
||||
Invalid = true;
|
||||
|
||||
New->setQualifierInfo(SS.getWithLocInContext(Context));
|
||||
|
|
|
@ -3051,7 +3051,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
// int X::member;
|
||||
// };
|
||||
if (DeclContext *DC = computeDeclContext(SS, false))
|
||||
diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc());
|
||||
diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
|
||||
D.getName().getKind() ==
|
||||
UnqualifiedIdKind::IK_TemplateId);
|
||||
else
|
||||
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
|
||||
<< Name << SS.getRange();
|
||||
|
|
|
@ -1262,7 +1262,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
|
||||
Invalid = true;
|
||||
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
|
||||
diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc);
|
||||
diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false);
|
||||
|
||||
LookupQualifiedName(Previous, SemanticContext);
|
||||
} else {
|
||||
|
@ -7124,120 +7124,43 @@ static bool CheckTemplateSpecializationScope(Sema &S,
|
|||
}
|
||||
|
||||
// C++ [temp.expl.spec]p2:
|
||||
// An explicit specialization shall be declared in the namespace
|
||||
// of which the template is a member, or, for member templates, in
|
||||
// the namespace of which the enclosing class or enclosing class
|
||||
// template is a member. An explicit specialization of a member
|
||||
// function, member class or static data member of a class
|
||||
// template shall be declared in the namespace of which the class
|
||||
// template is a member. Such a declaration may also be a
|
||||
// definition. If the declaration is not a definition, the
|
||||
// specialization may be defined later in the name- space in which
|
||||
// the explicit specialization was declared, or in a namespace
|
||||
// that encloses the one in which the explicit specialization was
|
||||
// declared.
|
||||
// An explicit specialization may be declared in any scope in which
|
||||
// the corresponding primary template may be defined.
|
||||
if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
|
||||
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
|
||||
<< Specialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (S.CurContext->isRecord() && !IsPartialSpecialization) {
|
||||
if (S.getLangOpts().MicrosoftExt) {
|
||||
// Do not warn for class scope explicit specialization during
|
||||
// instantiation, warning was already emitted during pattern
|
||||
// semantic analysis.
|
||||
if (!S.inTemplateInstantiation())
|
||||
S.Diag(Loc, diag::ext_function_specialization_in_class)
|
||||
<< Specialized;
|
||||
} else {
|
||||
S.Diag(Loc, diag::err_template_spec_decl_class_scope)
|
||||
<< Specialized;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (S.CurContext->isRecord() &&
|
||||
!S.CurContext->Equals(Specialized->getDeclContext())) {
|
||||
// Make sure that we're specializing in the right record context.
|
||||
// Otherwise, things can go horribly wrong.
|
||||
S.Diag(Loc, diag::err_template_spec_decl_class_scope)
|
||||
<< Specialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
// C++ [temp.class.spec]p6:
|
||||
// A class template partial specialization may be declared or redeclared
|
||||
// in any namespace scope in which its definition may be defined (14.5.1
|
||||
// and 14.5.2).
|
||||
DeclContext *SpecializedContext
|
||||
= Specialized->getDeclContext()->getEnclosingNamespaceContext();
|
||||
DeclContext *DC = S.CurContext->getEnclosingNamespaceContext();
|
||||
// A class template partial specialization may be declared in any
|
||||
// scope in which the primary template may be defined.
|
||||
DeclContext *SpecializedContext =
|
||||
Specialized->getDeclContext()->getRedeclContext();
|
||||
DeclContext *DC = S.CurContext->getRedeclContext();
|
||||
|
||||
// Make sure that this redeclaration (or definition) occurs in an enclosing
|
||||
// namespace.
|
||||
// Note that HandleDeclarator() performs this check for explicit
|
||||
// specializations of function templates, static data members, and member
|
||||
// functions, so we skip the check here for those kinds of entities.
|
||||
// FIXME: HandleDeclarator's diagnostics aren't quite as good, though.
|
||||
// Should we refactor that check, so that it occurs later?
|
||||
if (!DC->Encloses(SpecializedContext) &&
|
||||
!(isa<FunctionTemplateDecl>(Specialized) ||
|
||||
isa<FunctionDecl>(Specialized) ||
|
||||
isa<VarTemplateDecl>(Specialized) ||
|
||||
isa<VarDecl>(Specialized))) {
|
||||
// Make sure that this redeclaration (or definition) occurs in the same
|
||||
// scope or an enclosing namespace.
|
||||
if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext)
|
||||
: DC->Equals(SpecializedContext))) {
|
||||
if (isa<TranslationUnitDecl>(SpecializedContext))
|
||||
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
|
||||
<< EntityKind << Specialized;
|
||||
else if (isa<NamespaceDecl>(SpecializedContext)) {
|
||||
else {
|
||||
auto *ND = cast<NamedDecl>(SpecializedContext);
|
||||
int Diag = diag::err_template_spec_redecl_out_of_scope;
|
||||
if (S.getLangOpts().MicrosoftExt)
|
||||
if (S.getLangOpts().MicrosoftExt && !DC->isRecord())
|
||||
Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
|
||||
S.Diag(Loc, Diag) << EntityKind << Specialized
|
||||
<< cast<NamedDecl>(SpecializedContext);
|
||||
} else
|
||||
llvm_unreachable("unexpected namespace context for specialization");
|
||||
<< ND << isa<CXXRecordDecl>(ND);
|
||||
}
|
||||
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
|
||||
} else if ((!PrevDecl ||
|
||||
getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared ||
|
||||
getTemplateSpecializationKind(PrevDecl) ==
|
||||
TSK_ImplicitInstantiation)) {
|
||||
// C++ [temp.exp.spec]p2:
|
||||
// An explicit specialization shall be declared in the namespace of which
|
||||
// the template is a member, or, for member templates, in the namespace
|
||||
// of which the enclosing class or enclosing class template is a member.
|
||||
// An explicit specialization of a member function, member class or
|
||||
// static data member of a class template shall be declared in the
|
||||
// namespace of which the class template is a member.
|
||||
//
|
||||
// C++11 [temp.expl.spec]p2:
|
||||
// An explicit specialization shall be declared in a namespace enclosing
|
||||
// the specialized template.
|
||||
// C++11 [temp.explicit]p3:
|
||||
// An explicit instantiation shall appear in an enclosing namespace of its
|
||||
// template.
|
||||
if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
|
||||
bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext);
|
||||
if (isa<TranslationUnitDecl>(SpecializedContext)) {
|
||||
assert(!IsCPlusPlus11Extension &&
|
||||
"DC encloses TU but isn't in enclosing namespace set");
|
||||
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
|
||||
<< EntityKind << Specialized;
|
||||
} else if (isa<NamespaceDecl>(SpecializedContext)) {
|
||||
int Diag;
|
||||
if (!IsCPlusPlus11Extension)
|
||||
Diag = diag::err_template_spec_decl_out_of_scope;
|
||||
else if (!S.getLangOpts().CPlusPlus11)
|
||||
Diag = diag::ext_template_spec_decl_out_of_scope;
|
||||
else
|
||||
Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope;
|
||||
S.Diag(Loc, Diag)
|
||||
<< EntityKind << Specialized << cast<NamedDecl>(SpecializedContext);
|
||||
}
|
||||
|
||||
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
|
||||
}
|
||||
// Don't allow specializing in the wrong class during error recovery.
|
||||
// Otherwise, things can go horribly wrong.
|
||||
if (DC->isRecord())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -1653,6 +1653,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
NameInfo, T, TInfo, D->getSourceRange().getEnd());
|
||||
if (DGuide->isCopyDeductionCandidate())
|
||||
cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
|
||||
Function->setAccess(D->getAccess());
|
||||
} else {
|
||||
Function = FunctionDecl::Create(
|
||||
SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
|
||||
|
@ -2711,6 +2712,8 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
|
|||
assert(Specialization && "Class scope Specialization is null");
|
||||
SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD);
|
||||
|
||||
// FIXME: If this is a definition, check for redefinition errors!
|
||||
|
||||
return NewFD;
|
||||
}
|
||||
|
||||
|
|
|
@ -499,10 +499,10 @@ namespace dr42 { // dr42: yes
|
|||
|
||||
// dr43: na
|
||||
|
||||
namespace dr44 { // dr44: yes
|
||||
namespace dr44 { // dr44: sup 727
|
||||
struct A {
|
||||
template<int> void f();
|
||||
template<> void f<0>(); // expected-error {{explicit specialization of 'f' in class scope}}
|
||||
template<> void f<0>();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -925,7 +925,7 @@ namespace dr373 { // dr373: 5
|
|||
using namespace A::B; // expected-error {{expected namespace name}}
|
||||
}
|
||||
|
||||
namespace dr374 { // dr374: yes c++11
|
||||
namespace dr374 { // dr374: yes
|
||||
namespace N {
|
||||
template<typename T> void f();
|
||||
template<typename T> struct A { void f(); };
|
||||
|
@ -933,11 +933,6 @@ namespace dr374 { // dr374: yes c++11
|
|||
template<> void N::f<char>() {}
|
||||
template<> void N::A<char>::f() {}
|
||||
template<> struct N::A<int> {};
|
||||
#if __cplusplus < 201103L
|
||||
// expected-error@-4 {{extension}} expected-note@-7 {{here}}
|
||||
// expected-error@-4 {{extension}} expected-note@-7 {{here}}
|
||||
// expected-error@-4 {{extension}} expected-note@-8 {{here}}
|
||||
#endif
|
||||
}
|
||||
|
||||
// dr375: dup 345
|
||||
|
|
|
@ -3,6 +3,53 @@
|
|||
// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
|
||||
namespace dr727 { // dr727: 7
|
||||
struct A {
|
||||
template<typename T> struct C; // expected-note 6{{here}}
|
||||
template<typename T> void f(); // expected-note {{here}}
|
||||
template<typename T> static int N; // expected-error 0-1{{C++14}} expected-note 6{{here}}
|
||||
|
||||
template<> struct C<int>;
|
||||
template<> void f<int>();
|
||||
template<> static int N<int>;
|
||||
|
||||
template<typename T> struct C<T*>;
|
||||
template<typename T> static int N<T*>;
|
||||
|
||||
struct B {
|
||||
template<> struct C<float>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<> void f<float>(); // expected-error {{no function template matches}}
|
||||
template<> static int N<float>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
|
||||
template<typename T> struct C<T**>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<typename T> static int N<T**>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
|
||||
template<> struct A::C<double>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<> void A::f<double>(); // expected-error {{no function template matches}} expected-error {{cannot have a qualified name}}
|
||||
template<> static int A::N<double>; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}}
|
||||
|
||||
template<typename T> struct A::C<T***>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<typename T> static int A::N<T***>; // expected-error {{not in class 'A' or an enclosing namespace}} expected-error {{cannot have a qualified name}}
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct A::C<char>;
|
||||
template<> void A::f<char>();
|
||||
template<> int A::N<char>;
|
||||
|
||||
template<typename T> struct A::C<T****>;
|
||||
template<typename T> int A::N<T****>;
|
||||
|
||||
namespace C {
|
||||
template<> struct A::C<long>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<> void A::f<long>(); // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<> int A::N<long>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
|
||||
template<typename T> struct A::C<T*****>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
template<typename T> int A::N<T*****>; // expected-error {{not in class 'A' or an enclosing namespace}}
|
||||
}
|
||||
}
|
||||
|
||||
namespace dr777 { // dr777: 3.7
|
||||
#if __cplusplus >= 201103L
|
||||
template <typename... T>
|
||||
|
@ -16,5 +63,3 @@ template <typename... T>
|
|||
void h(int i = 0, T ...args, int j = 1) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace ExplicitInst {
|
|||
struct X {
|
||||
template<typename T> struct C {};
|
||||
template<typename T> C(T) -> C<T>;
|
||||
template<> C(int) -> C<int>; // expected-error {{explicit specialization of '<deduction guide for C>' in class scope}}
|
||||
template<> C(int) -> C<int>; // expected-error {{deduction guide cannot be explicitly specialized}}
|
||||
extern template C(float) -> C<float>; // expected-error {{expected member name or ';'}}
|
||||
template C(char) -> C<char>; // expected-error {{expected '<' after 'template'}}
|
||||
};
|
||||
|
|
|
@ -28,10 +28,8 @@ T pi1 = T(3.1415926535897932385); // expected-note 0-2 {{here}}
|
|||
|
||||
// Should recover as if specialization
|
||||
template float pi1<float> = 1.0; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}}
|
||||
#ifndef FIXING
|
||||
namespace expected_global {
|
||||
template<> double pi1<double> = 1.5; // expected-error {{variable template specialization of 'pi1' must originally be declared in the global scope}}
|
||||
template int pi1<int> = 10; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} \
|
||||
expected-error {{variable template specialization of 'pi1' must originally be declared in the global scope}}
|
||||
}
|
||||
#ifndef FIXING
|
||||
template int pi1<int> = 10; // expected-error {{explicit template instantiation cannot have a definition; if this definition is meant to be an explicit specialization, add '<>' after the 'template' keyword}} expected-error {{must occur at global scope}}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -10,9 +10,6 @@ struct NonDefaultConstructible {
|
|||
NonDefaultConstructible(int);
|
||||
};
|
||||
|
||||
// FIXME: The "must originally be declared in namespace" diagnostics throughout
|
||||
// this file are wrong.
|
||||
|
||||
// C++ [temp.expl.spec]p1:
|
||||
// An explicit specialization of any of the following:
|
||||
|
||||
|
@ -43,7 +40,7 @@ template<> void N0::f0(double) { }
|
|||
struct X1 {
|
||||
template<typename T> void f(T);
|
||||
|
||||
template<> void f(int); // expected-error{{in class scope}}
|
||||
template<> void f(int); // OK (DR727)
|
||||
};
|
||||
|
||||
// -- class template
|
||||
|
@ -94,7 +91,7 @@ template<> struct N0::X0<volatile void> {
|
|||
|
||||
// -- variable template [C++1y]
|
||||
namespace N0 {
|
||||
template<typename T> int v0; // expected-note +{{here}}
|
||||
template<typename T> int v0; // expected-note 4{{explicitly specialized declaration is here}}
|
||||
template<> extern int v0<char[1]>;
|
||||
template<> extern int v0<char[2]>;
|
||||
template<> extern int v0<char[5]>;
|
||||
|
@ -102,32 +99,32 @@ template<> extern int v0<char[6]>;
|
|||
}
|
||||
using N0::v0;
|
||||
|
||||
template<typename T> int v1; // expected-note +{{here}}
|
||||
template<typename T> int v1; // expected-note 4{{explicitly specialized declaration is here}}
|
||||
template<> extern int v1<char[3]>;
|
||||
template<> extern int v1<char[4]>;
|
||||
template<> extern int v1<char[7]>;
|
||||
template<> extern int v1<char[8]>;
|
||||
|
||||
template<> int N0::v0<int[1]>;
|
||||
template<> int v0<int[2]>; // FIXME: ill-formed
|
||||
template<> int v0<int[2]>;
|
||||
template<> int ::v1<int[3]>; // expected-warning {{extra qualification}}
|
||||
template<> int v1<int[4]>;
|
||||
|
||||
template<> int N0::v0<char[1]>;
|
||||
template<> int v0<char[2]>; // FIXME: ill-formed
|
||||
template<> int v0<char[2]>;
|
||||
template<> int ::v1<char[3]>; // expected-warning {{extra qualification}}
|
||||
template<> int v1<char[4]>;
|
||||
|
||||
namespace N1 {
|
||||
template<> int N0::v0<int[5]>; // expected-error {{must originally be declared in namespace 'N0'}} expected-error {{does not enclose namespace}}
|
||||
template<> int v0<int[6]>; // expected-error {{must originally be declared in namespace 'N0'}}
|
||||
template<> int ::v1<int[7]>; // expected-error {{must originally be declared in the global scope}} expected-error {{cannot name the global scope}}
|
||||
template<> int v1<int[8]>; // expected-error {{must originally be declared in the global scope}}
|
||||
template<> int N0::v0<int[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
|
||||
template<> int v0<int[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
|
||||
template<> int ::v1<int[7]>; // expected-error {{must occur at global scope}}
|
||||
template<> int v1<int[8]>; // expected-error {{must occur at global scope}}
|
||||
|
||||
template<> int N0::v0<char[5]>; // expected-error {{does not enclose namespace 'N0'}}
|
||||
template<> int v0<char[6]>; // FIXME: ill-formed
|
||||
template<> int ::v1<char[7]>; // expected-error {{cannot name the global scope}}
|
||||
template<> int v1<char[8]>; // FIXME: ill-formed
|
||||
template<> int N0::v0<char[5]>; // expected-error {{not in a namespace enclosing 'N0'}}
|
||||
template<> int v0<char[6]>; // expected-error {{not in a namespace enclosing 'N0'}}
|
||||
template<> int ::v1<char[7]>; // expected-error {{must occur at global scope}}
|
||||
template<> int v1<char[8]>; // expected-error {{must occur at global scope}}
|
||||
}
|
||||
|
||||
// -- member function of a class template
|
||||
|
|
|
@ -20,9 +20,6 @@ struct NonDefaultConstructible {
|
|||
// -- function template
|
||||
namespace N0 {
|
||||
template<typename T> void f0(T) {
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
T t;
|
||||
}
|
||||
|
||||
|
@ -43,16 +40,13 @@ namespace N1 {
|
|||
}
|
||||
|
||||
template<> void N0::f0(double);
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of function template specialization of 'f0' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
template<> void N0::f0(double) { }
|
||||
|
||||
struct X1 {
|
||||
template<typename T> void f(T);
|
||||
|
||||
template<> void f(int); // expected-error{{in class scope}}
|
||||
template<> void f(int);
|
||||
};
|
||||
|
||||
// -- class template
|
||||
|
@ -60,38 +54,20 @@ namespace N0 {
|
|||
|
||||
template<typename T>
|
||||
struct X0 { // expected-note {{explicitly specialized declaration is here}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
static T member;
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
|
||||
void f1(T t) {
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
t = 17;
|
||||
}
|
||||
|
||||
struct Inner : public T { }; // expected-note 2{{explicitly specialized declaration is here}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
|
||||
template<typename U>
|
||||
struct InnerTemplate : public T { }; // expected-note {{explicitly specialized declaration is here}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
// expected-error@-4 {{base specifier must name a class}}
|
||||
// expected-error@-1 {{base specifier must name a class}}
|
||||
|
||||
template<typename U>
|
||||
void ft1(T t, U u);
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -105,9 +81,6 @@ void N0::X0<T>::ft1(T t, U u) {
|
|||
template<typename T> T N0::X0<T>::member;
|
||||
|
||||
template<> struct N0::X0<void> { };
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of class template specialization of 'X0' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
N0::X0<void> test_X0;
|
||||
|
||||
namespace N1 {
|
||||
|
@ -124,9 +97,6 @@ template<> struct N0::X0<volatile void> {
|
|||
|
||||
// -- member function of a class template
|
||||
template<> void N0::X0<void*>::f1(void *) { }
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of member function specialization of 'f1' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
void test_spec(N0::X0<void*> xvp, void *vp) {
|
||||
xvp.f1(vp);
|
||||
|
@ -160,9 +130,6 @@ NonDefaultConstructible &get_static_member() {
|
|||
}
|
||||
|
||||
template<> int N0::X0<int>::member;
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of static data member specialization of 'member' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
template<> float N0::X0<float>::member = 3.14f;
|
||||
|
||||
|
@ -191,9 +158,6 @@ namespace N0 {
|
|||
|
||||
template<>
|
||||
struct N0::X0<long>::Inner { };
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of member class specialization of 'Inner' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct N0::X0<float>::Inner { };
|
||||
|
@ -233,9 +197,6 @@ struct N0::X0<int>::InnerTemplate<long> { }; // okay
|
|||
|
||||
template<> template<>
|
||||
struct N0::X0<int>::InnerTemplate<float> { };
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of class template specialization of 'InnerTemplate' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
namespace N1 {
|
||||
template<> template<>
|
||||
|
@ -268,9 +229,6 @@ void N0::X0<void*>::ft1(void *, unsigned) { } // okay
|
|||
|
||||
template<> template<>
|
||||
void N0::X0<void*>::ft1(void *, float) { }
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of function template specialization of 'ft1' outside namespace 'N0' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
namespace N1 {
|
||||
template<> template<>
|
||||
|
@ -293,6 +251,6 @@ namespace PR8979 {
|
|||
template<typename T, typename U> void f(Inner<T, U>&);
|
||||
|
||||
typedef Inner<OtherInner, OtherInner> MyInner;
|
||||
template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}}
|
||||
template<> void f(MyInner&);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,17 +4,9 @@
|
|||
|
||||
namespace N {
|
||||
template<class T> class X; // expected-note {{'N::X' declared here}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: Don't add a namespace qualifier to the template if it would trigger
|
||||
// the warning about the specialization being outside of the namespace.
|
||||
template<> class X<int> { /* ... */ }; // expected-error {{no template named 'X'; did you mean 'N::X'?}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of class template specialization of 'X' outside namespace 'N' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
namespace N {
|
||||
|
||||
|
|
|
@ -360,7 +360,9 @@ class TestClassScopeFunctionSpecialization {
|
|||
template<> void foo<int>(int a) { }
|
||||
};
|
||||
// CHECK: ClassScopeFunctionSpecializationDecl
|
||||
// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
|
||||
// CHECK-NEXT: CXXMethod{{.*}} foo 'void (int)'
|
||||
// CHECK-NEXT: ParmVarDecl
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: TemplateArgument{{.*}} 'int'
|
||||
|
||||
namespace TestTemplateTypeParmDecl {
|
||||
|
|
|
@ -489,7 +489,6 @@ void AfterClassBody() {
|
|||
namespace PR24246 {
|
||||
template <typename TX> struct A {
|
||||
template <bool> struct largest_type_select;
|
||||
// expected-warning@+1 {{explicit specialization of 'largest_type_select' within class scope is a Microsoft extension}}
|
||||
template <> struct largest_type_select<false> {
|
||||
blah x; // expected-error {{unknown type name 'blah'}}
|
||||
};
|
||||
|
|
|
@ -15,8 +15,8 @@ class A {
|
|||
template<typename T> static CONST T right<T,int> = 5;
|
||||
template<typename T> CONST int right<int,T>; // expected-error {{member 'right' declared as a template}}
|
||||
template<typename T> CONST float right<float,T> = 5; // expected-error {{member 'right' declared as a template}}
|
||||
template<> static CONST int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template<> static CONST float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template<> static CONST int right<int,int> = 7;
|
||||
template<> static CONST float right<float,int>;
|
||||
template static CONST int right<int,int>; // expected-error {{expected '<' after 'template'}}
|
||||
};
|
||||
|
||||
|
@ -163,8 +163,8 @@ namespace constexpred {
|
|||
template<typename T> constexpr int right<int,T>; // expected-error {{member 'right' declared as a template}} \
|
||||
// expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
|
||||
template<typename T> constexpr float right<float,T> = 5; // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
|
||||
template<> static constexpr int right<int,int> = 7; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template<> static constexpr float right<float,int>; // expected-error {{explicit specialization of 'right' in class scope}}
|
||||
template<> static constexpr int right<int,int> = 7;
|
||||
template<> static constexpr float right<float,int>; // expected-error {{requires an initializer}}
|
||||
template static constexpr int right<int,int>; // expected-error {{expected '<' after 'template'}}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ namespace nested {
|
|||
#endif
|
||||
float f1 = pi1a<float>;
|
||||
|
||||
template<> double pi1a<double> = 5.2; // expected-error {{variable template specialization of 'pi1a' must originally be declared in namespace 'n1'}}
|
||||
template<> double pi1a<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}
|
||||
double d1 = pi1a<double>;
|
||||
}
|
||||
|
||||
|
@ -422,8 +422,7 @@ namespace nested {
|
|||
#endif
|
||||
float f1 = n1::pi1b<float>;
|
||||
|
||||
template<> double n1::pi1b<double> = 5.2; // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \
|
||||
// expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}}
|
||||
template<> double n1::pi1b<double> = 5.2; // expected-error {{not in a namespace enclosing 'n1'}}
|
||||
double d1 = n1::pi1b<double>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,9 +185,9 @@ namespace RedundantParensInAddressTemplateParam {
|
|||
}
|
||||
|
||||
namespace TemplateSpecOutOfScopeNs {
|
||||
template<typename T> struct S {}; // expected-note {{here}}
|
||||
template<typename T> struct S {};
|
||||
}
|
||||
template<> struct TemplateSpecOutOfScopeNs::S<char> {}; // expected-warning {{class template specialization of 'S' outside namespace 'TemplateSpecOutOfScopeNs' is incompatible with C++98}}
|
||||
template<> struct TemplateSpecOutOfScopeNs::S<char> {};
|
||||
|
||||
struct Typename {
|
||||
template<typename T> struct Inner {};
|
||||
|
|
|
@ -78,9 +78,6 @@ template<> struct ::A<double>;
|
|||
|
||||
namespace N {
|
||||
template<typename T> struct B; // expected-note {{explicitly specialized}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-2 {{explicitly specialized}}
|
||||
#endif
|
||||
|
||||
template<> struct ::N::B<char>; // okay
|
||||
template<> struct ::N::B<short>; // okay
|
||||
|
@ -92,9 +89,6 @@ namespace N {
|
|||
template<> struct N::B<int> { }; // okay
|
||||
|
||||
template<> struct N::B<float> { };
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2 {{first declaration of class template specialization of 'B' outside namespace 'N' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
|
||||
namespace M {
|
||||
|
@ -121,9 +115,9 @@ class Wibble<int> { }; // expected-error{{cannot specialize a template template
|
|||
|
||||
namespace rdar9676205 {
|
||||
template<typename T>
|
||||
struct X {
|
||||
struct X { // expected-note {{here}}
|
||||
template<typename U>
|
||||
struct X<U*> { // expected-error{{explicit specialization of 'X' in class scope}}
|
||||
struct X<U*> { // expected-error{{partial specialization of 'X' not in a namespace enclosing}}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -18,16 +18,16 @@ template <typename T> struct X {
|
|||
namespace B {
|
||||
|
||||
template <>
|
||||
class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' outside namespace enclosing 'A' is a Microsoft extension}}
|
||||
class A::ClassTemplate<int>; // expected-warning {{class template specialization of 'ClassTemplate' not in a namespace enclosing 'A' is a Microsoft extension}}
|
||||
|
||||
template <class T1>
|
||||
class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' outside namespace enclosing 'A' is a Microsoft extension}}
|
||||
class A::ClassTemplatePartial<T1, T1 *> {}; // expected-warning {{class template partial specialization of 'ClassTemplatePartial' not in a namespace enclosing 'A' is a Microsoft extension}}
|
||||
|
||||
template <>
|
||||
struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' outside namespace enclosing 'A' is a Microsoft extension}}
|
||||
struct A::X<int>::MemberClass; // expected-warning {{member class specialization of 'MemberClass' not in class 'X' or an enclosing namespace is a Microsoft extension}}
|
||||
|
||||
template <>
|
||||
enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' outside namespace enclosing 'A' is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
|
||||
enum A::X<int>::MemberEnumeration; // expected-warning {{member enumeration specialization of 'MemberEnumeration' not in class 'X' or an enclosing namespace is a Microsoft extension}} // expected-error {{ISO C++ forbids forward references to 'enum' types}}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -54,5 +54,5 @@ class Foo {
|
|||
|
||||
// Don't crash here.
|
||||
template<>
|
||||
static void Bar(const long& input) {} // expected-error{{explicit specialization of 'Bar' in class scope}}
|
||||
static void Bar(const long& input) {} // expected-warning{{explicit specialization cannot have a storage class}}
|
||||
};
|
||||
|
|
|
@ -185,7 +185,7 @@ namespace SameSignatureAfterInstantiation {
|
|||
|
||||
namespace PR22040 {
|
||||
template <typename T> struct Foobar {
|
||||
template <> void bazqux(typename T::type) {} // expected-error {{cannot specialize a function 'bazqux' within class scope}} expected-error 2{{cannot be used prior to '::' because it has no members}}
|
||||
template <> void bazqux(typename T::type) {} // expected-error 2{{cannot be used prior to '::' because it has no members}}
|
||||
};
|
||||
|
||||
void test() {
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
class A {
|
||||
public:
|
||||
template<class U> A(U p) {}
|
||||
template<> A(int p) {
|
||||
// expected-warning@-1 {{explicit specialization of 'A' within class scope is a Microsoft extension}}
|
||||
}
|
||||
template<> A(int p) {}
|
||||
|
||||
template<class U> void f(U p) {}
|
||||
|
||||
template<> void f(int p) {
|
||||
// expected-warning@-1 {{explicit specialization of 'f' within class scope is a Microsoft extension}}
|
||||
}
|
||||
template<> void f(int p) {}
|
||||
|
||||
void f(int p) {}
|
||||
};
|
||||
|
@ -28,14 +25,11 @@ void test1() {
|
|||
template<class T> class B {
|
||||
public:
|
||||
template<class U> B(U p) {}
|
||||
template<> B(int p) {
|
||||
// expected-warning@-1 {{explicit specialization of 'B<T>' within class scope is a Microsoft extension}}
|
||||
}
|
||||
template<> B(int p) {}
|
||||
|
||||
template<class U> void f(U p) { T y = 9; }
|
||||
|
||||
template<> void f(int p) {
|
||||
// expected-warning@-1 {{explicit specialization of 'f' within class scope is a Microsoft extension}}
|
||||
T a = 3;
|
||||
}
|
||||
|
||||
|
@ -56,9 +50,7 @@ namespace PR12709 {
|
|||
|
||||
template<bool b> void specialized_member_template() {}
|
||||
|
||||
template<> void specialized_member_template<false>() {
|
||||
// expected-warning@-1 {{explicit specialization of 'specialized_member_template' within class scope is a Microsoft extension}}
|
||||
}
|
||||
template<> void specialized_member_template<false>() {}
|
||||
};
|
||||
|
||||
void f() { TemplateClass<int> t; }
|
||||
|
@ -67,8 +59,8 @@ namespace PR12709 {
|
|||
namespace Duplicates {
|
||||
template<typename T> struct A {
|
||||
template<typename U> void f();
|
||||
template<> void f<int>() {} // expected-warning {{Microsoft extension}}
|
||||
template<> void f<T>() {} // expected-warning {{Microsoft extension}}
|
||||
template<> void f<int>() {}
|
||||
template<> void f<T>() {}
|
||||
};
|
||||
|
||||
// FIXME: We should diagnose the duplicate explicit specialization definitions
|
||||
|
@ -81,6 +73,6 @@ struct S {
|
|||
template <int>
|
||||
int f(int = 0);
|
||||
template <>
|
||||
int f<0>(int); // expected-warning {{Microsoft extension}}
|
||||
int f<0>(int);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,17 +7,11 @@ template<typename T> struct vector;
|
|||
namespace N {
|
||||
namespace M {
|
||||
template<typename T> struct A;
|
||||
#if __cplusplus <= 199711L // C++03 or earlier modes
|
||||
// expected-note@-2{{explicitly specialized declaration is here}}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct N::M::A<T*> { };
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-warning@-2{{first declaration of class template partial specialization of 'A' outside namespace 'M' is a C++11 extension}}
|
||||
#endif
|
||||
|
||||
// C++ [temp.class.spec]p9
|
||||
// bullet 1, as amended by DR1315
|
||||
|
|
|
@ -303,7 +303,7 @@
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#44">44</a></td>
|
||||
<td>CD1</td>
|
||||
<td>Member specializations</td>
|
||||
<td class="full" align="center">Yes</td>
|
||||
<td class="svn" align="center">Superseded by <a href="#727">727</a></td>
|
||||
</tr>
|
||||
<tr id="45">
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45">45</a></td>
|
||||
|
@ -2285,7 +2285,7 @@ of class templates</td>
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374">374</a></td>
|
||||
<td>CD2</td>
|
||||
<td>Can explicit specialization outside namespace use qualified name?</td>
|
||||
<td class="full" align="center">Yes (C++11 onwards)</td>
|
||||
<td class="full" align="center">Yes</td>
|
||||
</tr>
|
||||
<tr id="375">
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#375">375</a></td>
|
||||
|
@ -4387,7 +4387,7 @@ and <I>POD class</I></td>
|
|||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#727">727</a></td>
|
||||
<td>C++17</td>
|
||||
<td>In-class explicit specializations</td>
|
||||
<td class="none" align="center">Unknown</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
</tr>
|
||||
<tr class="open" id="728">
|
||||
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#728">728</a></td>
|
||||
|
|
Loading…
Reference in New Issue