aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp85
1 files changed, 60 insertions, 25 deletions
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 9a04bf2..0277dfb 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -711,41 +711,61 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
}
}
- // Provide an ExtWarn if the C++1z feature of using 'typename' here is used.
- // Generate a meaningful error if the user forgot to put class before the
- // identifier, comma, or greater. Provide a fixit if the identifier, comma,
- // or greater appear immediately or after 'struct'. In the latter case,
- // replace the keyword with 'class'.
+ TemplateNameKind Kind = TemplateNameKind::TNK_Non_template;
+ SourceLocation NameLoc;
+ IdentifierInfo *ParamName = nullptr;
+ SourceLocation EllipsisLoc;
bool TypenameKeyword = false;
- if (!TryConsumeToken(tok::kw_class)) {
+
+ if (TryConsumeToken(tok::kw_class)) {
+ Kind = TemplateNameKind::TNK_Type_template;
+ } else {
+
+ // Provide an ExtWarn if the C++1z feature of using 'typename' here is used.
+ // Generate a meaningful error if the user forgot to put class before the
+ // identifier, comma, or greater. Provide a fixit if the identifier, comma,
+ // or greater appear immediately or after 'struct'. In the latter case,
+ // replace the keyword with 'class'.
bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);
const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
if (Tok.is(tok::kw_typename)) {
TypenameKeyword = true;
+ Kind = TemplateNameKind::TNK_Type_template;
Diag(Tok.getLocation(),
getLangOpts().CPlusPlus17
? diag::warn_cxx14_compat_template_template_param_typename
: diag::ext_template_template_param_typename)
- << (!getLangOpts().CPlusPlus17
- ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
- : FixItHint());
+ << (!getLangOpts().CPlusPlus17
+ ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
+ : FixItHint());
+ Kind = TemplateNameKind::TNK_Type_template;
+ } else if (TryConsumeToken(tok::kw_concept)) {
+ Kind = TemplateNameKind::TNK_Concept_template;
+ } else if (TryConsumeToken(tok::kw_auto)) {
+ Kind = TemplateNameKind::TNK_Var_template;
} else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater,
tok::greatergreater, tok::ellipsis)) {
+ // Provide a fixit if the identifier, comma,
+ // or greater appear immediately or after 'struct'. In the latter case,
+ // replace the keyword with 'class'.
Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
<< getLangOpts().CPlusPlus17
<< (Replace
? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint::CreateInsertion(Tok.getLocation(), "class "));
- } else
- Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
- << getLangOpts().CPlusPlus17;
-
+ }
if (Replace)
ConsumeToken();
}
+ if (!getLangOpts().CPlusPlus26 &&
+ (Kind == TemplateNameKind::TNK_Concept_template ||
+ Kind == TemplateNameKind::TNK_Var_template)) {
+ Diag(PrevTokLocation, diag::err_cxx26_template_template_params)
+ << (Kind == TemplateNameKind::TNK_Concept_template);
+ }
+
// Parse the ellipsis, if given.
- SourceLocation EllipsisLoc;
if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
@@ -753,8 +773,7 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
: diag::ext_variadic_templates);
// Get the identifier, if given.
- SourceLocation NameLoc = Tok.getLocation();
- IdentifierInfo *ParamName = nullptr;
+ NameLoc = Tok.getLocation();
if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
ConsumeToken();
@@ -792,7 +811,7 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
}
return Actions.ActOnTemplateTemplateParameter(
- getCurScope(), TemplateLoc, ParamList, TypenameKeyword, EllipsisLoc,
+ getCurScope(), TemplateLoc, Kind, TypenameKeyword, ParamList, EllipsisLoc,
ParamName, NameLoc, Depth, Position, EqualLoc, DefaultArg);
}
@@ -1201,7 +1220,8 @@ static bool isEndOfTemplateArgument(Token Tok) {
ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
- !Tok.is(tok::annot_cxxscope))
+ !Tok.is(tok::annot_cxxscope) && !Tok.is(tok::annot_template_id) &&
+ !Tok.is(tok::annot_non_type))
return ParsedTemplateArgument();
// C++0x [temp.arg.template]p1:
@@ -1245,12 +1265,27 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
/*EnteringContext=*/false, Template))
Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
- } else if (Tok.is(tok::identifier)) {
+ } else if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) ||
+ Tok.is(tok::annot_non_type)) {
// We may have a (non-dependent) template name.
TemplateTy Template;
UnqualifiedId Name;
- Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
- ConsumeToken(); // the identifier
+ if (Tok.is(tok::annot_non_type)) {
+ NamedDecl *ND = getNonTypeAnnotation(Tok);
+ if (!isa<VarTemplateDecl>(ND))
+ return Result;
+ Name.setIdentifier(ND->getIdentifier(), Tok.getLocation());
+ ConsumeAnnotationToken();
+ } else if (Tok.is(tok::annot_template_id)) {
+ TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
+ if (TemplateId->LAngleLoc.isValid())
+ return Result;
+ Name.setIdentifier(TemplateId->Name, Tok.getLocation());
+ ConsumeAnnotationToken();
+ } else {
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+ }
TryConsumeToken(tok::ellipsis, EllipsisLoc);
@@ -1261,7 +1296,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
/*hasTemplateKeyword=*/false, Name,
/*ObjectType=*/nullptr,
/*EnteringContext=*/false, Template, MemberOfUnknownSpecialization);
- if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+ if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template ||
+ TNK == TNK_Var_template || TNK == TNK_Concept_template) {
// We have an id-expression that refers to a class template or
// (C++0x) alias template.
Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
@@ -1301,13 +1337,12 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
{
TentativeParsingAction TPA(*this);
- ParsedTemplateArgument TemplateTemplateArgument
- = ParseTemplateTemplateArgument();
+ ParsedTemplateArgument TemplateTemplateArgument =
+ ParseTemplateTemplateArgument();
if (!TemplateTemplateArgument.isInvalid()) {
TPA.Commit();
return TemplateTemplateArgument;
}
-
// Revert this tentative parse to parse a non-type template argument.
TPA.Revert();
}