diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-12-07 05:09:50 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-12-07 05:09:50 +0000 |
commit | a98f8fc8d842651619bb67f98ec6f211d8b206a5 (patch) | |
tree | 6435211b0e2e7a1724710a8692b51888db6fd222 | |
parent | 567befd88fd6e21ab9c02c5db51a753b9430dc68 (diff) | |
download | bcm5719-llvm-a98f8fc8d842651619bb67f98ec6f211d8b206a5.tar.gz bcm5719-llvm-a98f8fc8d842651619bb67f98ec6f211d8b206a5.zip |
Give a more appropriate diagnostic when a template specialization or
instantiation appears in a non-enclosing namespace (the previous diagnostic
talked about the C++98 rule even in C++11 mode).
llvm-svn: 196642
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 64 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/no-body.cpp | 4 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaTemplate/class-template-spec.cpp | 2 |
5 files changed, 38 insertions, 36 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0376d106eae..d72c04c0121 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5596,13 +5596,37 @@ static bool CheckTemplateSpecializationScope(Sema &S, // 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). - bool ComplainedAboutScope = false; - DeclContext *SpecializedContext + DeclContext *SpecializedContext = Specialized->getDeclContext()->getEnclosingNamespaceContext(); DeclContext *DC = S.CurContext->getEnclosingNamespaceContext(); - if ((!PrevDecl || - getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared || - getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){ + + // 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))) { + if (isa<TranslationUnitDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_redecl_global_scope) + << EntityKind << Specialized; + else if (isa<NamespaceDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope) + << EntityKind << Specialized + << cast<NamedDecl>(SpecializedContext); + else + llvm_unreachable("unexpected namespace context for specialization"); + + 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 @@ -5611,9 +5635,12 @@ static bool CheckTemplateSpecializationScope(Sema &S, // static data member of a class template shall be declared in the // namespace of which the class template is a member. // - // C++0x [temp.expl.spec]p2: + // 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)) { @@ -5634,34 +5661,9 @@ static bool CheckTemplateSpecializationScope(Sema &S, } S.Diag(Specialized->getLocation(), diag::note_specialized_entity); - ComplainedAboutScope = - !(IsCPlusPlus11Extension && S.getLangOpts().CPlusPlus11); } } - // 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 (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) && - !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) || - isa<FunctionDecl>(Specialized))) { - if (isa<TranslationUnitDecl>(SpecializedContext)) - S.Diag(Loc, diag::err_template_spec_redecl_global_scope) - << EntityKind << Specialized; - else if (isa<NamespaceDecl>(SpecializedContext)) - S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope) - << EntityKind << Specialized - << cast<NamedDecl>(SpecializedContext); - - S.Diag(Specialized->getLocation(), diag::note_specialized_entity); - } - - // FIXME: check for specialization-after-instantiation errors and such. - return false; } diff --git a/clang/test/CXX/temp/temp.spec/no-body.cpp b/clang/test/CXX/temp/temp.spec/no-body.cpp index a4d7914d9eb..61d285b27ed 100644 --- a/clang/test/CXX/temp/temp.spec/no-body.cpp +++ b/clang/test/CXX/temp/temp.spec/no-body.cpp @@ -37,7 +37,7 @@ namespace noargs_body { namespace exp_spec { #ifndef FIXING template<> void f0<int>(int) { } // expected-error {{no function template matches function template specialization 'f0'}} - template<> struct x0<int> { }; // expected-error {{class template specialization of 'x0' must originally be declared in the global scope}} + template<> struct x0<int> { }; // expected-error {{class template specialization of 'x0' must occur at global scope}} #endif } @@ -51,7 +51,7 @@ namespace args_bad { template void f1<int>(int) { } // 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 {{no function template matches function template specialization 'f1'}} template struct x1<int> { }; // 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 {{class template specialization of 'x1' must originally be declared in the global scope}} + expected-error {{class template specialization of 'x1' must occur at global scope}} #endif } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp index 75b198e47d1..1a7065e0022 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp @@ -79,7 +79,7 @@ template<> struct N0::X0<void> { }; N0::X0<void> test_X0; namespace N1 { - template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' must originally be declared in namespace 'N0'}} + template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' not in a namespace enclosing 'N0'}} } namespace N0 { diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp index c972bf7c7d0..4fbc45a7d7d 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -80,7 +80,7 @@ template<> struct N0::X0<void> { }; // expected-warning{{C++11 extension}} N0::X0<void> test_X0; namespace N1 { - template<> struct N0::X0<const void> { }; // expected-error{{originally}} + template<> struct N0::X0<const void> { }; // expected-error{{not in a namespace enclosing 'N0'}} } namespace N0 { diff --git a/clang/test/SemaTemplate/class-template-spec.cpp b/clang/test/SemaTemplate/class-template-spec.cpp index f9015b37ea0..e82537abded 100644 --- a/clang/test/SemaTemplate/class-template-spec.cpp +++ b/clang/test/SemaTemplate/class-template-spec.cpp @@ -91,7 +91,7 @@ template<> struct N::B<float> { }; // expected-warning{{C++11 extension}} namespace M { template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}} - template<> struct ::A<long double>; // expected-error{{originally}} + template<> struct ::A<long double>; // expected-error{{must occur at global scope}} } template<> struct N::B<char> { |