Instantiation bug fix extension (cf. r184503) -- minor code fixes, including a typo that caused a runtime assertion after firing diagnosis for class definitions, with the 'template' keyword as template header, in friend declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184634 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index d9370d4..2567e41 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -595,6 +595,9 @@
def err_template_defn_explicit_instantiation : Error<
"%select{function|class}0 cannot be defined in an explicit instantiation; if this "
"declaration is meant to be a %select{function|class}0 definition, remove the 'template' keyword">;
+def err_friend_explicit_instantiation : Error<
+ "friend cannot be declared in an explicit instantiation; if this "
+ "declaration is meant to be a friend declaration, remove the 'template' keyword">;
def err_explicit_instantiation_enum : Error<
"enumerations cannot be explicitly instantiated">;
def err_expected_template_parameter : Error<"expected template parameter">;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 68d8e6b..9ba1314 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1465,7 +1465,6 @@
// This is an explicit specialization or a class template
// partial specialization.
TemplateParameterLists FakedParamLists;
-
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
// This looks like an explicit instantiation, because we have
// something like
@@ -1475,25 +1474,35 @@
// but it actually has a definition. Most likely, this was
// meant to be an explicit specialization, but the user forgot
// the '<>' after 'template'.
- assert(TUK == Sema::TUK_Definition && "Expected a definition here");
+ // It this is friend declaration however, since it cannot have a
+ // template header, it is most likely that the user meant to
+ // remove the 'template' keyword.
+ assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) &&
+ "Expected a definition here");
- SourceLocation LAngleLoc
- = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
- Diag(TemplateId->TemplateNameLoc,
- diag::err_explicit_instantiation_with_definition)
- << SourceRange(TemplateInfo.TemplateLoc)
- << FixItHint::CreateInsertion(LAngleLoc, "<>");
-
- // Create a fake template parameter list that contains only
- // "template<>", so that we treat this construct as a class
- // template specialization.
- FakedParamLists.push_back(
- Actions.ActOnTemplateParameterList(0, SourceLocation(),
- TemplateInfo.TemplateLoc,
- LAngleLoc,
- 0, 0,
- LAngleLoc));
- TemplateParams = &FakedParamLists;
+ if (TUK == Sema::TUK_Friend) {
+ Diag(DS.getFriendSpecLoc(),
+ diag::err_friend_explicit_instantiation);
+ TemplateParams = 0;
+ } else {
+ SourceLocation LAngleLoc
+ = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+ Diag(TemplateId->TemplateNameLoc,
+ diag::err_explicit_instantiation_with_definition)
+ << SourceRange(TemplateInfo.TemplateLoc)
+ << FixItHint::CreateInsertion(LAngleLoc, "<>");
+
+ // Create a fake template parameter list that contains only
+ // "template<>", so that we treat this construct as a class
+ // template specialization.
+ FakedParamLists.push_back(
+ Actions.ActOnTemplateParameterList(0, SourceLocation(),
+ TemplateInfo.TemplateLoc,
+ LAngleLoc,
+ 0, 0,
+ LAngleLoc));
+ TemplateParams = &FakedParamLists;
+ }
}
// Build the class template specialization.
@@ -1546,6 +1555,7 @@
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation)
<< 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
+ TemplateParams = 0;
}
bool IsDependent = false;
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index e8e7efd..973eeb2 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -242,6 +242,8 @@
// If the declarator-id is not a template-id, issue a diagnostic and
// recover by ignoring the 'template' keyword.
Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
+ return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(),
+ &LateParsedAttrs);
} else {
SourceLocation LAngleLoc
= PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
@@ -251,24 +253,21 @@
<< FixItHint::CreateInsertion(LAngleLoc, "<>");
// Recover as if it were an explicit specialization.
- TemplateParameterLists ParamLists;
- SmallVector<Decl*, 4> TemplateParams;
- ParamLists.push_back(
- TemplateParameterList::Create(Actions.getASTContext(),
- TemplateInfo.TemplateLoc,
- LAngleLoc,
- (NamedDecl**)TemplateParams.data(),
- TemplateParams.size(), LAngleLoc));
+ TemplateParameterLists FakedParamLists;
+ FakedParamLists.push_back(
+ Actions.ActOnTemplateParameterList(0, SourceLocation(),
+ TemplateInfo.TemplateLoc,
+ LAngleLoc, 0, 0, LAngleLoc));
return ParseFunctionDefinition(DeclaratorInfo,
- ParsedTemplateInfo(&ParamLists,
+ ParsedTemplateInfo(&FakedParamLists,
/*isSpecialization=*/true,
/*LastParamListWasEmpty=*/true),
&LateParsedAttrs);
}
}
return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
- &LateParsedAttrs);
+ &LateParsedAttrs);
}
// Parse this declaration.