r196642 - Give a more appropriate diagnostic when a template specialization or
Richard Smith
richard-llvm at metafoo.co.uk
Fri Dec 6 21:09:50 PST 2013
Author: rsmith
Date: Fri Dec 6 23:09:50 2013
New Revision: 196642
URL: http://llvm.org/viewvc/llvm-project?rev=196642&view=rev
Log:
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).
Modified:
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/temp/temp.spec/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/SemaTemplate/class-template-spec.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=196642&r1=196641&r2=196642&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Dec 6 23:09:50 2013
@@ -5596,13 +5596,37 @@ static bool CheckTemplateSpecializationS
// 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 CheckTemplateSpecializationS
// 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 CheckTemplateSpecializationS
}
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;
}
Modified: cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp?rev=196642&r1=196641&r2=196642&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp Fri Dec 6 23:09:50 2013
@@ -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
}
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=196642&r1=196641&r2=196642&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 Dec 6 23:09:50 2013
@@ -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 {
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=196642&r1=196641&r2=196642&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 Dec 6 23:09:50 2013
@@ -80,7 +80,7 @@ template<> struct N0::X0<void> { }; // e
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 {
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=196642&r1=196641&r2=196642&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-spec.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-spec.cpp Fri Dec 6 23:09:50 2013
@@ -91,7 +91,7 @@ template<> struct N::B<float> { }; // ex
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> {
More information about the cfe-commits
mailing list