summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-04-17 03:52:20 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-04-17 03:52:20 +0000
commit11a80dcb422ab40e8854a8de0715dce374c107e6 (patch)
tree12efe515c960cc1119ed198959e77f18002b2507 /clang/lib/Sema/SemaTemplate.cpp
parenta56071c5fbe05b6fd8da3388fc60a959a6fc6464 (diff)
downloadbcm5719-llvm-11a80dcb422ab40e8854a8de0715dce374c107e6.tar.gz
bcm5719-llvm-11a80dcb422ab40e8854a8de0715dce374c107e6.zip
PR19340: If we see a declaration of a member of an unspecialized class template
that looks like it might be an explicit specialization, don't recover as an explicit specialization (bypassing the check that would reject that). llvm-svn: 206444
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp85
1 files changed, 46 insertions, 39 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 58742fc055e..2ef144f1587 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1721,6 +1721,38 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// template<> for each enclosing class template that is
// explicitly specialized.
bool SawNonEmptyTemplateParameterList = false;
+
+ auto CheckExplicitSpecialization = [&](SourceRange Range,
+ bool Recovery = false) {
+ if (SawNonEmptyTemplateParameterList) {
+ Diag(DeclLoc, diag::err_specialize_member_of_template)
+ << !Recovery << Range;
+ Invalid = true;
+ IsExplicitSpecialization = false;
+ return true;
+ }
+
+ return false;
+ };
+
+ auto DiagnoseMissingExplicitSpecialization = [&] (SourceRange Range) {
+ // Check that we can have an explicit specialization here.
+ if (CheckExplicitSpecialization(Range, true))
+ return true;
+
+ // We don't have a template header, but we should.
+ SourceLocation ExpectedTemplateLoc;
+ if (!ParamLists.empty())
+ ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
+ else
+ ExpectedTemplateLoc = DeclStartLoc;
+
+ Diag(DeclLoc, diag::err_template_spec_needs_header)
+ << Range
+ << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
+ return false;
+ };
+
unsigned ParamIdx = 0;
for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
++TypeIdx) {
@@ -1791,13 +1823,8 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// are not explicitly specialized as well.
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
- if (SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << ParamLists[ParamIdx]->getSourceRange();
- Invalid = true;
- IsExplicitSpecialization = false;
+ if (CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange()))
return 0;
- }
} else
SawNonEmptyTemplateParameterList = true;
}
@@ -1820,29 +1847,20 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
Invalid = true;
return 0;
}
-
+
// Consume this template header.
++ParamIdx;
continue;
- }
-
- if (!IsFriend) {
- // We don't have a template header, but we should.
- SourceLocation ExpectedTemplateLoc;
- if (!ParamLists.empty())
- ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
- else
- ExpectedTemplateLoc = DeclStartLoc;
-
- // FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
- Diag(DeclLoc, diag::err_template_spec_needs_header)
- << getRangeOfTypeInNestedNameSpecifier(Context, T, SS)
- << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
}
-
+
+ if (!IsFriend)
+ if (DiagnoseMissingExplicitSpecialization(
+ getRangeOfTypeInNestedNameSpecifier(Context, T, SS)))
+ return 0;
+
continue;
}
-
+
if (NeedNonemptyTemplateHeader) {
// In friend declarations we can have template-ids which don't
// depend on the corresponding template parameter lists. But
@@ -1886,18 +1904,11 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// the declaration itself.
if (ParamIdx >= ParamLists.size()) {
if (TemplateId && !IsFriend) {
- // FIXME: Don't recover this way if we SawNonEmptyTemplateParameterList.
// We don't have a template header for the declaration itself, but we
// should.
- SourceLocation ExpectedTemplateLoc;
- if (!ParamLists.empty())
- ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
- else
- ExpectedTemplateLoc = DeclStartLoc;
- Diag(DeclLoc, diag::err_template_spec_needs_header)
- << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)
- << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
IsExplicitSpecialization = true;
+ DiagnoseMissingExplicitSpecialization(SourceRange(TemplateId->LAngleLoc,
+ TemplateId->RAngleLoc));
// Fabricate an empty template parameter list for the invented header.
return TemplateParameterList::Create(Context, SourceLocation(),
@@ -1947,14 +1958,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
- if (ParamLists.back()->size() == 0 && SawNonEmptyTemplateParameterList) {
- Diag(DeclLoc, diag::err_specialize_member_of_template)
- << ParamLists[ParamIdx]->getSourceRange();
- Invalid = true;
- IsExplicitSpecialization = false;
+ if (ParamLists.back()->size() == 0 &&
+ CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange()))
return 0;
- }
-
+
// Return the last template parameter list, which corresponds to the
// entity being declared.
return ParamLists.back();
OpenPOWER on IntegriCloud