Author: rsmith Date: Fri Mar 16 06:36:56 2018 New Revision: 327705 URL: http://llvm.org/viewvc/llvm-project?rev=327705&view=rev Log: 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). Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ASTDumper.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/CXX/drs/dr0xx.cpp cfe/trunk/test/CXX/drs/dr3xx.cpp cfe/trunk/test/CXX/drs/dr7xx.cpp cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp cfe/trunk/test/Misc/ast-dump-decl.cpp cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp cfe/trunk/test/SemaCXX/cxx98-compat.cpp cfe/trunk/test/SemaTemplate/class-template-spec.cpp cfe/trunk/test/SemaTemplate/ext_ms_template_spec.cpp cfe/trunk/test/SemaTemplate/function-template-specialization.cpp cfe/trunk/test/SemaTemplate/instantiate-method.cpp cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp cfe/trunk/www/cxx_dr_status.html Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar 16 06:36:56 2018 @@ -4144,42 +4144,20 @@ def note_explicit_specialization_declare "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 : Erro 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< Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 16 06:36:56 2018 @@ -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, Modified: cfe/trunk/lib/AST/ASTDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTDumper.cpp (original) +++ cfe/trunk/lib/AST/ASTDumper.cpp Fri Mar 16 06:36:56 2018 @@ -1602,7 +1602,7 @@ void ASTDumper::VisitClassTemplatePartia void ASTDumper::VisitClassScopeFunctionSpecializationDecl( const ClassScopeFunctionSpecializationDecl *D) { - dumpDeclRef(D->getSpecialization()); + dumpDecl(D->getSpecialization()); if (D->hasExplicitTemplateArgs()) dumpTemplateArgumentListInfo(D->templateArgs()); } Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Mar 16 06:36:56 2018 @@ -5231,10 +5231,13 @@ bool Sema::DiagnoseClassNameShadow(DeclC /// /// \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( } // 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 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, 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, } // 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(Scop 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(Scop // 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)); Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Mar 16 06:36:56 2018 @@ -3051,7 +3051,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, // 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(); Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Mar 16 06:36:56 2018 @@ -1262,7 +1262,7 @@ Sema::CheckClassTemplate(Scope *S, unsig 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 CheckTemplateSpecializationS } // 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(); - - // 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))) { + // 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 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; Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Mar 16 06:36:56 2018 @@ -1653,6 +1653,7 @@ Decl *TemplateDeclInstantiator::VisitFun 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::VisitCla assert(Specialization && "Class scope Specialization is null"); SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD); + // FIXME: If this is a definition, check for redefinition errors! + return NewFD; } Modified: cfe/trunk/test/CXX/drs/dr0xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr0xx.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr0xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr0xx.cpp Fri Mar 16 06:36:56 2018 @@ -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>(); }; } Modified: cfe/trunk/test/CXX/drs/dr3xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr3xx.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr3xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr3xx.cpp Fri Mar 16 06:36:56 2018 @@ -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 Modified: cfe/trunk/test/CXX/drs/dr7xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr7xx.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr7xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr7xx.cpp Fri Mar 16 06:36:56 2018 @@ -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 Modified: cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.deduct.guide/p1.cpp Fri Mar 16 06:36:56 2018 @@ -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'}} }; Modified: cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp Fri Mar 16 06:36:56 2018 @@ -28,10 +28,8 @@ T pi1 = T(3.1415926535897932385); // exp // 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 +} Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp Fri Mar 16 06:36:56 2018 @@ -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<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<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 {{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 Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp Fri Mar 16 06:36:56 2018 @@ -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_memb } 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> 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 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&); }; } Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp (original) +++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp Fri Mar 16 06:36:56 2018 @@ -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 { Modified: cfe/trunk/test/Misc/ast-dump-decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-decl.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/Misc/ast-dump-decl.cpp (original) +++ cfe/trunk/test/Misc/ast-dump-decl.cpp Fri Mar 16 06:36:56 2018 @@ -360,7 +360,9 @@ class TestClassScopeFunctionSpecializati 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 { Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original) +++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Fri Mar 16 06:36:56 2018 @@ -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'}} }; Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_in_class.cpp Fri Mar 16 06:36:56 2018 @@ -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'}} }; } Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Fri Mar 16 06:36:56 2018 @@ -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>; } } Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Fri Mar 16 06:36:56 2018 @@ -185,9 +185,9 @@ namespace RedundantParensInAddressTempla } 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 {}; Modified: cfe/trunk/test/SemaTemplate/class-template-spec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-spec.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/class-template-spec.cpp (original) +++ cfe/trunk/test/SemaTemplate/class-template-spec.cpp Fri Mar 16 06:36:56 2018 @@ -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 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}} }; }; Modified: cfe/trunk/test/SemaTemplate/ext_ms_template_spec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ext_ms_template_spec.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/ext_ms_template_spec.cpp (original) +++ cfe/trunk/test/SemaTemplate/ext_ms_template_spec.cpp Fri Mar 16 06:36:56 2018 @@ -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}} } Modified: cfe/trunk/test/SemaTemplate/function-template-specialization.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/function-template-specialization.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/function-template-specialization.cpp (original) +++ cfe/trunk/test/SemaTemplate/function-template-specialization.cpp Fri Mar 16 06:36:56 2018 @@ -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}} }; Modified: cfe/trunk/test/SemaTemplate/instantiate-method.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-method.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/instantiate-method.cpp (original) +++ cfe/trunk/test/SemaTemplate/instantiate-method.cpp Fri Mar 16 06:36:56 2018 @@ -185,7 +185,7 @@ namespace SameSignatureAfterInstantiatio 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() { Modified: cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp (original) +++ cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp Fri Mar 16 06:36:56 2018 @@ -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); }; } Modified: cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp (original) +++ cfe/trunk/test/SemaTemplate/temp_class_spec_neg.cpp Fri Mar 16 06:36:56 2018 @@ -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 Modified: cfe/trunk/www/cxx_dr_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=327705&r1=327704&r2=327705&view=diff ============================================================================== --- cfe/trunk/www/cxx_dr_status.html (original) +++ cfe/trunk/www/cxx_dr_status.html Fri Mar 16 06:36:56 2018 @@ -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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits