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 /lib/Sema/SemaTemplate.cpp | |
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
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 20 |
1 files changed, 16 insertions, 4 deletions
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; } } |