diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-23 12:11:45 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-23 12:11:45 +0000 |
commit | 3ebd75399112dd9ad1c96ee5e7c59df580378cc8 (patch) | |
tree | 529bece3ff5b924840e9e7a55a01b467ff960f2a | |
parent | 3e0c0985a17c3846d05d185962e08819a4b49aa7 (diff) |
Tolerate extraneous "template<>" headers better, downgrading the
complaint to a warning and providing a helpful node in the case where
the "template<>" header is redundant because the corresponding
template-id refers to an explicit specialization. C++0x might still
change this behavior, and existing practice is all over the place on
the number of "template<>" headers actually needed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89651 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 20 | ||||
-rw-r--r-- | test/SemaTemplate/temp_explicit.cpp | 17 |
3 files changed, 38 insertions, 4 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7ca011986b..399cf37cca 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1049,6 +1049,11 @@ def err_template_param_list_matches_nontemplate : Error< def err_template_spec_extra_headers : Error< "extraneous template parameter list in template specialization or " "out-of-line template definition">; +def warn_template_spec_extra_headers : Warning< + "extraneous template parameter list in template specialization">; +def note_explicit_template_spec_does_not_need_header : Note< + "'template<>' header not required for explicitly-specialized class %0 " + "declared here">; def err_template_qualified_declarator_no_match : Error< "nested name specifier '%0' for declaration does not refer into a class, " "class template or class template partial specialization">; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 096289fa35..bfdf17afae 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1048,6 +1048,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // template-ids will match up with the template parameter lists. llvm::SmallVector<const TemplateSpecializationType *, 4> TemplateIdsInSpecifier; + llvm::SmallVector<ClassTemplateSpecializationDecl *, 4> + ExplicitSpecializationsInSpecifier; for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); NNS; NNS = NNS->getPrefix()) { if (const TemplateSpecializationType *SpecType @@ -1061,10 +1063,10 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, = cast<ClassTemplateSpecializationDecl>(Record->getDecl()); // If the nested name specifier refers to an explicit specialization, // we don't need a template<> header. - // FIXME: revisit this approach once we cope with specializations - // properly. - if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) + if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) { + ExplicitSpecializationsInSpecifier.push_back(SpecDecl); continue; + } } TemplateIdsInSpecifier.push_back(SpecType); @@ -1145,10 +1147,20 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // If there were too many template parameter lists, complain about that now. if (Idx != NumParamLists - 1) { while (Idx < NumParamLists - 1) { + bool isExplicitSpecHeader = ParamLists[Idx]->size() == 0; Diag(ParamLists[Idx]->getTemplateLoc(), - diag::err_template_spec_extra_headers) + isExplicitSpecHeader? diag::warn_template_spec_extra_headers + : diag::err_template_spec_extra_headers) << SourceRange(ParamLists[Idx]->getTemplateLoc(), ParamLists[Idx]->getRAngleLoc()); + + if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) { + Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(), + diag::note_explicit_template_spec_does_not_need_header) + << ExplicitSpecializationsInSpecifier.back(); + ExplicitSpecializationsInSpecifier.pop_back(); + } + ++Idx; } } diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp index 9c824d6f41..ae409aff66 100644 --- a/test/SemaTemplate/temp_explicit.cpp +++ b/test/SemaTemplate/temp_explicit.cpp @@ -108,3 +108,20 @@ struct X6 { }; template struct X6::Inner; // expected-error{{non-templated}} + +// PR5559 +template <typename T> +struct Foo; + +template <> +struct Foo<int> // expected-note{{header not required for explicitly-specialized}} +{ + template <typename U> + struct Bar + {}; +}; + +template <> // expected-warning{{extraneous template parameter list}} +template <> +struct Foo<int>::Bar<void> +{}; |