diff options
Diffstat (limited to 'clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 85 |
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(); } |