1645 lines · cpp
1//===--- ParseTemplate.cpp - Template Parsing -----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements parsing of C++ templates.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/DeclTemplate.h"15#include "clang/AST/ExprCXX.h"16#include "clang/Basic/DiagnosticParse.h"17#include "clang/Parse/Parser.h"18#include "clang/Parse/RAIIObjectsForParser.h"19#include "clang/Sema/DeclSpec.h"20#include "clang/Sema/EnterExpressionEvaluationContext.h"21#include "clang/Sema/ParsedTemplate.h"22#include "clang/Sema/Scope.h"23using namespace clang;24 25unsigned Parser::ReenterTemplateScopes(MultiParseScope &S, Decl *D) {26 return Actions.ActOnReenterTemplateScope(D, [&] {27 S.Enter(Scope::TemplateParamScope);28 return Actions.getCurScope();29 });30}31 32Parser::DeclGroupPtrTy33Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,34 SourceLocation &DeclEnd,35 ParsedAttributes &AccessAttrs) {36 ObjCDeclContextSwitch ObjCDC(*this);37 38 if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {39 return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(),40 DeclEnd, AccessAttrs,41 AccessSpecifier::AS_none);42 }43 return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs,44 AccessSpecifier::AS_none);45}46 47Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(48 DeclaratorContext Context, SourceLocation &DeclEnd,49 ParsedAttributes &AccessAttrs, AccessSpecifier AS) {50 assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&51 "Token does not start a template declaration.");52 53 MultiParseScope TemplateParamScopes(*this);54 55 // Tell the action that names should be checked in the context of56 // the declaration to come.57 ParsingDeclRAIIObject58 ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);59 60 // Parse multiple levels of template headers within this template61 // parameter scope, e.g.,62 //63 // template<typename T>64 // template<typename U>65 // class A<T>::B { ... };66 //67 // We parse multiple levels non-recursively so that we can build a68 // single data structure containing all of the template parameter69 // lists to easily differentiate between the case above and:70 //71 // template<typename T>72 // class A {73 // template<typename U> class B;74 // };75 //76 // In the first case, the action for declaring A<T>::B receives77 // both template parameter lists. In the second case, the action for78 // defining A<T>::B receives just the inner template parameter list79 // (and retrieves the outer template parameter list from its80 // context).81 bool isSpecialization = true;82 bool LastParamListWasEmpty = false;83 TemplateParameterLists ParamLists;84 TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);85 86 do {87 // Consume the 'export', if any.88 SourceLocation ExportLoc;89 TryConsumeToken(tok::kw_export, ExportLoc);90 91 // Consume the 'template', which should be here.92 SourceLocation TemplateLoc;93 if (!TryConsumeToken(tok::kw_template, TemplateLoc)) {94 Diag(Tok.getLocation(), diag::err_expected_template);95 return nullptr;96 }97 98 // Parse the '<' template-parameter-list '>'99 SourceLocation LAngleLoc, RAngleLoc;100 SmallVector<NamedDecl*, 4> TemplateParams;101 if (ParseTemplateParameters(TemplateParamScopes,102 CurTemplateDepthTracker.getDepth(),103 TemplateParams, LAngleLoc, RAngleLoc)) {104 // Skip until the semi-colon or a '}'.105 SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);106 TryConsumeToken(tok::semi);107 return nullptr;108 }109 110 ExprResult OptionalRequiresClauseConstraintER;111 if (!TemplateParams.empty()) {112 isSpecialization = false;113 ++CurTemplateDepthTracker;114 115 if (TryConsumeToken(tok::kw_requires)) {116 OptionalRequiresClauseConstraintER =117 Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(118 /*IsTrailingRequiresClause=*/false));119 if (!OptionalRequiresClauseConstraintER.isUsable()) {120 // Skip until the semi-colon or a '}'.121 SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);122 TryConsumeToken(tok::semi);123 return nullptr;124 }125 }126 } else {127 LastParamListWasEmpty = true;128 }129 130 ParamLists.push_back(Actions.ActOnTemplateParameterList(131 CurTemplateDepthTracker.getDepth(), ExportLoc, TemplateLoc, LAngleLoc,132 TemplateParams, RAngleLoc, OptionalRequiresClauseConstraintER.get()));133 } while (Tok.isOneOf(tok::kw_export, tok::kw_template));134 135 ParsedTemplateInfo TemplateInfo(&ParamLists, isSpecialization,136 LastParamListWasEmpty);137 138 // Parse the actual template declaration.139 if (Tok.is(tok::kw_concept)) {140 Decl *ConceptDecl = ParseConceptDefinition(TemplateInfo, DeclEnd);141 // We need to explicitly pass ConceptDecl to ParsingDeclRAIIObject, so that142 // delayed diagnostics (e.g. warn_deprecated) have a Decl to work with.143 ParsingTemplateParams.complete(ConceptDecl);144 return Actions.ConvertDeclToDeclGroup(ConceptDecl);145 }146 147 return ParseDeclarationAfterTemplate(148 Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);149}150 151Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(152 DeclaratorContext Context, SourceLocation &DeclEnd, AccessSpecifier AS) {153 ParsedAttributes AccessAttrs(AttrFactory);154 return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs,155 AS);156}157 158Parser::DeclGroupPtrTy Parser::ParseDeclarationAfterTemplate(159 DeclaratorContext Context, ParsedTemplateInfo &TemplateInfo,160 ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd,161 ParsedAttributes &AccessAttrs, AccessSpecifier AS) {162 assert(TemplateInfo.Kind != ParsedTemplateKind::NonTemplate &&163 "Template information required");164 165 if (Tok.is(tok::kw_static_assert)) {166 // A static_assert declaration may not be templated.167 Diag(Tok.getLocation(), diag::err_templated_invalid_declaration)168 << TemplateInfo.getSourceRange();169 // Parse the static_assert declaration to improve error recovery.170 return Actions.ConvertDeclToDeclGroup(171 ParseStaticAssertDeclaration(DeclEnd));172 }173 174 // We are parsing a member template.175 if (Context == DeclaratorContext::Member)176 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,177 &DiagsFromTParams);178 179 ParsedAttributes DeclAttrs(AttrFactory);180 ParsedAttributes DeclSpecAttrs(AttrFactory);181 182 // GNU attributes are applied to the declaration specification while the183 // standard attributes are applied to the declaration. We parse the two184 // attribute sets into different containters so we can apply them during185 // the regular parsing process.186 while (MaybeParseCXX11Attributes(DeclAttrs) ||187 MaybeParseGNUAttributes(DeclSpecAttrs))188 ;189 190 if (Tok.is(tok::kw_using))191 return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,192 DeclAttrs);193 194 // Parse the declaration specifiers, stealing any diagnostics from195 // the template parameters.196 ParsingDeclSpec DS(*this, &DiagsFromTParams);197 DS.SetRangeStart(DeclSpecAttrs.Range.getBegin());198 DS.SetRangeEnd(DeclSpecAttrs.Range.getEnd());199 DS.takeAttributesAppendingingFrom(DeclSpecAttrs);200 201 ParseDeclarationSpecifiers(DS, TemplateInfo, AS,202 getDeclSpecContextFromDeclaratorContext(Context));203 204 if (Tok.is(tok::semi)) {205 ProhibitAttributes(DeclAttrs);206 DeclEnd = ConsumeToken();207 RecordDecl *AnonRecord = nullptr;208 Decl *Decl = Actions.ParsedFreeStandingDeclSpec(209 getCurScope(), AS, DS, ParsedAttributesView::none(),210 TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams211 : MultiTemplateParamsArg(),212 TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation,213 AnonRecord);214 Actions.ActOnDefinedDeclarationSpecifier(Decl);215 assert(!AnonRecord &&216 "Anonymous unions/structs should not be valid with template");217 DS.complete(Decl);218 return Actions.ConvertDeclToDeclGroup(Decl);219 }220 221 if (DS.hasTagDefinition())222 Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());223 224 // Move the attributes from the prefix into the DS.225 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation)226 ProhibitAttributes(DeclAttrs);227 228 return ParseDeclGroup(DS, Context, DeclAttrs, TemplateInfo, &DeclEnd);229}230 231Decl *232Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,233 SourceLocation &DeclEnd) {234 assert(TemplateInfo.Kind != ParsedTemplateKind::NonTemplate &&235 "Template information required");236 assert(Tok.is(tok::kw_concept) &&237 "ParseConceptDefinition must be called when at a 'concept' keyword");238 239 ConsumeToken(); // Consume 'concept'240 241 SourceLocation BoolKWLoc;242 if (TryConsumeToken(tok::kw_bool, BoolKWLoc))243 Diag(Tok.getLocation(), diag::err_concept_legacy_bool_keyword) <<244 FixItHint::CreateRemoval(SourceLocation(BoolKWLoc));245 246 DiagnoseAndSkipCXX11Attributes();247 248 CXXScopeSpec SS;249 if (ParseOptionalCXXScopeSpecifier(250 SS, /*ObjectType=*/nullptr,251 /*ObjectHasErrors=*/false, /*EnteringContext=*/false,252 /*MayBePseudoDestructor=*/nullptr,253 /*IsTypename=*/false, /*LastII=*/nullptr, /*OnlyNamespace=*/true) ||254 SS.isInvalid()) {255 SkipUntil(tok::semi);256 return nullptr;257 }258 259 if (SS.isNotEmpty())260 Diag(SS.getBeginLoc(),261 diag::err_concept_definition_not_identifier);262 263 UnqualifiedId Result;264 if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,265 /*ObjectHadErrors=*/false, /*EnteringContext=*/false,266 /*AllowDestructorName=*/false,267 /*AllowConstructorName=*/false,268 /*AllowDeductionGuide=*/false,269 /*TemplateKWLoc=*/nullptr, Result)) {270 SkipUntil(tok::semi);271 return nullptr;272 }273 274 if (Result.getKind() != UnqualifiedIdKind::IK_Identifier) {275 Diag(Result.getBeginLoc(), diag::err_concept_definition_not_identifier);276 SkipUntil(tok::semi);277 return nullptr;278 }279 280 const IdentifierInfo *Id = Result.Identifier;281 SourceLocation IdLoc = Result.getBeginLoc();282 283 // [C++26][basic.scope.pdecl]/p13284 // The locus of a concept-definition is immediately after its concept-name.285 ConceptDecl *D = Actions.ActOnStartConceptDefinition(286 getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc);287 288 ParsedAttributes Attrs(AttrFactory);289 MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);290 291 if (!TryConsumeToken(tok::equal)) {292 Diag(Tok.getLocation(), diag::err_expected) << tok::equal;293 SkipUntil(tok::semi);294 if (D)295 D->setInvalidDecl();296 return nullptr;297 }298 299 ExprResult ConstraintExprResult = ParseConstraintExpression();300 if (ConstraintExprResult.isInvalid()) {301 SkipUntil(tok::semi);302 if (D)303 D->setInvalidDecl();304 return nullptr;305 }306 307 DeclEnd = Tok.getLocation();308 ExpectAndConsumeSemi(diag::err_expected_semi_declaration);309 Expr *ConstraintExpr = ConstraintExprResult.get();310 311 if (!D)312 return nullptr;313 314 return Actions.ActOnFinishConceptDefinition(getCurScope(), D, ConstraintExpr,315 Attrs);316}317 318bool Parser::ParseTemplateParameters(319 MultiParseScope &TemplateScopes, unsigned Depth,320 SmallVectorImpl<NamedDecl *> &TemplateParams, SourceLocation &LAngleLoc,321 SourceLocation &RAngleLoc) {322 // Get the template parameter list.323 if (!TryConsumeToken(tok::less, LAngleLoc)) {324 Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";325 return true;326 }327 328 // Try to parse the template parameter list.329 bool Failed = false;330 // FIXME: Missing greatergreatergreater support.331 if (!Tok.is(tok::greater) && !Tok.is(tok::greatergreater)) {332 TemplateScopes.Enter(Scope::TemplateParamScope);333 Failed = ParseTemplateParameterList(Depth, TemplateParams);334 }335 336 if (Tok.is(tok::greatergreater)) {337 // No diagnostic required here: a template-parameter-list can only be338 // followed by a declaration or, for a template template parameter, the339 // 'class' keyword. Therefore, the second '>' will be diagnosed later.340 // This matters for elegant diagnosis of:341 // template<template<typename>> struct S;342 Tok.setKind(tok::greater);343 RAngleLoc = Tok.getLocation();344 Tok.setLocation(Tok.getLocation().getLocWithOffset(1));345 } else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) {346 Diag(Tok.getLocation(), diag::err_expected) << tok::greater;347 return true;348 }349 return false;350}351 352bool353Parser::ParseTemplateParameterList(const unsigned Depth,354 SmallVectorImpl<NamedDecl*> &TemplateParams) {355 while (true) {356 357 if (NamedDecl *TmpParam358 = ParseTemplateParameter(Depth, TemplateParams.size())) {359 TemplateParams.push_back(TmpParam);360 } else {361 // If we failed to parse a template parameter, skip until we find362 // a comma or closing brace.363 SkipUntil(tok::comma, tok::greater, tok::greatergreater,364 StopAtSemi | StopBeforeMatch);365 }366 367 // Did we find a comma or the end of the template parameter list?368 if (Tok.is(tok::comma)) {369 ConsumeToken();370 } else if (Tok.isOneOf(tok::greater, tok::greatergreater)) {371 // Don't consume this... that's done by template parser.372 break;373 } else {374 // Somebody probably forgot to close the template. Skip ahead and375 // try to get out of the expression. This error is currently376 // subsumed by whatever goes on in ParseTemplateParameter.377 Diag(Tok.getLocation(), diag::err_expected_comma_greater);378 SkipUntil(tok::comma, tok::greater, tok::greatergreater,379 StopAtSemi | StopBeforeMatch);380 return false;381 }382 }383 return true;384}385 386Parser::TPResult Parser::isStartOfTemplateTypeParameter() {387 if (Tok.is(tok::kw_class)) {388 // "class" may be the start of an elaborated-type-specifier or a389 // type-parameter. Per C++ [temp.param]p3, we prefer the type-parameter.390 switch (NextToken().getKind()) {391 case tok::equal:392 case tok::comma:393 case tok::greater:394 case tok::greatergreater:395 case tok::ellipsis:396 return TPResult::True;397 398 case tok::identifier:399 // This may be either a type-parameter or an elaborated-type-specifier.400 // We have to look further.401 break;402 403 default:404 return TPResult::False;405 }406 407 switch (GetLookAheadToken(2).getKind()) {408 case tok::equal:409 case tok::comma:410 case tok::greater:411 case tok::greatergreater:412 return TPResult::True;413 414 default:415 return TPResult::False;416 }417 }418 419 if (TryAnnotateTypeConstraint())420 return TPResult::Error;421 422 if (isTypeConstraintAnnotation() &&423 // Next token might be 'auto' or 'decltype', indicating that this424 // type-constraint is in fact part of a placeholder-type-specifier of a425 // non-type template parameter.426 !GetLookAheadToken(Tok.is(tok::annot_cxxscope) ? 2 : 1)427 .isOneOf(tok::kw_auto, tok::kw_decltype))428 return TPResult::True;429 430 // 'typedef' is a reasonably-common typo/thinko for 'typename', and is431 // ill-formed otherwise.432 if (Tok.isNot(tok::kw_typename) && Tok.isNot(tok::kw_typedef))433 return TPResult::False;434 435 // C++ [temp.param]p2:436 // There is no semantic difference between class and typename in a437 // template-parameter. typename followed by an unqualified-id438 // names a template type parameter. typename followed by a439 // qualified-id denotes the type in a non-type440 // parameter-declaration.441 Token Next = NextToken();442 443 // If we have an identifier, skip over it.444 if (Next.getKind() == tok::identifier)445 Next = GetLookAheadToken(2);446 447 switch (Next.getKind()) {448 case tok::equal:449 case tok::comma:450 case tok::greater:451 case tok::greatergreater:452 case tok::ellipsis:453 return TPResult::True;454 455 case tok::kw_typename:456 case tok::kw_typedef:457 case tok::kw_class:458 // These indicate that a comma was missed after a type parameter, not that459 // we have found a non-type parameter.460 return TPResult::True;461 462 default:463 return TPResult::False;464 }465}466 467NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {468 469 switch (isStartOfTemplateTypeParameter()) {470 case TPResult::True:471 // Is there just a typo in the input code? ('typedef' instead of472 // 'typename')473 if (Tok.is(tok::kw_typedef)) {474 Diag(Tok.getLocation(), diag::err_expected_template_parameter);475 476 Diag(Tok.getLocation(), diag::note_meant_to_use_typename)477 << FixItHint::CreateReplacement(CharSourceRange::getCharRange(478 Tok.getLocation(),479 Tok.getEndLoc()),480 "typename");481 482 Tok.setKind(tok::kw_typename);483 }484 485 return ParseTypeParameter(Depth, Position);486 case TPResult::False:487 break;488 489 case TPResult::Error: {490 // We return an invalid parameter as opposed to null to avoid having bogus491 // diagnostics about an empty template parameter list.492 // FIXME: Fix ParseTemplateParameterList to better handle nullptr results493 // from here.494 // Return a NTTP as if there was an error in a scope specifier, the user495 // probably meant to write the type of a NTTP.496 DeclSpec DS(getAttrFactory());497 DS.SetTypeSpecError();498 Declarator D(DS, ParsedAttributesView::none(),499 DeclaratorContext::TemplateParam);500 D.SetIdentifier(nullptr, Tok.getLocation());501 D.setInvalidType(true);502 NamedDecl *ErrorParam = Actions.ActOnNonTypeTemplateParameter(503 getCurScope(), D, Depth, Position, /*EqualLoc=*/SourceLocation(),504 /*DefaultArg=*/nullptr);505 ErrorParam->setInvalidDecl(true);506 SkipUntil(tok::comma, tok::greater, tok::greatergreater,507 StopAtSemi | StopBeforeMatch);508 return ErrorParam;509 }510 511 case TPResult::Ambiguous:512 llvm_unreachable("template param classification can't be ambiguous");513 }514 515 if (Tok.is(tok::kw_template))516 return ParseTemplateTemplateParameter(Depth, Position);517 518 // If it's none of the above, then it must be a parameter declaration.519 // NOTE: This will pick up errors in the closure of the template parameter520 // list (e.g., template < ; Check here to implement >> style closures.521 return ParseNonTypeTemplateParameter(Depth, Position);522}523 524bool Parser::isTypeConstraintAnnotation() {525 const Token &T = Tok.is(tok::annot_cxxscope) ? NextToken() : Tok;526 if (T.isNot(tok::annot_template_id))527 return false;528 const auto *ExistingAnnot =529 static_cast<TemplateIdAnnotation *>(T.getAnnotationValue());530 return ExistingAnnot->Kind == TNK_Concept_template;531}532 533bool Parser::TryAnnotateTypeConstraint() {534 if (!getLangOpts().CPlusPlus20)535 return false;536 // The type constraint may declare template parameters, notably537 // if it contains a generic lambda, so we need to increment538 // the template depth as these parameters would not be instantiated539 // at the current depth.540 TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);541 ++CurTemplateDepthTracker;542 CXXScopeSpec SS;543 bool WasScopeAnnotation = Tok.is(tok::annot_cxxscope);544 if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,545 /*ObjectHasErrors=*/false,546 /*EnteringContext=*/false,547 /*MayBePseudoDestructor=*/nullptr,548 // If this is not a type-constraint, then549 // this scope-spec is part of the typename550 // of a non-type template parameter551 /*IsTypename=*/true, /*LastII=*/nullptr,552 // We won't find concepts in553 // non-namespaces anyway, so might as well554 // parse this correctly for possible type555 // names.556 /*OnlyNamespace=*/false))557 return true;558 559 if (Tok.is(tok::identifier)) {560 UnqualifiedId PossibleConceptName;561 PossibleConceptName.setIdentifier(Tok.getIdentifierInfo(),562 Tok.getLocation());563 564 TemplateTy PossibleConcept;565 bool MemberOfUnknownSpecialization = false;566 auto TNK = Actions.isTemplateName(getCurScope(), SS,567 /*hasTemplateKeyword=*/false,568 PossibleConceptName,569 /*ObjectType=*/ParsedType(),570 /*EnteringContext=*/false,571 PossibleConcept,572 MemberOfUnknownSpecialization,573 /*Disambiguation=*/true);574 if (MemberOfUnknownSpecialization || !PossibleConcept ||575 TNK != TNK_Concept_template) {576 if (SS.isNotEmpty())577 AnnotateScopeToken(SS, !WasScopeAnnotation);578 return false;579 }580 581 // At this point we're sure we're dealing with a constrained parameter. It582 // may or may not have a template parameter list following the concept583 // name.584 if (AnnotateTemplateIdToken(PossibleConcept, TNK, SS,585 /*TemplateKWLoc=*/SourceLocation(),586 PossibleConceptName,587 /*AllowTypeAnnotation=*/false,588 /*TypeConstraint=*/true))589 return true;590 }591 592 if (SS.isNotEmpty())593 AnnotateScopeToken(SS, !WasScopeAnnotation);594 return false;595}596 597NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {598 assert((Tok.isOneOf(tok::kw_class, tok::kw_typename) ||599 isTypeConstraintAnnotation()) &&600 "A type-parameter starts with 'class', 'typename' or a "601 "type-constraint");602 603 CXXScopeSpec TypeConstraintSS;604 TemplateIdAnnotation *TypeConstraint = nullptr;605 bool TypenameKeyword = false;606 SourceLocation KeyLoc;607 ParseOptionalCXXScopeSpecifier(TypeConstraintSS, /*ObjectType=*/nullptr,608 /*ObjectHasErrors=*/false,609 /*EnteringContext*/ false);610 if (Tok.is(tok::annot_template_id)) {611 // Consume the 'type-constraint'.612 TypeConstraint =613 static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());614 assert(TypeConstraint->Kind == TNK_Concept_template &&615 "stray non-concept template-id annotation");616 KeyLoc = ConsumeAnnotationToken();617 } else {618 assert(TypeConstraintSS.isEmpty() &&619 "expected type constraint after scope specifier");620 621 // Consume the 'class' or 'typename' keyword.622 TypenameKeyword = Tok.is(tok::kw_typename);623 KeyLoc = ConsumeToken();624 }625 626 // Grab the ellipsis (if given).627 SourceLocation EllipsisLoc;628 if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {629 Diag(EllipsisLoc,630 getLangOpts().CPlusPlus11631 ? diag::warn_cxx98_compat_variadic_templates632 : diag::ext_variadic_templates);633 }634 635 // Grab the template parameter name (if given)636 SourceLocation NameLoc = Tok.getLocation();637 IdentifierInfo *ParamName = nullptr;638 if (Tok.is(tok::identifier)) {639 ParamName = Tok.getIdentifierInfo();640 ConsumeToken();641 } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,642 tok::greatergreater)) {643 // Unnamed template parameter. Don't have to do anything here, just644 // don't consume this token.645 } else {646 Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;647 return nullptr;648 }649 650 // Recover from misplaced ellipsis.651 bool AlreadyHasEllipsis = EllipsisLoc.isValid();652 if (TryConsumeToken(tok::ellipsis, EllipsisLoc))653 DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true);654 655 // Grab a default argument (if available).656 // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before657 // we introduce the type parameter into the local scope.658 SourceLocation EqualLoc;659 ParsedType DefaultArg;660 std::optional<DelayTemplateIdDestructionRAII> DontDestructTemplateIds;661 if (TryConsumeToken(tok::equal, EqualLoc)) {662 // The default argument might contain a lambda declaration; avoid destroying663 // parsed template ids at the end of that declaration because they can be664 // used in a type constraint later.665 DontDestructTemplateIds.emplace(*this, /*DelayTemplateIdDestruction=*/true);666 // The default argument may declare template parameters, notably667 // if it contains a generic lambda, so we need to increase668 // the template depth as these parameters would not be instantiated669 // at the current level.670 TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);671 ++CurTemplateDepthTracker;672 DefaultArg =673 ParseTypeName(/*Range=*/nullptr, DeclaratorContext::TemplateTypeArg)674 .get();675 }676 677 NamedDecl *NewDecl = Actions.ActOnTypeParameter(getCurScope(),678 TypenameKeyword, EllipsisLoc,679 KeyLoc, ParamName, NameLoc,680 Depth, Position, EqualLoc,681 DefaultArg,682 TypeConstraint != nullptr);683 684 if (TypeConstraint) {685 Actions.ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,686 cast<TemplateTypeParmDecl>(NewDecl),687 EllipsisLoc);688 }689 690 return NewDecl;691}692 693NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,694 unsigned Position) {695 assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");696 697 // Handle the template <...> part.698 SourceLocation TemplateLoc = ConsumeToken();699 SmallVector<NamedDecl*,8> TemplateParams;700 SourceLocation LAngleLoc, RAngleLoc;701 ExprResult OptionalRequiresClauseConstraintER;702 {703 MultiParseScope TemplateParmScope(*this);704 if (ParseTemplateParameters(TemplateParmScope, Depth + 1, TemplateParams,705 LAngleLoc, RAngleLoc)) {706 return nullptr;707 }708 if (TryConsumeToken(tok::kw_requires)) {709 OptionalRequiresClauseConstraintER =710 Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(711 /*IsTrailingRequiresClause=*/false));712 if (!OptionalRequiresClauseConstraintER.isUsable()) {713 SkipUntil(tok::comma, tok::greater, tok::greatergreater,714 StopAtSemi | StopBeforeMatch);715 return nullptr;716 }717 }718 }719 720 TemplateNameKind Kind = TemplateNameKind::TNK_Non_template;721 SourceLocation NameLoc;722 IdentifierInfo *ParamName = nullptr;723 SourceLocation EllipsisLoc;724 bool TypenameKeyword = false;725 726 if (TryConsumeToken(tok::kw_class)) {727 Kind = TemplateNameKind::TNK_Type_template;728 } else {729 730 // Provide an ExtWarn if the C++1z feature of using 'typename' here is used.731 // Generate a meaningful error if the user forgot to put class before the732 // identifier, comma, or greater. Provide a fixit if the identifier, comma,733 // or greater appear immediately or after 'struct'. In the latter case,734 // replace the keyword with 'class'.735 bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);736 const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;737 if (Tok.is(tok::kw_typename)) {738 TypenameKeyword = true;739 Kind = TemplateNameKind::TNK_Type_template;740 Diag(Tok.getLocation(),741 getLangOpts().CPlusPlus17742 ? diag::warn_cxx14_compat_template_template_param_typename743 : diag::ext_template_template_param_typename)744 << (!getLangOpts().CPlusPlus17745 ? FixItHint::CreateReplacement(Tok.getLocation(), "class")746 : FixItHint());747 Kind = TemplateNameKind::TNK_Type_template;748 } else if (TryConsumeToken(tok::kw_concept)) {749 Kind = TemplateNameKind::TNK_Concept_template;750 } else if (TryConsumeToken(tok::kw_auto)) {751 Kind = TemplateNameKind::TNK_Var_template;752 } else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater,753 tok::greatergreater, tok::ellipsis)) {754 // Provide a fixit if the identifier, comma,755 // or greater appear immediately or after 'struct'. In the latter case,756 // replace the keyword with 'class'.757 Diag(Tok.getLocation(), diag::err_class_on_template_template_param)758 << getLangOpts().CPlusPlus17759 << (Replace760 ? FixItHint::CreateReplacement(Tok.getLocation(), "class")761 : FixItHint::CreateInsertion(Tok.getLocation(), "class "));762 }763 if (Replace)764 ConsumeToken();765 }766 767 if (!getLangOpts().CPlusPlus26 &&768 (Kind == TemplateNameKind::TNK_Concept_template ||769 Kind == TemplateNameKind::TNK_Var_template)) {770 Diag(PrevTokLocation, diag::err_cxx26_template_template_params)771 << (Kind == TemplateNameKind::TNK_Concept_template);772 }773 774 // Parse the ellipsis, if given.775 if (TryConsumeToken(tok::ellipsis, EllipsisLoc))776 Diag(EllipsisLoc,777 getLangOpts().CPlusPlus11778 ? diag::warn_cxx98_compat_variadic_templates779 : diag::ext_variadic_templates);780 781 // Get the identifier, if given.782 NameLoc = Tok.getLocation();783 if (Tok.is(tok::identifier)) {784 ParamName = Tok.getIdentifierInfo();785 ConsumeToken();786 } else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,787 tok::greatergreater)) {788 // Unnamed template parameter. Don't have to do anything here, just789 // don't consume this token.790 } else {791 Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;792 return nullptr;793 }794 795 // Recover from misplaced ellipsis.796 bool AlreadyHasEllipsis = EllipsisLoc.isValid();797 if (TryConsumeToken(tok::ellipsis, EllipsisLoc))798 DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true);799 800 TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(801 Depth, SourceLocation(), TemplateLoc, LAngleLoc, TemplateParams,802 RAngleLoc, OptionalRequiresClauseConstraintER.get());803 804 // Grab a default argument (if available).805 // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before806 // we introduce the template parameter into the local scope.807 SourceLocation EqualLoc;808 ParsedTemplateArgument DefaultArg;809 if (TryConsumeToken(tok::equal, EqualLoc)) {810 DefaultArg = ParseTemplateTemplateArgument();811 if (DefaultArg.isInvalid()) {812 Diag(Tok.getLocation(),813 diag::err_default_template_template_parameter_not_template);814 SkipUntil(tok::comma, tok::greater, tok::greatergreater,815 StopAtSemi | StopBeforeMatch);816 }817 }818 819 return Actions.ActOnTemplateTemplateParameter(820 getCurScope(), TemplateLoc, Kind, TypenameKeyword, ParamList, EllipsisLoc,821 ParamName, NameLoc, Depth, Position, EqualLoc, DefaultArg);822}823 824NamedDecl *825Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {826 // Parse the declaration-specifiers (i.e., the type).827 // FIXME: The type should probably be restricted in some way... Not all828 // declarators (parts of declarators?) are accepted for parameters.829 DeclSpec DS(AttrFactory);830 ParsedTemplateInfo TemplateInfo;831 ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none,832 DeclSpecContext::DSC_template_param);833 834 // Parse this as a typename.835 Declarator ParamDecl(DS, ParsedAttributesView::none(),836 DeclaratorContext::TemplateParam);837 ParseDeclarator(ParamDecl);838 if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {839 Diag(Tok.getLocation(), diag::err_expected_template_parameter);840 return nullptr;841 }842 843 // Recover from misplaced ellipsis.844 SourceLocation EllipsisLoc;845 if (TryConsumeToken(tok::ellipsis, EllipsisLoc))846 DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, ParamDecl);847 848 // If there is a default value, parse it.849 // Per C++0x [basic.scope.pdecl]p9, we parse the default argument before850 // we introduce the template parameter into the local scope.851 SourceLocation EqualLoc;852 ExprResult DefaultArg;853 if (TryConsumeToken(tok::equal, EqualLoc)) {854 if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {855 Diag(Tok.getLocation(), diag::err_stmt_expr_in_default_arg) << 1;856 SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);857 } else {858 // C++ [temp.param]p15:859 // When parsing a default template-argument for a non-type860 // template-parameter, the first non-nested > is taken as the861 // end of the template-parameter-list rather than a greater-than862 // operator.863 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);864 865 // The default argument may declare template parameters, notably866 // if it contains a generic lambda, so we need to increase867 // the template depth as these parameters would not be instantiated868 // at the current level.869 TemplateParameterDepthRAII CurTemplateDepthTracker(870 TemplateParameterDepth);871 ++CurTemplateDepthTracker;872 EnterExpressionEvaluationContext ConstantEvaluated(873 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);874 DefaultArg = Actions.ActOnConstantExpression(ParseInitializer());875 if (DefaultArg.isInvalid())876 SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);877 }878 }879 880 // Create the parameter.881 return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,882 Depth, Position, EqualLoc,883 DefaultArg.get());884}885 886void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,887 SourceLocation CorrectLoc,888 bool AlreadyHasEllipsis,889 bool IdentifierHasName) {890 FixItHint Insertion;891 if (!AlreadyHasEllipsis)892 Insertion = FixItHint::CreateInsertion(CorrectLoc, "...");893 Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration)894 << FixItHint::CreateRemoval(EllipsisLoc) << Insertion895 << !IdentifierHasName;896}897 898void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,899 Declarator &D) {900 assert(EllipsisLoc.isValid());901 bool AlreadyHasEllipsis = D.getEllipsisLoc().isValid();902 if (!AlreadyHasEllipsis)903 D.setEllipsisLoc(EllipsisLoc);904 DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(),905 AlreadyHasEllipsis, D.hasName());906}907 908bool Parser::ParseGreaterThanInTemplateList(SourceLocation LAngleLoc,909 SourceLocation &RAngleLoc,910 bool ConsumeLastToken,911 bool ObjCGenericList) {912 // What will be left once we've consumed the '>'.913 tok::TokenKind RemainingToken;914 const char *ReplacementStr = "> >";915 bool MergeWithNextToken = false;916 917 switch (Tok.getKind()) {918 default:919 Diag(getEndOfPreviousToken(), diag::err_expected) << tok::greater;920 Diag(LAngleLoc, diag::note_matching) << tok::less;921 return true;922 923 case tok::greater:924 // Determine the location of the '>' token. Only consume this token925 // if the caller asked us to.926 RAngleLoc = Tok.getLocation();927 if (ConsumeLastToken)928 ConsumeToken();929 return false;930 931 case tok::greatergreater:932 RemainingToken = tok::greater;933 break;934 935 case tok::greatergreatergreater:936 RemainingToken = tok::greatergreater;937 break;938 939 case tok::greaterequal:940 RemainingToken = tok::equal;941 ReplacementStr = "> =";942 943 // Join two adjacent '=' tokens into one, for cases like:944 // void (*p)() = f<int>;945 // return f<int>==p;946 if (NextToken().is(tok::equal) &&947 areTokensAdjacent(Tok, NextToken())) {948 RemainingToken = tok::equalequal;949 MergeWithNextToken = true;950 }951 break;952 953 case tok::greatergreaterequal:954 RemainingToken = tok::greaterequal;955 break;956 }957 958 // This template-id is terminated by a token that starts with a '>'.959 // Outside C++11 and Objective-C, this is now error recovery.960 //961 // C++11 allows this when the token is '>>', and in CUDA + C++11 mode, we962 // extend that treatment to also apply to the '>>>' token.963 //964 // Objective-C allows this in its type parameter / argument lists.965 966 SourceLocation TokBeforeGreaterLoc = PrevTokLocation;967 SourceLocation TokLoc = Tok.getLocation();968 Token Next = NextToken();969 970 // Whether splitting the current token after the '>' would undesirably result971 // in the remaining token pasting with the token after it. This excludes the972 // MergeWithNextToken cases, which we've already handled.973 bool PreventMergeWithNextToken =974 (RemainingToken == tok::greater ||975 RemainingToken == tok::greatergreater) &&976 (Next.isOneOf(tok::greater, tok::greatergreater,977 tok::greatergreatergreater, tok::equal, tok::greaterequal,978 tok::greatergreaterequal, tok::equalequal)) &&979 areTokensAdjacent(Tok, Next);980 981 // Diagnose this situation as appropriate.982 if (!ObjCGenericList) {983 // The source range of the replaced token(s).984 CharSourceRange ReplacementRange = CharSourceRange::getCharRange(985 TokLoc, Lexer::AdvanceToTokenCharacter(TokLoc, 2, PP.getSourceManager(),986 getLangOpts()));987 988 // A hint to put a space between the '>>'s. In order to make the hint as989 // clear as possible, we include the characters either side of the space in990 // the replacement, rather than just inserting a space at SecondCharLoc.991 FixItHint Hint1 = FixItHint::CreateReplacement(ReplacementRange,992 ReplacementStr);993 994 // A hint to put another space after the token, if it would otherwise be995 // lexed differently.996 FixItHint Hint2;997 if (PreventMergeWithNextToken)998 Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");999 1000 unsigned DiagId = diag::err_two_right_angle_brackets_need_space;1001 if (getLangOpts().CPlusPlus11 &&1002 (Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))1003 DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;1004 else if (Tok.is(tok::greaterequal))1005 DiagId = diag::err_right_angle_bracket_equal_needs_space;1006 Diag(TokLoc, DiagId) << Hint1 << Hint2;1007 }1008 1009 // Find the "length" of the resulting '>' token. This is not always 1, as it1010 // can contain escaped newlines.1011 unsigned GreaterLength = Lexer::getTokenPrefixLength(1012 TokLoc, 1, PP.getSourceManager(), getLangOpts());1013 1014 // Annotate the source buffer to indicate that we split the token after the1015 // '>'. This allows us to properly find the end of, and extract the spelling1016 // of, the '>' token later.1017 RAngleLoc = PP.SplitToken(TokLoc, GreaterLength);1018 1019 // Strip the initial '>' from the token.1020 bool CachingTokens = PP.IsPreviousCachedToken(Tok);1021 1022 Token Greater = Tok;1023 Greater.setLocation(RAngleLoc);1024 Greater.setKind(tok::greater);1025 Greater.setLength(GreaterLength);1026 1027 unsigned OldLength = Tok.getLength();1028 if (MergeWithNextToken) {1029 ConsumeToken();1030 OldLength += Tok.getLength();1031 }1032 1033 Tok.setKind(RemainingToken);1034 Tok.setLength(OldLength - GreaterLength);1035 1036 // Split the second token if lexing it normally would lex a different token1037 // (eg, the fifth token in 'A<B>>>' should re-lex as '>', not '>>').1038 SourceLocation AfterGreaterLoc = TokLoc.getLocWithOffset(GreaterLength);1039 if (PreventMergeWithNextToken)1040 AfterGreaterLoc = PP.SplitToken(AfterGreaterLoc, Tok.getLength());1041 Tok.setLocation(AfterGreaterLoc);1042 1043 // Update the token cache to match what we just did if necessary.1044 if (CachingTokens) {1045 // If the previous cached token is being merged, delete it.1046 if (MergeWithNextToken)1047 PP.ReplacePreviousCachedToken({});1048 1049 if (ConsumeLastToken)1050 PP.ReplacePreviousCachedToken({Greater, Tok});1051 else1052 PP.ReplacePreviousCachedToken({Greater});1053 }1054 1055 if (ConsumeLastToken) {1056 PrevTokLocation = RAngleLoc;1057 } else {1058 PrevTokLocation = TokBeforeGreaterLoc;1059 PP.EnterToken(Tok, /*IsReinject=*/true);1060 Tok = Greater;1061 }1062 1063 return false;1064}1065 1066bool Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,1067 SourceLocation &LAngleLoc,1068 TemplateArgList &TemplateArgs,1069 SourceLocation &RAngleLoc,1070 TemplateTy Template) {1071 assert(Tok.is(tok::less) && "Must have already parsed the template-name");1072 1073 // Consume the '<'.1074 LAngleLoc = ConsumeToken();1075 1076 // Parse the optional template-argument-list.1077 bool Invalid = false;1078 {1079 GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);1080 if (!Tok.isOneOf(tok::greater, tok::greatergreater,1081 tok::greatergreatergreater, tok::greaterequal,1082 tok::greatergreaterequal))1083 Invalid = ParseTemplateArgumentList(TemplateArgs, Template, LAngleLoc);1084 1085 if (Invalid) {1086 // Try to find the closing '>'.1087 if (getLangOpts().CPlusPlus11)1088 SkipUntil(tok::greater, tok::greatergreater,1089 tok::greatergreatergreater, StopAtSemi | StopBeforeMatch);1090 else1091 SkipUntil(tok::greater, StopAtSemi | StopBeforeMatch);1092 }1093 }1094 1095 return ParseGreaterThanInTemplateList(LAngleLoc, RAngleLoc, ConsumeLastToken,1096 /*ObjCGenericList=*/false) ||1097 Invalid;1098}1099 1100bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,1101 CXXScopeSpec &SS,1102 SourceLocation TemplateKWLoc,1103 UnqualifiedId &TemplateName,1104 bool AllowTypeAnnotation,1105 bool TypeConstraint) {1106 assert(getLangOpts().CPlusPlus && "Can only annotate template-ids in C++");1107 assert((Tok.is(tok::less) || TypeConstraint) &&1108 "Parser isn't at the beginning of a template-id");1109 assert(!(TypeConstraint && AllowTypeAnnotation) && "type-constraint can't be "1110 "a type annotation");1111 assert((!TypeConstraint || TNK == TNK_Concept_template) && "type-constraint "1112 "must accompany a concept name");1113 assert((Template || TNK == TNK_Non_template) && "missing template name");1114 1115 // Consume the template-name.1116 SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();1117 1118 // Parse the enclosed template argument list.1119 SourceLocation LAngleLoc, RAngleLoc;1120 TemplateArgList TemplateArgs;1121 bool ArgsInvalid = false;1122 if (!TypeConstraint || Tok.is(tok::less)) {1123 ArgsInvalid = ParseTemplateIdAfterTemplateName(1124 false, LAngleLoc, TemplateArgs, RAngleLoc, Template);1125 // If we couldn't recover from invalid arguments, don't form an annotation1126 // token -- we don't know how much to annotate.1127 // FIXME: This can lead to duplicate diagnostics if we retry parsing this1128 // template-id in another context. Try to annotate anyway?1129 if (RAngleLoc.isInvalid())1130 return true;1131 }1132 1133 ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs);1134 1135 // Build the annotation token.1136 if (TNK == TNK_Type_template && AllowTypeAnnotation) {1137 TypeResult Type =1138 ArgsInvalid1139 ? TypeError()1140 : Actions.ActOnTemplateIdType(1141 getCurScope(), ElaboratedTypeKeyword::None,1142 /*ElaboratedKeywordLoc=*/SourceLocation(), SS, TemplateKWLoc,1143 Template, TemplateName.Identifier, TemplateNameLoc, LAngleLoc,1144 TemplateArgsPtr, RAngleLoc);1145 1146 Tok.setKind(tok::annot_typename);1147 setTypeAnnotation(Tok, Type);1148 if (SS.isNotEmpty())1149 Tok.setLocation(SS.getBeginLoc());1150 else if (TemplateKWLoc.isValid())1151 Tok.setLocation(TemplateKWLoc);1152 else1153 Tok.setLocation(TemplateNameLoc);1154 } else {1155 // Build a template-id annotation token that can be processed1156 // later.1157 Tok.setKind(tok::annot_template_id);1158 1159 const IdentifierInfo *TemplateII =1160 TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier1161 ? TemplateName.Identifier1162 : nullptr;1163 1164 OverloadedOperatorKind OpKind =1165 TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier1166 ? OO_None1167 : TemplateName.OperatorFunctionId.Operator;1168 1169 TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(1170 TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,1171 LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid, TemplateIds);1172 1173 Tok.setAnnotationValue(TemplateId);1174 if (TemplateKWLoc.isValid())1175 Tok.setLocation(TemplateKWLoc);1176 else1177 Tok.setLocation(TemplateNameLoc);1178 }1179 1180 // Common fields for the annotation token1181 Tok.setAnnotationEndLoc(RAngleLoc);1182 1183 // In case the tokens were cached, have Preprocessor replace them with the1184 // annotation token.1185 PP.AnnotateCachedTokens(Tok);1186 return false;1187}1188 1189void Parser::AnnotateTemplateIdTokenAsType(1190 CXXScopeSpec &SS, ImplicitTypenameContext AllowImplicitTypename,1191 bool IsClassName) {1192 assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");1193 1194 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1195 assert(TemplateId->mightBeType() &&1196 "Only works for type and dependent templates");1197 1198 ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),1199 TemplateId->NumArgs);1200 1201 TypeResult Type =1202 TemplateId->isInvalid()1203 ? TypeError()1204 : Actions.ActOnTemplateIdType(1205 getCurScope(), ElaboratedTypeKeyword::None,1206 /*ElaboratedKeywordLoc=*/SourceLocation(), SS,1207 TemplateId->TemplateKWLoc, TemplateId->Template,1208 TemplateId->Name, TemplateId->TemplateNameLoc,1209 TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc,1210 /*IsCtorOrDtorName=*/false, IsClassName, AllowImplicitTypename);1211 // Create the new "type" annotation token.1212 Tok.setKind(tok::annot_typename);1213 setTypeAnnotation(Tok, Type);1214 if (SS.isNotEmpty()) // it was a C++ qualified type name.1215 Tok.setLocation(SS.getBeginLoc());1216 // End location stays the same1217 1218 // Replace the template-id annotation token, and possible the scope-specifier1219 // that precedes it, with the typename annotation token.1220 PP.AnnotateCachedTokens(Tok);1221}1222 1223/// Determine whether the given token can end a template argument.1224static bool isEndOfTemplateArgument(Token Tok) {1225 // FIXME: Handle '>>>'.1226 return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater,1227 tok::greatergreatergreater);1228}1229 1230ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {1231 if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&1232 !Tok.is(tok::annot_cxxscope) && !Tok.is(tok::annot_template_id) &&1233 !Tok.is(tok::annot_non_type))1234 return ParsedTemplateArgument();1235 1236 // C++0x [temp.arg.template]p1:1237 // A template-argument for a template template-parameter shall be the name1238 // of a class template or an alias template, expressed as id-expression.1239 //1240 // We parse an id-expression that refers to a class template or alias1241 // template. The grammar we parse is:1242 //1243 // nested-name-specifier[opt] template[opt] identifier ...[opt]1244 //1245 // followed by a token that terminates a template argument, such as ',',1246 // '>', or (in some cases) '>>'.1247 CXXScopeSpec SS; // nested-name-specifier, if present1248 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,1249 /*ObjectHasErrors=*/false,1250 /*EnteringContext=*/false);1251 1252 ParsedTemplateArgument Result;1253 SourceLocation EllipsisLoc;1254 if (SS.isSet() && Tok.is(tok::kw_template)) {1255 // Parse the optional 'template' keyword following the1256 // nested-name-specifier.1257 SourceLocation TemplateKWLoc = ConsumeToken();1258 1259 if (Tok.is(tok::identifier)) {1260 // We appear to have a dependent template name.1261 UnqualifiedId Name;1262 Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());1263 ConsumeToken(); // the identifier1264 1265 TryConsumeToken(tok::ellipsis, EllipsisLoc);1266 1267 // If the next token signals the end of a template argument, then we have1268 // a (possibly-dependent) template name that could be a template template1269 // argument.1270 TemplateTy Template;1271 if (isEndOfTemplateArgument(Tok) &&1272 Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc, Name,1273 /*ObjectType=*/nullptr,1274 /*EnteringContext=*/false, Template))1275 Result = ParsedTemplateArgument(TemplateKWLoc, SS, Template,1276 Name.StartLocation);1277 }1278 } else if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) ||1279 Tok.is(tok::annot_non_type)) {1280 // We may have a (non-dependent) template name.1281 TemplateTy Template;1282 UnqualifiedId Name;1283 if (Tok.is(tok::annot_non_type)) {1284 NamedDecl *ND = getNonTypeAnnotation(Tok);1285 if (!isa<VarTemplateDecl>(ND))1286 return Result;1287 Name.setIdentifier(ND->getIdentifier(), Tok.getLocation());1288 ConsumeAnnotationToken();1289 } else if (Tok.is(tok::annot_template_id)) {1290 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1291 if (TemplateId->LAngleLoc.isValid())1292 return Result;1293 Name.setIdentifier(TemplateId->Name, Tok.getLocation());1294 ConsumeAnnotationToken();1295 } else {1296 Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());1297 ConsumeToken(); // the identifier1298 }1299 1300 TryConsumeToken(tok::ellipsis, EllipsisLoc);1301 1302 if (isEndOfTemplateArgument(Tok)) {1303 bool MemberOfUnknownSpecialization;1304 TemplateNameKind TNK = Actions.isTemplateName(1305 getCurScope(), SS,1306 /*hasTemplateKeyword=*/false, Name,1307 /*ObjectType=*/nullptr,1308 /*EnteringContext=*/false, Template, MemberOfUnknownSpecialization);1309 if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template ||1310 TNK == TNK_Var_template || TNK == TNK_Concept_template) {1311 // We have an id-expression that refers to a class template or1312 // (C++0x) alias template.1313 Result = ParsedTemplateArgument(/*TemplateKwLoc=*/SourceLocation(), SS,1314 Template, Name.StartLocation);1315 }1316 }1317 }1318 1319 Result = Actions.ActOnTemplateTemplateArgument(Result);1320 1321 // If this is a pack expansion, build it as such.1322 if (EllipsisLoc.isValid() && !Result.isInvalid())1323 Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);1324 1325 return Result;1326}1327 1328ParsedTemplateArgument Parser::ParseTemplateArgument() {1329 // C++ [temp.arg]p2:1330 // In a template-argument, an ambiguity between a type-id and an1331 // expression is resolved to a type-id, regardless of the form of1332 // the corresponding template-parameter.1333 //1334 // Therefore, we initially try to parse a type-id - and isCXXTypeId might look1335 // up and annotate an identifier as an id-expression during disambiguation,1336 // so enter the appropriate context for a constant expression template1337 // argument before trying to disambiguate.1338 1339 EnterExpressionEvaluationContext EnterConstantEvaluated(1340 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated,1341 /*LambdaContextDecl=*/nullptr,1342 /*ExprContext=*/Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);1343 if (isCXXTypeId(TentativeCXXTypeIdContext::AsTemplateArgument)) {1344 TypeResult TypeArg = ParseTypeName(1345 /*Range=*/nullptr, DeclaratorContext::TemplateArg);1346 return Actions.ActOnTemplateTypeArgument(TypeArg);1347 }1348 1349 // Try to parse a template template argument.1350 {1351 TentativeParsingAction TPA(*this);1352 1353 ParsedTemplateArgument TemplateTemplateArgument =1354 ParseTemplateTemplateArgument();1355 if (!TemplateTemplateArgument.isInvalid()) {1356 TPA.Commit();1357 return TemplateTemplateArgument;1358 }1359 // Revert this tentative parse to parse a non-type template argument.1360 TPA.Revert();1361 }1362 1363 // Parse a non-type template argument.1364 ExprResult ExprArg;1365 SourceLocation Loc = Tok.getLocation();1366 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))1367 ExprArg = ParseBraceInitializer();1368 else1369 ExprArg = ParseConstantExpressionInExprEvalContext(1370 TypoCorrectionTypeBehavior::AllowBoth);1371 if (ExprArg.isInvalid() || !ExprArg.get()) {1372 return ParsedTemplateArgument();1373 }1374 1375 return ParsedTemplateArgument(ParsedTemplateArgument::NonType,1376 ExprArg.get(), Loc);1377}1378 1379bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,1380 TemplateTy Template,1381 SourceLocation OpenLoc) {1382 1383 ColonProtectionRAIIObject ColonProtection(*this, false);1384 1385 auto RunSignatureHelp = [&] {1386 if (!Template)1387 return QualType();1388 CalledSignatureHelp = true;1389 return Actions.CodeCompletion().ProduceTemplateArgumentSignatureHelp(1390 Template, TemplateArgs, OpenLoc);1391 };1392 1393 do {1394 PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);1395 ParsedTemplateArgument Arg = ParseTemplateArgument();1396 SourceLocation EllipsisLoc;1397 if (TryConsumeToken(tok::ellipsis, EllipsisLoc))1398 Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);1399 1400 if (Arg.isInvalid()) {1401 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)1402 RunSignatureHelp();1403 return true;1404 }1405 1406 // Save this template argument.1407 TemplateArgs.push_back(Arg);1408 1409 // If the next token is a comma, consume it and keep reading1410 // arguments.1411 } while (TryConsumeToken(tok::comma));1412 1413 return false;1414}1415 1416Parser::DeclGroupPtrTy Parser::ParseExplicitInstantiation(1417 DeclaratorContext Context, SourceLocation ExternLoc,1418 SourceLocation TemplateLoc, SourceLocation &DeclEnd,1419 ParsedAttributes &AccessAttrs, AccessSpecifier AS) {1420 // This isn't really required here.1421 ParsingDeclRAIIObject1422 ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);1423 ParsedTemplateInfo TemplateInfo(ExternLoc, TemplateLoc);1424 return ParseDeclarationAfterTemplate(1425 Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);1426}1427 1428SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {1429 if (TemplateParams)1430 return getTemplateParamsRange(TemplateParams->data(),1431 TemplateParams->size());1432 1433 SourceRange R(TemplateLoc);1434 if (ExternLoc.isValid())1435 R.setBegin(ExternLoc);1436 return R;1437}1438 1439void Parser::LateTemplateParserCallback(void *P, LateParsedTemplate &LPT) {1440 ((Parser *)P)->ParseLateTemplatedFuncDef(LPT);1441}1442 1443void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {1444 if (!LPT.D)1445 return;1446 1447 // Destroy TemplateIdAnnotations when we're done, if possible.1448 DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);1449 1450 // Get the FunctionDecl.1451 FunctionDecl *FunD = LPT.D->getAsFunction();1452 // Track template parameter depth.1453 TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);1454 1455 // To restore the context after late parsing.1456 Sema::ContextRAII GlobalSavedContext(1457 Actions, Actions.Context.getTranslationUnitDecl());1458 1459 MultiParseScope Scopes(*this);1460 1461 // Get the list of DeclContexts to reenter.1462 SmallVector<DeclContext*, 4> DeclContextsToReenter;1463 for (DeclContext *DC = FunD; DC && !DC->isTranslationUnit();1464 DC = DC->getLexicalParent())1465 DeclContextsToReenter.push_back(DC);1466 1467 // Reenter scopes from outermost to innermost.1468 for (DeclContext *DC : reverse(DeclContextsToReenter)) {1469 CurTemplateDepthTracker.addDepth(1470 ReenterTemplateScopes(Scopes, cast<Decl>(DC)));1471 Scopes.Enter(Scope::DeclScope);1472 // We'll reenter the function context itself below.1473 if (DC != FunD)1474 Actions.PushDeclContext(Actions.getCurScope(), DC);1475 }1476 1477 // Parsing should occur with empty FP pragma stack and FP options used in the1478 // point of the template definition.1479 Sema::FpPragmaStackSaveRAII SavedStack(Actions);1480 Actions.resetFPOptions(LPT.FPO);1481 1482 assert(!LPT.Toks.empty() && "Empty body!");1483 1484 // Append the current token at the end of the new token stream so that it1485 // doesn't get lost.1486 LPT.Toks.push_back(Tok);1487 PP.EnterTokenStream(LPT.Toks, true, /*IsReinject*/true);1488 1489 // Consume the previously pushed token.1490 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);1491 assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) &&1492 "Inline method not starting with '{', ':' or 'try'");1493 1494 // Parse the method body. Function body parsing code is similar enough1495 // to be re-used for method bodies as well.1496 ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |1497 Scope::CompoundStmtScope);1498 1499 // Recreate the containing function DeclContext.1500 Sema::ContextRAII FunctionSavedContext(Actions, FunD->getLexicalParent());1501 1502 Actions.ActOnStartOfFunctionDef(getCurScope(), FunD);1503 1504 if (Tok.is(tok::kw_try)) {1505 ParseFunctionTryBlock(LPT.D, FnScope);1506 } else {1507 if (Tok.is(tok::colon))1508 ParseConstructorInitializer(LPT.D);1509 else1510 Actions.ActOnDefaultCtorInitializers(LPT.D);1511 1512 if (Tok.is(tok::l_brace)) {1513 assert((!isa<FunctionTemplateDecl>(LPT.D) ||1514 cast<FunctionTemplateDecl>(LPT.D)1515 ->getTemplateParameters()1516 ->getDepth() == TemplateParameterDepth - 1) &&1517 "TemplateParameterDepth should be greater than the depth of "1518 "current template being instantiated!");1519 ParseFunctionStatementBody(LPT.D, FnScope);1520 Actions.UnmarkAsLateParsedTemplate(FunD);1521 } else1522 Actions.ActOnFinishFunctionBody(LPT.D, nullptr);1523 }1524}1525 1526void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {1527 tok::TokenKind kind = Tok.getKind();1528 if (!ConsumeAndStoreFunctionPrologue(Toks)) {1529 // Consume everything up to (and including) the matching right brace.1530 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);1531 }1532 1533 // If we're in a function-try-block, we need to store all the catch blocks.1534 if (kind == tok::kw_try) {1535 while (Tok.is(tok::kw_catch)) {1536 ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);1537 ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);1538 }1539 }1540}1541 1542bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) {1543 TentativeParsingAction TPA(*this);1544 // FIXME: We could look at the token sequence in a lot more detail here.1545 if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater,1546 StopAtSemi | StopBeforeMatch)) {1547 TPA.Commit();1548 1549 SourceLocation Greater;1550 ParseGreaterThanInTemplateList(Less, Greater, true, false);1551 Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS,1552 Less, Greater);1553 return true;1554 }1555 1556 // There's no matching '>' token, this probably isn't supposed to be1557 // interpreted as a template-id. Parse it as an (ill-formed) comparison.1558 TPA.Revert();1559 return false;1560}1561 1562void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) {1563 assert(Tok.is(tok::less) && "not at a potential angle bracket");1564 1565 bool DependentTemplateName = false;1566 if (!Actions.mightBeIntendedToBeTemplateName(PotentialTemplateName,1567 DependentTemplateName))1568 return;1569 1570 // OK, this might be a name that the user intended to be parsed as a1571 // template-name, followed by a '<' token. Check for some easy cases.1572 1573 // If we have potential_template<>, then it's supposed to be a template-name.1574 if (NextToken().is(tok::greater) ||1575 (getLangOpts().CPlusPlus11 &&1576 NextToken().isOneOf(tok::greatergreater, tok::greatergreatergreater))) {1577 SourceLocation Less = ConsumeToken();1578 SourceLocation Greater;1579 ParseGreaterThanInTemplateList(Less, Greater, true, false);1580 Actions.diagnoseExprIntendedAsTemplateName(1581 getCurScope(), PotentialTemplateName, Less, Greater);1582 // FIXME: Perform error recovery.1583 PotentialTemplateName = ExprError();1584 return;1585 }1586 1587 // If we have 'potential_template<type-id', assume it's supposed to be a1588 // template-name if there's a matching '>' later on.1589 {1590 // FIXME: Avoid the tentative parse when NextToken() can't begin a type.1591 TentativeParsingAction TPA(*this);1592 SourceLocation Less = ConsumeToken();1593 if (isTypeIdUnambiguously() &&1594 diagnoseUnknownTemplateId(PotentialTemplateName, Less)) {1595 TPA.Commit();1596 // FIXME: Perform error recovery.1597 PotentialTemplateName = ExprError();1598 return;1599 }1600 TPA.Revert();1601 }1602 1603 // Otherwise, remember that we saw this in case we see a potentially-matching1604 // '>' token later on.1605 AngleBracketTracker::Priority Priority =1606 (DependentTemplateName ? AngleBracketTracker::DependentName1607 : AngleBracketTracker::PotentialTypo) |1608 (Tok.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess1609 : AngleBracketTracker::NoSpaceBeforeLess);1610 AngleBrackets.add(*this, PotentialTemplateName.get(), Tok.getLocation(),1611 Priority);1612}1613 1614bool Parser::checkPotentialAngleBracketDelimiter(1615 const AngleBracketTracker::Loc &LAngle, const Token &OpToken) {1616 // If a comma in an expression context is followed by a type that can be a1617 // template argument and cannot be an expression, then this is ill-formed,1618 // but might be intended to be part of a template-id.1619 if (OpToken.is(tok::comma) && isTypeIdUnambiguously() &&1620 diagnoseUnknownTemplateId(LAngle.TemplateName, LAngle.LessLoc)) {1621 AngleBrackets.clear(*this);1622 return true;1623 }1624 1625 // If a context that looks like a template-id is followed by '()', then1626 // this is ill-formed, but might be intended to be a template-id1627 // followed by '()'.1628 if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) &&1629 NextToken().is(tok::r_paren)) {1630 Actions.diagnoseExprIntendedAsTemplateName(1631 getCurScope(), LAngle.TemplateName, LAngle.LessLoc,1632 OpToken.getLocation());1633 AngleBrackets.clear(*this);1634 return true;1635 }1636 1637 // After a '>' (etc), we're no longer potentially in a construct that's1638 // intended to be treated as a template-id.1639 if (OpToken.is(tok::greater) ||1640 (getLangOpts().CPlusPlus11 &&1641 OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater)))1642 AngleBrackets.clear(*this);1643 return false;1644}1645