Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseTemplate.cpp
35233 views
//===--- ParseTemplate.cpp - Template Parsing -----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements parsing of C++ templates.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/ASTContext.h"13#include "clang/AST/DeclTemplate.h"14#include "clang/AST/ExprCXX.h"15#include "clang/Parse/ParseDiagnostic.h"16#include "clang/Parse/Parser.h"17#include "clang/Parse/RAIIObjectsForParser.h"18#include "clang/Sema/DeclSpec.h"19#include "clang/Sema/EnterExpressionEvaluationContext.h"20#include "clang/Sema/ParsedTemplate.h"21#include "clang/Sema/Scope.h"22#include "clang/Sema/SemaDiagnostic.h"23#include "llvm/Support/TimeProfiler.h"24using namespace clang;2526/// Re-enter a possible template scope, creating as many template parameter27/// scopes as necessary.28/// \return The number of template parameter scopes entered.29unsigned Parser::ReenterTemplateScopes(MultiParseScope &S, Decl *D) {30return Actions.ActOnReenterTemplateScope(D, [&] {31S.Enter(Scope::TemplateParamScope);32return Actions.getCurScope();33});34}3536/// Parse a template declaration, explicit instantiation, or37/// explicit specialization.38Parser::DeclGroupPtrTy39Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,40SourceLocation &DeclEnd,41ParsedAttributes &AccessAttrs) {42ObjCDeclContextSwitch ObjCDC(*this);4344if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {45return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(),46DeclEnd, AccessAttrs,47AccessSpecifier::AS_none);48}49return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs,50AccessSpecifier::AS_none);51}5253/// Parse a template declaration or an explicit specialization.54///55/// Template declarations include one or more template parameter lists56/// and either the function or class template declaration. Explicit57/// specializations contain one or more 'template < >' prefixes58/// followed by a (possibly templated) declaration. Since the59/// syntactic form of both features is nearly identical, we parse all60/// of the template headers together and let semantic analysis sort61/// the declarations from the explicit specializations.62///63/// template-declaration: [C++ temp]64/// 'export'[opt] 'template' '<' template-parameter-list '>' declaration65///66/// template-declaration: [C++2a]67/// template-head declaration68/// template-head concept-definition69///70/// TODO: requires-clause71/// template-head: [C++2a]72/// 'template' '<' template-parameter-list '>'73/// requires-clause[opt]74///75/// explicit-specialization: [ C++ temp.expl.spec]76/// 'template' '<' '>' declaration77Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization(78DeclaratorContext Context, SourceLocation &DeclEnd,79ParsedAttributes &AccessAttrs, AccessSpecifier AS) {80assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&81"Token does not start a template declaration.");8283MultiParseScope TemplateParamScopes(*this);8485// Tell the action that names should be checked in the context of86// the declaration to come.87ParsingDeclRAIIObject88ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);8990// Parse multiple levels of template headers within this template91// parameter scope, e.g.,92//93// template<typename T>94// template<typename U>95// class A<T>::B { ... };96//97// We parse multiple levels non-recursively so that we can build a98// single data structure containing all of the template parameter99// lists to easily differentiate between the case above and:100//101// template<typename T>102// class A {103// template<typename U> class B;104// };105//106// In the first case, the action for declaring A<T>::B receives107// both template parameter lists. In the second case, the action for108// defining A<T>::B receives just the inner template parameter list109// (and retrieves the outer template parameter list from its110// context).111bool isSpecialization = true;112bool LastParamListWasEmpty = false;113TemplateParameterLists ParamLists;114TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);115116do {117// Consume the 'export', if any.118SourceLocation ExportLoc;119TryConsumeToken(tok::kw_export, ExportLoc);120121// Consume the 'template', which should be here.122SourceLocation TemplateLoc;123if (!TryConsumeToken(tok::kw_template, TemplateLoc)) {124Diag(Tok.getLocation(), diag::err_expected_template);125return nullptr;126}127128// Parse the '<' template-parameter-list '>'129SourceLocation LAngleLoc, RAngleLoc;130SmallVector<NamedDecl*, 4> TemplateParams;131if (ParseTemplateParameters(TemplateParamScopes,132CurTemplateDepthTracker.getDepth(),133TemplateParams, LAngleLoc, RAngleLoc)) {134// Skip until the semi-colon or a '}'.135SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);136TryConsumeToken(tok::semi);137return nullptr;138}139140ExprResult OptionalRequiresClauseConstraintER;141if (!TemplateParams.empty()) {142isSpecialization = false;143++CurTemplateDepthTracker;144145if (TryConsumeToken(tok::kw_requires)) {146OptionalRequiresClauseConstraintER =147Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(148/*IsTrailingRequiresClause=*/false));149if (!OptionalRequiresClauseConstraintER.isUsable()) {150// Skip until the semi-colon or a '}'.151SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);152TryConsumeToken(tok::semi);153return nullptr;154}155}156} else {157LastParamListWasEmpty = true;158}159160ParamLists.push_back(Actions.ActOnTemplateParameterList(161CurTemplateDepthTracker.getDepth(), ExportLoc, TemplateLoc, LAngleLoc,162TemplateParams, RAngleLoc, OptionalRequiresClauseConstraintER.get()));163} while (Tok.isOneOf(tok::kw_export, tok::kw_template));164165ParsedTemplateInfo TemplateInfo(&ParamLists, isSpecialization,166LastParamListWasEmpty);167168// Parse the actual template declaration.169if (Tok.is(tok::kw_concept)) {170Decl *ConceptDecl = ParseConceptDefinition(TemplateInfo, DeclEnd);171// We need to explicitly pass ConceptDecl to ParsingDeclRAIIObject, so that172// delayed diagnostics (e.g. warn_deprecated) have a Decl to work with.173ParsingTemplateParams.complete(ConceptDecl);174return Actions.ConvertDeclToDeclGroup(ConceptDecl);175}176177return ParseDeclarationAfterTemplate(178Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);179}180181/// Parse a single declaration that declares a template,182/// template specialization, or explicit instantiation of a template.183///184/// \param DeclEnd will receive the source location of the last token185/// within this declaration.186///187/// \param AS the access specifier associated with this188/// declaration. Will be AS_none for namespace-scope declarations.189///190/// \returns the new declaration.191Parser::DeclGroupPtrTy Parser::ParseDeclarationAfterTemplate(192DeclaratorContext Context, ParsedTemplateInfo &TemplateInfo,193ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd,194ParsedAttributes &AccessAttrs, AccessSpecifier AS) {195assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&196"Template information required");197198if (Tok.is(tok::kw_static_assert)) {199// A static_assert declaration may not be templated.200Diag(Tok.getLocation(), diag::err_templated_invalid_declaration)201<< TemplateInfo.getSourceRange();202// Parse the static_assert declaration to improve error recovery.203return Actions.ConvertDeclToDeclGroup(204ParseStaticAssertDeclaration(DeclEnd));205}206207// We are parsing a member template.208if (Context == DeclaratorContext::Member)209return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,210&DiagsFromTParams);211212ParsedAttributes DeclAttrs(AttrFactory);213ParsedAttributes DeclSpecAttrs(AttrFactory);214215// GNU attributes are applied to the declaration specification while the216// standard attributes are applied to the declaration. We parse the two217// attribute sets into different containters so we can apply them during218// the regular parsing process.219while (MaybeParseCXX11Attributes(DeclAttrs) ||220MaybeParseGNUAttributes(DeclSpecAttrs))221;222223if (Tok.is(tok::kw_using))224return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,225DeclAttrs);226227// Parse the declaration specifiers, stealing any diagnostics from228// the template parameters.229ParsingDeclSpec DS(*this, &DiagsFromTParams);230DS.SetRangeStart(DeclSpecAttrs.Range.getBegin());231DS.SetRangeEnd(DeclSpecAttrs.Range.getEnd());232DS.takeAttributesFrom(DeclSpecAttrs);233234ParseDeclarationSpecifiers(DS, TemplateInfo, AS,235getDeclSpecContextFromDeclaratorContext(Context));236237if (Tok.is(tok::semi)) {238ProhibitAttributes(DeclAttrs);239DeclEnd = ConsumeToken();240RecordDecl *AnonRecord = nullptr;241Decl *Decl = Actions.ParsedFreeStandingDeclSpec(242getCurScope(), AS, DS, ParsedAttributesView::none(),243TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams244: MultiTemplateParamsArg(),245TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation,246AnonRecord);247Actions.ActOnDefinedDeclarationSpecifier(Decl);248assert(!AnonRecord &&249"Anonymous unions/structs should not be valid with template");250DS.complete(Decl);251return Actions.ConvertDeclToDeclGroup(Decl);252}253254if (DS.hasTagDefinition())255Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());256257// Move the attributes from the prefix into the DS.258if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)259ProhibitAttributes(DeclAttrs);260261return ParseDeclGroup(DS, Context, DeclAttrs, TemplateInfo, &DeclEnd);262}263264/// \brief Parse a single declaration that declares a concept.265///266/// \param DeclEnd will receive the source location of the last token267/// within this declaration.268///269/// \returns the new declaration.270Decl *271Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,272SourceLocation &DeclEnd) {273assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&274"Template information required");275assert(Tok.is(tok::kw_concept) &&276"ParseConceptDefinition must be called when at a 'concept' keyword");277278ConsumeToken(); // Consume 'concept'279280SourceLocation BoolKWLoc;281if (TryConsumeToken(tok::kw_bool, BoolKWLoc))282Diag(Tok.getLocation(), diag::err_concept_legacy_bool_keyword) <<283FixItHint::CreateRemoval(SourceLocation(BoolKWLoc));284285DiagnoseAndSkipCXX11Attributes();286287CXXScopeSpec SS;288if (ParseOptionalCXXScopeSpecifier(289SS, /*ObjectType=*/nullptr,290/*ObjectHasErrors=*/false, /*EnteringContext=*/false,291/*MayBePseudoDestructor=*/nullptr,292/*IsTypename=*/false, /*LastII=*/nullptr, /*OnlyNamespace=*/true) ||293SS.isInvalid()) {294SkipUntil(tok::semi);295return nullptr;296}297298if (SS.isNotEmpty())299Diag(SS.getBeginLoc(),300diag::err_concept_definition_not_identifier);301302UnqualifiedId Result;303if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,304/*ObjectHadErrors=*/false, /*EnteringContext=*/false,305/*AllowDestructorName=*/false,306/*AllowConstructorName=*/false,307/*AllowDeductionGuide=*/false,308/*TemplateKWLoc=*/nullptr, Result)) {309SkipUntil(tok::semi);310return nullptr;311}312313if (Result.getKind() != UnqualifiedIdKind::IK_Identifier) {314Diag(Result.getBeginLoc(), diag::err_concept_definition_not_identifier);315SkipUntil(tok::semi);316return nullptr;317}318319const IdentifierInfo *Id = Result.Identifier;320SourceLocation IdLoc = Result.getBeginLoc();321322ParsedAttributes Attrs(AttrFactory);323MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);324325if (!TryConsumeToken(tok::equal)) {326Diag(Tok.getLocation(), diag::err_expected) << tok::equal;327SkipUntil(tok::semi);328return nullptr;329}330331ExprResult ConstraintExprResult =332Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression());333if (ConstraintExprResult.isInvalid()) {334SkipUntil(tok::semi);335return nullptr;336}337338DeclEnd = Tok.getLocation();339ExpectAndConsumeSemi(diag::err_expected_semi_declaration);340Expr *ConstraintExpr = ConstraintExprResult.get();341return Actions.ActOnConceptDefinition(getCurScope(),342*TemplateInfo.TemplateParams, Id, IdLoc,343ConstraintExpr, Attrs);344}345346/// ParseTemplateParameters - Parses a template-parameter-list enclosed in347/// angle brackets. Depth is the depth of this template-parameter-list, which348/// is the number of template headers directly enclosing this template header.349/// TemplateParams is the current list of template parameters we're building.350/// The template parameter we parse will be added to this list. LAngleLoc and351/// RAngleLoc will receive the positions of the '<' and '>', respectively,352/// that enclose this template parameter list.353///354/// \returns true if an error occurred, false otherwise.355bool Parser::ParseTemplateParameters(356MultiParseScope &TemplateScopes, unsigned Depth,357SmallVectorImpl<NamedDecl *> &TemplateParams, SourceLocation &LAngleLoc,358SourceLocation &RAngleLoc) {359// Get the template parameter list.360if (!TryConsumeToken(tok::less, LAngleLoc)) {361Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";362return true;363}364365// Try to parse the template parameter list.366bool Failed = false;367// FIXME: Missing greatergreatergreater support.368if (!Tok.is(tok::greater) && !Tok.is(tok::greatergreater)) {369TemplateScopes.Enter(Scope::TemplateParamScope);370Failed = ParseTemplateParameterList(Depth, TemplateParams);371}372373if (Tok.is(tok::greatergreater)) {374// No diagnostic required here: a template-parameter-list can only be375// followed by a declaration or, for a template template parameter, the376// 'class' keyword. Therefore, the second '>' will be diagnosed later.377// This matters for elegant diagnosis of:378// template<template<typename>> struct S;379Tok.setKind(tok::greater);380RAngleLoc = Tok.getLocation();381Tok.setLocation(Tok.getLocation().getLocWithOffset(1));382} else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) {383Diag(Tok.getLocation(), diag::err_expected) << tok::greater;384return true;385}386return false;387}388389/// ParseTemplateParameterList - Parse a template parameter list. If390/// the parsing fails badly (i.e., closing bracket was left out), this391/// will try to put the token stream in a reasonable position (closing392/// a statement, etc.) and return false.393///394/// template-parameter-list: [C++ temp]395/// template-parameter396/// template-parameter-list ',' template-parameter397bool398Parser::ParseTemplateParameterList(const unsigned Depth,399SmallVectorImpl<NamedDecl*> &TemplateParams) {400while (true) {401402if (NamedDecl *TmpParam403= ParseTemplateParameter(Depth, TemplateParams.size())) {404TemplateParams.push_back(TmpParam);405} else {406// If we failed to parse a template parameter, skip until we find407// a comma or closing brace.408SkipUntil(tok::comma, tok::greater, tok::greatergreater,409StopAtSemi | StopBeforeMatch);410}411412// Did we find a comma or the end of the template parameter list?413if (Tok.is(tok::comma)) {414ConsumeToken();415} else if (Tok.isOneOf(tok::greater, tok::greatergreater)) {416// Don't consume this... that's done by template parser.417break;418} else {419// Somebody probably forgot to close the template. Skip ahead and420// try to get out of the expression. This error is currently421// subsumed by whatever goes on in ParseTemplateParameter.422Diag(Tok.getLocation(), diag::err_expected_comma_greater);423SkipUntil(tok::comma, tok::greater, tok::greatergreater,424StopAtSemi | StopBeforeMatch);425return false;426}427}428return true;429}430431/// Determine whether the parser is at the start of a template432/// type parameter.433Parser::TPResult Parser::isStartOfTemplateTypeParameter() {434if (Tok.is(tok::kw_class)) {435// "class" may be the start of an elaborated-type-specifier or a436// type-parameter. Per C++ [temp.param]p3, we prefer the type-parameter.437switch (NextToken().getKind()) {438case tok::equal:439case tok::comma:440case tok::greater:441case tok::greatergreater:442case tok::ellipsis:443return TPResult::True;444445case tok::identifier:446// This may be either a type-parameter or an elaborated-type-specifier.447// We have to look further.448break;449450default:451return TPResult::False;452}453454switch (GetLookAheadToken(2).getKind()) {455case tok::equal:456case tok::comma:457case tok::greater:458case tok::greatergreater:459return TPResult::True;460461default:462return TPResult::False;463}464}465466if (TryAnnotateTypeConstraint())467return TPResult::Error;468469if (isTypeConstraintAnnotation() &&470// Next token might be 'auto' or 'decltype', indicating that this471// type-constraint is in fact part of a placeholder-type-specifier of a472// non-type template parameter.473!GetLookAheadToken(Tok.is(tok::annot_cxxscope) ? 2 : 1)474.isOneOf(tok::kw_auto, tok::kw_decltype))475return TPResult::True;476477// 'typedef' is a reasonably-common typo/thinko for 'typename', and is478// ill-formed otherwise.479if (Tok.isNot(tok::kw_typename) && Tok.isNot(tok::kw_typedef))480return TPResult::False;481482// C++ [temp.param]p2:483// There is no semantic difference between class and typename in a484// template-parameter. typename followed by an unqualified-id485// names a template type parameter. typename followed by a486// qualified-id denotes the type in a non-type487// parameter-declaration.488Token Next = NextToken();489490// If we have an identifier, skip over it.491if (Next.getKind() == tok::identifier)492Next = GetLookAheadToken(2);493494switch (Next.getKind()) {495case tok::equal:496case tok::comma:497case tok::greater:498case tok::greatergreater:499case tok::ellipsis:500return TPResult::True;501502case tok::kw_typename:503case tok::kw_typedef:504case tok::kw_class:505// These indicate that a comma was missed after a type parameter, not that506// we have found a non-type parameter.507return TPResult::True;508509default:510return TPResult::False;511}512}513514/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).515///516/// template-parameter: [C++ temp.param]517/// type-parameter518/// parameter-declaration519///520/// type-parameter: (See below)521/// type-parameter-key ...[opt] identifier[opt]522/// type-parameter-key identifier[opt] = type-id523/// (C++2a) type-constraint ...[opt] identifier[opt]524/// (C++2a) type-constraint identifier[opt] = type-id525/// 'template' '<' template-parameter-list '>' type-parameter-key526/// ...[opt] identifier[opt]527/// 'template' '<' template-parameter-list '>' type-parameter-key528/// identifier[opt] '=' id-expression529///530/// type-parameter-key:531/// class532/// typename533///534NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {535536switch (isStartOfTemplateTypeParameter()) {537case TPResult::True:538// Is there just a typo in the input code? ('typedef' instead of539// 'typename')540if (Tok.is(tok::kw_typedef)) {541Diag(Tok.getLocation(), diag::err_expected_template_parameter);542543Diag(Tok.getLocation(), diag::note_meant_to_use_typename)544<< FixItHint::CreateReplacement(CharSourceRange::getCharRange(545Tok.getLocation(),546Tok.getEndLoc()),547"typename");548549Tok.setKind(tok::kw_typename);550}551552return ParseTypeParameter(Depth, Position);553case TPResult::False:554break;555556case TPResult::Error: {557// We return an invalid parameter as opposed to null to avoid having bogus558// diagnostics about an empty template parameter list.559// FIXME: Fix ParseTemplateParameterList to better handle nullptr results560// from here.561// Return a NTTP as if there was an error in a scope specifier, the user562// probably meant to write the type of a NTTP.563DeclSpec DS(getAttrFactory());564DS.SetTypeSpecError();565Declarator D(DS, ParsedAttributesView::none(),566DeclaratorContext::TemplateParam);567D.SetIdentifier(nullptr, Tok.getLocation());568D.setInvalidType(true);569NamedDecl *ErrorParam = Actions.ActOnNonTypeTemplateParameter(570getCurScope(), D, Depth, Position, /*EqualLoc=*/SourceLocation(),571/*DefaultArg=*/nullptr);572ErrorParam->setInvalidDecl(true);573SkipUntil(tok::comma, tok::greater, tok::greatergreater,574StopAtSemi | StopBeforeMatch);575return ErrorParam;576}577578case TPResult::Ambiguous:579llvm_unreachable("template param classification can't be ambiguous");580}581582if (Tok.is(tok::kw_template))583return ParseTemplateTemplateParameter(Depth, Position);584585// If it's none of the above, then it must be a parameter declaration.586// NOTE: This will pick up errors in the closure of the template parameter587// list (e.g., template < ; Check here to implement >> style closures.588return ParseNonTypeTemplateParameter(Depth, Position);589}590591/// Check whether the current token is a template-id annotation denoting a592/// type-constraint.593bool Parser::isTypeConstraintAnnotation() {594const Token &T = Tok.is(tok::annot_cxxscope) ? NextToken() : Tok;595if (T.isNot(tok::annot_template_id))596return false;597const auto *ExistingAnnot =598static_cast<TemplateIdAnnotation *>(T.getAnnotationValue());599return ExistingAnnot->Kind == TNK_Concept_template;600}601602/// Try parsing a type-constraint at the current location.603///604/// type-constraint:605/// nested-name-specifier[opt] concept-name606/// nested-name-specifier[opt] concept-name607/// '<' template-argument-list[opt] '>'[opt]608///609/// \returns true if an error occurred, and false otherwise.610bool Parser::TryAnnotateTypeConstraint() {611if (!getLangOpts().CPlusPlus20)612return false;613CXXScopeSpec SS;614bool WasScopeAnnotation = Tok.is(tok::annot_cxxscope);615if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,616/*ObjectHasErrors=*/false,617/*EnteringContext=*/false,618/*MayBePseudoDestructor=*/nullptr,619// If this is not a type-constraint, then620// this scope-spec is part of the typename621// of a non-type template parameter622/*IsTypename=*/true, /*LastII=*/nullptr,623// We won't find concepts in624// non-namespaces anyway, so might as well625// parse this correctly for possible type626// names.627/*OnlyNamespace=*/false))628return true;629630if (Tok.is(tok::identifier)) {631UnqualifiedId PossibleConceptName;632PossibleConceptName.setIdentifier(Tok.getIdentifierInfo(),633Tok.getLocation());634635TemplateTy PossibleConcept;636bool MemberOfUnknownSpecialization = false;637auto TNK = Actions.isTemplateName(getCurScope(), SS,638/*hasTemplateKeyword=*/false,639PossibleConceptName,640/*ObjectType=*/ParsedType(),641/*EnteringContext=*/false,642PossibleConcept,643MemberOfUnknownSpecialization,644/*Disambiguation=*/true);645if (MemberOfUnknownSpecialization || !PossibleConcept ||646TNK != TNK_Concept_template) {647if (SS.isNotEmpty())648AnnotateScopeToken(SS, !WasScopeAnnotation);649return false;650}651652// At this point we're sure we're dealing with a constrained parameter. It653// may or may not have a template parameter list following the concept654// name.655if (AnnotateTemplateIdToken(PossibleConcept, TNK, SS,656/*TemplateKWLoc=*/SourceLocation(),657PossibleConceptName,658/*AllowTypeAnnotation=*/false,659/*TypeConstraint=*/true))660return true;661}662663if (SS.isNotEmpty())664AnnotateScopeToken(SS, !WasScopeAnnotation);665return false;666}667668/// ParseTypeParameter - Parse a template type parameter (C++ [temp.param]).669/// Other kinds of template parameters are parsed in670/// ParseTemplateTemplateParameter and ParseNonTypeTemplateParameter.671///672/// type-parameter: [C++ temp.param]673/// 'class' ...[opt][C++0x] identifier[opt]674/// 'class' identifier[opt] '=' type-id675/// 'typename' ...[opt][C++0x] identifier[opt]676/// 'typename' identifier[opt] '=' type-id677NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {678assert((Tok.isOneOf(tok::kw_class, tok::kw_typename) ||679isTypeConstraintAnnotation()) &&680"A type-parameter starts with 'class', 'typename' or a "681"type-constraint");682683CXXScopeSpec TypeConstraintSS;684TemplateIdAnnotation *TypeConstraint = nullptr;685bool TypenameKeyword = false;686SourceLocation KeyLoc;687ParseOptionalCXXScopeSpecifier(TypeConstraintSS, /*ObjectType=*/nullptr,688/*ObjectHasErrors=*/false,689/*EnteringContext*/ false);690if (Tok.is(tok::annot_template_id)) {691// Consume the 'type-constraint'.692TypeConstraint =693static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());694assert(TypeConstraint->Kind == TNK_Concept_template &&695"stray non-concept template-id annotation");696KeyLoc = ConsumeAnnotationToken();697} else {698assert(TypeConstraintSS.isEmpty() &&699"expected type constraint after scope specifier");700701// Consume the 'class' or 'typename' keyword.702TypenameKeyword = Tok.is(tok::kw_typename);703KeyLoc = ConsumeToken();704}705706// Grab the ellipsis (if given).707SourceLocation EllipsisLoc;708if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {709Diag(EllipsisLoc,710getLangOpts().CPlusPlus11711? diag::warn_cxx98_compat_variadic_templates712: diag::ext_variadic_templates);713}714715// Grab the template parameter name (if given)716SourceLocation NameLoc = Tok.getLocation();717IdentifierInfo *ParamName = nullptr;718if (Tok.is(tok::identifier)) {719ParamName = Tok.getIdentifierInfo();720ConsumeToken();721} else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,722tok::greatergreater)) {723// Unnamed template parameter. Don't have to do anything here, just724// don't consume this token.725} else {726Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;727return nullptr;728}729730// Recover from misplaced ellipsis.731bool AlreadyHasEllipsis = EllipsisLoc.isValid();732if (TryConsumeToken(tok::ellipsis, EllipsisLoc))733DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true);734735// Grab a default argument (if available).736// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before737// we introduce the type parameter into the local scope.738SourceLocation EqualLoc;739ParsedType DefaultArg;740std::optional<DelayTemplateIdDestructionRAII> DontDestructTemplateIds;741if (TryConsumeToken(tok::equal, EqualLoc)) {742// The default argument might contain a lambda declaration; avoid destroying743// parsed template ids at the end of that declaration because they can be744// used in a type constraint later.745DontDestructTemplateIds.emplace(*this, /*DelayTemplateIdDestruction=*/true);746// The default argument may declare template parameters, notably747// if it contains a generic lambda, so we need to increase748// the template depth as these parameters would not be instantiated749// at the current level.750TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);751++CurTemplateDepthTracker;752DefaultArg =753ParseTypeName(/*Range=*/nullptr, DeclaratorContext::TemplateTypeArg)754.get();755}756757NamedDecl *NewDecl = Actions.ActOnTypeParameter(getCurScope(),758TypenameKeyword, EllipsisLoc,759KeyLoc, ParamName, NameLoc,760Depth, Position, EqualLoc,761DefaultArg,762TypeConstraint != nullptr);763764if (TypeConstraint) {765Actions.ActOnTypeConstraint(TypeConstraintSS, TypeConstraint,766cast<TemplateTypeParmDecl>(NewDecl),767EllipsisLoc);768}769770return NewDecl;771}772773/// ParseTemplateTemplateParameter - Handle the parsing of template774/// template parameters.775///776/// type-parameter: [C++ temp.param]777/// template-head type-parameter-key ...[opt] identifier[opt]778/// template-head type-parameter-key identifier[opt] = id-expression779/// type-parameter-key:780/// 'class'781/// 'typename' [C++1z]782/// template-head: [C++2a]783/// 'template' '<' template-parameter-list '>'784/// requires-clause[opt]785NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,786unsigned Position) {787assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");788789// Handle the template <...> part.790SourceLocation TemplateLoc = ConsumeToken();791SmallVector<NamedDecl*,8> TemplateParams;792SourceLocation LAngleLoc, RAngleLoc;793ExprResult OptionalRequiresClauseConstraintER;794{795MultiParseScope TemplateParmScope(*this);796if (ParseTemplateParameters(TemplateParmScope, Depth + 1, TemplateParams,797LAngleLoc, RAngleLoc)) {798return nullptr;799}800if (TryConsumeToken(tok::kw_requires)) {801OptionalRequiresClauseConstraintER =802Actions.ActOnRequiresClause(ParseConstraintLogicalOrExpression(803/*IsTrailingRequiresClause=*/false));804if (!OptionalRequiresClauseConstraintER.isUsable()) {805SkipUntil(tok::comma, tok::greater, tok::greatergreater,806StopAtSemi | StopBeforeMatch);807return nullptr;808}809}810}811812// Provide an ExtWarn if the C++1z feature of using 'typename' here is used.813// Generate a meaningful error if the user forgot to put class before the814// identifier, comma, or greater. Provide a fixit if the identifier, comma,815// or greater appear immediately or after 'struct'. In the latter case,816// replace the keyword with 'class'.817bool TypenameKeyword = false;818if (!TryConsumeToken(tok::kw_class)) {819bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);820const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;821if (Tok.is(tok::kw_typename)) {822TypenameKeyword = true;823Diag(Tok.getLocation(),824getLangOpts().CPlusPlus17825? diag::warn_cxx14_compat_template_template_param_typename826: diag::ext_template_template_param_typename)827<< (!getLangOpts().CPlusPlus17828? FixItHint::CreateReplacement(Tok.getLocation(), "class")829: FixItHint());830} else if (Next.isOneOf(tok::identifier, tok::comma, tok::greater,831tok::greatergreater, tok::ellipsis)) {832Diag(Tok.getLocation(), diag::err_class_on_template_template_param)833<< getLangOpts().CPlusPlus17834<< (Replace835? FixItHint::CreateReplacement(Tok.getLocation(), "class")836: FixItHint::CreateInsertion(Tok.getLocation(), "class "));837} else838Diag(Tok.getLocation(), diag::err_class_on_template_template_param)839<< getLangOpts().CPlusPlus17;840841if (Replace)842ConsumeToken();843}844845// Parse the ellipsis, if given.846SourceLocation EllipsisLoc;847if (TryConsumeToken(tok::ellipsis, EllipsisLoc))848Diag(EllipsisLoc,849getLangOpts().CPlusPlus11850? diag::warn_cxx98_compat_variadic_templates851: diag::ext_variadic_templates);852853// Get the identifier, if given.854SourceLocation NameLoc = Tok.getLocation();855IdentifierInfo *ParamName = nullptr;856if (Tok.is(tok::identifier)) {857ParamName = Tok.getIdentifierInfo();858ConsumeToken();859} else if (Tok.isOneOf(tok::equal, tok::comma, tok::greater,860tok::greatergreater)) {861// Unnamed template parameter. Don't have to do anything here, just862// don't consume this token.863} else {864Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;865return nullptr;866}867868// Recover from misplaced ellipsis.869bool AlreadyHasEllipsis = EllipsisLoc.isValid();870if (TryConsumeToken(tok::ellipsis, EllipsisLoc))871DiagnoseMisplacedEllipsis(EllipsisLoc, NameLoc, AlreadyHasEllipsis, true);872873TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(874Depth, SourceLocation(), TemplateLoc, LAngleLoc, TemplateParams,875RAngleLoc, OptionalRequiresClauseConstraintER.get());876877// Grab a default argument (if available).878// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before879// we introduce the template parameter into the local scope.880SourceLocation EqualLoc;881ParsedTemplateArgument DefaultArg;882if (TryConsumeToken(tok::equal, EqualLoc)) {883DefaultArg = ParseTemplateTemplateArgument();884if (DefaultArg.isInvalid()) {885Diag(Tok.getLocation(),886diag::err_default_template_template_parameter_not_template);887SkipUntil(tok::comma, tok::greater, tok::greatergreater,888StopAtSemi | StopBeforeMatch);889}890}891892return Actions.ActOnTemplateTemplateParameter(893getCurScope(), TemplateLoc, ParamList, TypenameKeyword, EllipsisLoc,894ParamName, NameLoc, Depth, Position, EqualLoc, DefaultArg);895}896897/// ParseNonTypeTemplateParameter - Handle the parsing of non-type898/// template parameters (e.g., in "template<int Size> class array;").899///900/// template-parameter:901/// ...902/// parameter-declaration903NamedDecl *904Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {905// Parse the declaration-specifiers (i.e., the type).906// FIXME: The type should probably be restricted in some way... Not all907// declarators (parts of declarators?) are accepted for parameters.908DeclSpec DS(AttrFactory);909ParsedTemplateInfo TemplateInfo;910ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none,911DeclSpecContext::DSC_template_param);912913// Parse this as a typename.914Declarator ParamDecl(DS, ParsedAttributesView::none(),915DeclaratorContext::TemplateParam);916ParseDeclarator(ParamDecl);917if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {918Diag(Tok.getLocation(), diag::err_expected_template_parameter);919return nullptr;920}921922// Recover from misplaced ellipsis.923SourceLocation EllipsisLoc;924if (TryConsumeToken(tok::ellipsis, EllipsisLoc))925DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, ParamDecl);926927// If there is a default value, parse it.928// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before929// we introduce the template parameter into the local scope.930SourceLocation EqualLoc;931ExprResult DefaultArg;932if (TryConsumeToken(tok::equal, EqualLoc)) {933if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {934Diag(Tok.getLocation(), diag::err_stmt_expr_in_default_arg) << 1;935SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);936} else {937// C++ [temp.param]p15:938// When parsing a default template-argument for a non-type939// template-parameter, the first non-nested > is taken as the940// end of the template-parameter-list rather than a greater-than941// operator.942GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);943944// The default argument may declare template parameters, notably945// if it contains a generic lambda, so we need to increase946// the template depth as these parameters would not be instantiated947// at the current level.948TemplateParameterDepthRAII CurTemplateDepthTracker(949TemplateParameterDepth);950++CurTemplateDepthTracker;951EnterExpressionEvaluationContext ConstantEvaluated(952Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);953DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseInitializer());954if (DefaultArg.isInvalid())955SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);956}957}958959// Create the parameter.960return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,961Depth, Position, EqualLoc,962DefaultArg.get());963}964965void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,966SourceLocation CorrectLoc,967bool AlreadyHasEllipsis,968bool IdentifierHasName) {969FixItHint Insertion;970if (!AlreadyHasEllipsis)971Insertion = FixItHint::CreateInsertion(CorrectLoc, "...");972Diag(EllipsisLoc, diag::err_misplaced_ellipsis_in_declaration)973<< FixItHint::CreateRemoval(EllipsisLoc) << Insertion974<< !IdentifierHasName;975}976977void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,978Declarator &D) {979assert(EllipsisLoc.isValid());980bool AlreadyHasEllipsis = D.getEllipsisLoc().isValid();981if (!AlreadyHasEllipsis)982D.setEllipsisLoc(EllipsisLoc);983DiagnoseMisplacedEllipsis(EllipsisLoc, D.getIdentifierLoc(),984AlreadyHasEllipsis, D.hasName());985}986987/// Parses a '>' at the end of a template list.988///989/// If this function encounters '>>', '>>>', '>=', or '>>=', it tries990/// to determine if these tokens were supposed to be a '>' followed by991/// '>', '>>', '>=', or '>='. It emits an appropriate diagnostic if necessary.992///993/// \param RAngleLoc the location of the consumed '>'.994///995/// \param ConsumeLastToken if true, the '>' is consumed.996///997/// \param ObjCGenericList if true, this is the '>' closing an Objective-C998/// type parameter or type argument list, rather than a C++ template parameter999/// or argument list.1000///1001/// \returns true, if current token does not start with '>', false otherwise.1002bool Parser::ParseGreaterThanInTemplateList(SourceLocation LAngleLoc,1003SourceLocation &RAngleLoc,1004bool ConsumeLastToken,1005bool ObjCGenericList) {1006// What will be left once we've consumed the '>'.1007tok::TokenKind RemainingToken;1008const char *ReplacementStr = "> >";1009bool MergeWithNextToken = false;10101011switch (Tok.getKind()) {1012default:1013Diag(getEndOfPreviousToken(), diag::err_expected) << tok::greater;1014Diag(LAngleLoc, diag::note_matching) << tok::less;1015return true;10161017case tok::greater:1018// Determine the location of the '>' token. Only consume this token1019// if the caller asked us to.1020RAngleLoc = Tok.getLocation();1021if (ConsumeLastToken)1022ConsumeToken();1023return false;10241025case tok::greatergreater:1026RemainingToken = tok::greater;1027break;10281029case tok::greatergreatergreater:1030RemainingToken = tok::greatergreater;1031break;10321033case tok::greaterequal:1034RemainingToken = tok::equal;1035ReplacementStr = "> =";10361037// Join two adjacent '=' tokens into one, for cases like:1038// void (*p)() = f<int>;1039// return f<int>==p;1040if (NextToken().is(tok::equal) &&1041areTokensAdjacent(Tok, NextToken())) {1042RemainingToken = tok::equalequal;1043MergeWithNextToken = true;1044}1045break;10461047case tok::greatergreaterequal:1048RemainingToken = tok::greaterequal;1049break;1050}10511052// This template-id is terminated by a token that starts with a '>'.1053// Outside C++11 and Objective-C, this is now error recovery.1054//1055// C++11 allows this when the token is '>>', and in CUDA + C++11 mode, we1056// extend that treatment to also apply to the '>>>' token.1057//1058// Objective-C allows this in its type parameter / argument lists.10591060SourceLocation TokBeforeGreaterLoc = PrevTokLocation;1061SourceLocation TokLoc = Tok.getLocation();1062Token Next = NextToken();10631064// Whether splitting the current token after the '>' would undesirably result1065// in the remaining token pasting with the token after it. This excludes the1066// MergeWithNextToken cases, which we've already handled.1067bool PreventMergeWithNextToken =1068(RemainingToken == tok::greater ||1069RemainingToken == tok::greatergreater) &&1070(Next.isOneOf(tok::greater, tok::greatergreater,1071tok::greatergreatergreater, tok::equal, tok::greaterequal,1072tok::greatergreaterequal, tok::equalequal)) &&1073areTokensAdjacent(Tok, Next);10741075// Diagnose this situation as appropriate.1076if (!ObjCGenericList) {1077// The source range of the replaced token(s).1078CharSourceRange ReplacementRange = CharSourceRange::getCharRange(1079TokLoc, Lexer::AdvanceToTokenCharacter(TokLoc, 2, PP.getSourceManager(),1080getLangOpts()));10811082// A hint to put a space between the '>>'s. In order to make the hint as1083// clear as possible, we include the characters either side of the space in1084// the replacement, rather than just inserting a space at SecondCharLoc.1085FixItHint Hint1 = FixItHint::CreateReplacement(ReplacementRange,1086ReplacementStr);10871088// A hint to put another space after the token, if it would otherwise be1089// lexed differently.1090FixItHint Hint2;1091if (PreventMergeWithNextToken)1092Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");10931094unsigned DiagId = diag::err_two_right_angle_brackets_need_space;1095if (getLangOpts().CPlusPlus11 &&1096(Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))1097DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;1098else if (Tok.is(tok::greaterequal))1099DiagId = diag::err_right_angle_bracket_equal_needs_space;1100Diag(TokLoc, DiagId) << Hint1 << Hint2;1101}11021103// Find the "length" of the resulting '>' token. This is not always 1, as it1104// can contain escaped newlines.1105unsigned GreaterLength = Lexer::getTokenPrefixLength(1106TokLoc, 1, PP.getSourceManager(), getLangOpts());11071108// Annotate the source buffer to indicate that we split the token after the1109// '>'. This allows us to properly find the end of, and extract the spelling1110// of, the '>' token later.1111RAngleLoc = PP.SplitToken(TokLoc, GreaterLength);11121113// Strip the initial '>' from the token.1114bool CachingTokens = PP.IsPreviousCachedToken(Tok);11151116Token Greater = Tok;1117Greater.setLocation(RAngleLoc);1118Greater.setKind(tok::greater);1119Greater.setLength(GreaterLength);11201121unsigned OldLength = Tok.getLength();1122if (MergeWithNextToken) {1123ConsumeToken();1124OldLength += Tok.getLength();1125}11261127Tok.setKind(RemainingToken);1128Tok.setLength(OldLength - GreaterLength);11291130// Split the second token if lexing it normally would lex a different token1131// (eg, the fifth token in 'A<B>>>' should re-lex as '>', not '>>').1132SourceLocation AfterGreaterLoc = TokLoc.getLocWithOffset(GreaterLength);1133if (PreventMergeWithNextToken)1134AfterGreaterLoc = PP.SplitToken(AfterGreaterLoc, Tok.getLength());1135Tok.setLocation(AfterGreaterLoc);11361137// Update the token cache to match what we just did if necessary.1138if (CachingTokens) {1139// If the previous cached token is being merged, delete it.1140if (MergeWithNextToken)1141PP.ReplacePreviousCachedToken({});11421143if (ConsumeLastToken)1144PP.ReplacePreviousCachedToken({Greater, Tok});1145else1146PP.ReplacePreviousCachedToken({Greater});1147}11481149if (ConsumeLastToken) {1150PrevTokLocation = RAngleLoc;1151} else {1152PrevTokLocation = TokBeforeGreaterLoc;1153PP.EnterToken(Tok, /*IsReinject=*/true);1154Tok = Greater;1155}11561157return false;1158}11591160/// Parses a template-id that after the template name has1161/// already been parsed.1162///1163/// This routine takes care of parsing the enclosed template argument1164/// list ('<' template-parameter-list [opt] '>') and placing the1165/// results into a form that can be transferred to semantic analysis.1166///1167/// \param ConsumeLastToken if true, then we will consume the last1168/// token that forms the template-id. Otherwise, we will leave the1169/// last token in the stream (e.g., so that it can be replaced with an1170/// annotation token).1171bool Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken,1172SourceLocation &LAngleLoc,1173TemplateArgList &TemplateArgs,1174SourceLocation &RAngleLoc,1175TemplateTy Template) {1176assert(Tok.is(tok::less) && "Must have already parsed the template-name");11771178// Consume the '<'.1179LAngleLoc = ConsumeToken();11801181// Parse the optional template-argument-list.1182bool Invalid = false;1183{1184GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);1185if (!Tok.isOneOf(tok::greater, tok::greatergreater,1186tok::greatergreatergreater, tok::greaterequal,1187tok::greatergreaterequal))1188Invalid = ParseTemplateArgumentList(TemplateArgs, Template, LAngleLoc);11891190if (Invalid) {1191// Try to find the closing '>'.1192if (getLangOpts().CPlusPlus11)1193SkipUntil(tok::greater, tok::greatergreater,1194tok::greatergreatergreater, StopAtSemi | StopBeforeMatch);1195else1196SkipUntil(tok::greater, StopAtSemi | StopBeforeMatch);1197}1198}11991200return ParseGreaterThanInTemplateList(LAngleLoc, RAngleLoc, ConsumeLastToken,1201/*ObjCGenericList=*/false) ||1202Invalid;1203}12041205/// Replace the tokens that form a simple-template-id with an1206/// annotation token containing the complete template-id.1207///1208/// The first token in the stream must be the name of a template that1209/// is followed by a '<'. This routine will parse the complete1210/// simple-template-id and replace the tokens with a single annotation1211/// token with one of two different kinds: if the template-id names a1212/// type (and \p AllowTypeAnnotation is true), the annotation token is1213/// a type annotation that includes the optional nested-name-specifier1214/// (\p SS). Otherwise, the annotation token is a template-id1215/// annotation that does not include the optional1216/// nested-name-specifier.1217///1218/// \param Template the declaration of the template named by the first1219/// token (an identifier), as returned from \c Action::isTemplateName().1220///1221/// \param TNK the kind of template that \p Template1222/// refers to, as returned from \c Action::isTemplateName().1223///1224/// \param SS if non-NULL, the nested-name-specifier that precedes1225/// this template name.1226///1227/// \param TemplateKWLoc if valid, specifies that this template-id1228/// annotation was preceded by the 'template' keyword and gives the1229/// location of that keyword. If invalid (the default), then this1230/// template-id was not preceded by a 'template' keyword.1231///1232/// \param AllowTypeAnnotation if true (the default), then a1233/// simple-template-id that refers to a class template, template1234/// template parameter, or other template that produces a type will be1235/// replaced with a type annotation token. Otherwise, the1236/// simple-template-id is always replaced with a template-id1237/// annotation token.1238///1239/// \param TypeConstraint if true, then this is actually a type-constraint,1240/// meaning that the template argument list can be omitted (and the template in1241/// question must be a concept).1242///1243/// If an unrecoverable parse error occurs and no annotation token can be1244/// formed, this function returns true.1245///1246bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,1247CXXScopeSpec &SS,1248SourceLocation TemplateKWLoc,1249UnqualifiedId &TemplateName,1250bool AllowTypeAnnotation,1251bool TypeConstraint) {1252assert(getLangOpts().CPlusPlus && "Can only annotate template-ids in C++");1253assert((Tok.is(tok::less) || TypeConstraint) &&1254"Parser isn't at the beginning of a template-id");1255assert(!(TypeConstraint && AllowTypeAnnotation) && "type-constraint can't be "1256"a type annotation");1257assert((!TypeConstraint || TNK == TNK_Concept_template) && "type-constraint "1258"must accompany a concept name");1259assert((Template || TNK == TNK_Non_template) && "missing template name");12601261// Consume the template-name.1262SourceLocation TemplateNameLoc = TemplateName.getSourceRange().getBegin();12631264// Parse the enclosed template argument list.1265SourceLocation LAngleLoc, RAngleLoc;1266TemplateArgList TemplateArgs;1267bool ArgsInvalid = false;1268if (!TypeConstraint || Tok.is(tok::less)) {1269ArgsInvalid = ParseTemplateIdAfterTemplateName(1270false, LAngleLoc, TemplateArgs, RAngleLoc, Template);1271// If we couldn't recover from invalid arguments, don't form an annotation1272// token -- we don't know how much to annotate.1273// FIXME: This can lead to duplicate diagnostics if we retry parsing this1274// template-id in another context. Try to annotate anyway?1275if (RAngleLoc.isInvalid())1276return true;1277}12781279ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs);12801281// Build the annotation token.1282if (TNK == TNK_Type_template && AllowTypeAnnotation) {1283TypeResult Type = ArgsInvalid1284? TypeError()1285: Actions.ActOnTemplateIdType(1286getCurScope(), SS, TemplateKWLoc, Template,1287TemplateName.Identifier, TemplateNameLoc,1288LAngleLoc, TemplateArgsPtr, RAngleLoc);12891290Tok.setKind(tok::annot_typename);1291setTypeAnnotation(Tok, Type);1292if (SS.isNotEmpty())1293Tok.setLocation(SS.getBeginLoc());1294else if (TemplateKWLoc.isValid())1295Tok.setLocation(TemplateKWLoc);1296else1297Tok.setLocation(TemplateNameLoc);1298} else {1299// Build a template-id annotation token that can be processed1300// later.1301Tok.setKind(tok::annot_template_id);13021303const IdentifierInfo *TemplateII =1304TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier1305? TemplateName.Identifier1306: nullptr;13071308OverloadedOperatorKind OpKind =1309TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier1310? OO_None1311: TemplateName.OperatorFunctionId.Operator;13121313TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(1314TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,1315LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid, TemplateIds);13161317Tok.setAnnotationValue(TemplateId);1318if (TemplateKWLoc.isValid())1319Tok.setLocation(TemplateKWLoc);1320else1321Tok.setLocation(TemplateNameLoc);1322}13231324// Common fields for the annotation token1325Tok.setAnnotationEndLoc(RAngleLoc);13261327// In case the tokens were cached, have Preprocessor replace them with the1328// annotation token.1329PP.AnnotateCachedTokens(Tok);1330return false;1331}13321333/// Replaces a template-id annotation token with a type1334/// annotation token.1335///1336/// If there was a failure when forming the type from the template-id,1337/// a type annotation token will still be created, but will have a1338/// NULL type pointer to signify an error.1339///1340/// \param SS The scope specifier appearing before the template-id, if any.1341///1342/// \param AllowImplicitTypename whether this is a context where T::type1343/// denotes a dependent type.1344/// \param IsClassName Is this template-id appearing in a context where we1345/// know it names a class, such as in an elaborated-type-specifier or1346/// base-specifier? ('typename' and 'template' are unneeded and disallowed1347/// in those contexts.)1348void Parser::AnnotateTemplateIdTokenAsType(1349CXXScopeSpec &SS, ImplicitTypenameContext AllowImplicitTypename,1350bool IsClassName) {1351assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");13521353TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1354assert(TemplateId->mightBeType() &&1355"Only works for type and dependent templates");13561357ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),1358TemplateId->NumArgs);13591360TypeResult Type =1361TemplateId->isInvalid()1362? TypeError()1363: Actions.ActOnTemplateIdType(1364getCurScope(), SS, TemplateId->TemplateKWLoc,1365TemplateId->Template, TemplateId->Name,1366TemplateId->TemplateNameLoc, TemplateId->LAngleLoc,1367TemplateArgsPtr, TemplateId->RAngleLoc,1368/*IsCtorOrDtorName=*/false, IsClassName, AllowImplicitTypename);1369// Create the new "type" annotation token.1370Tok.setKind(tok::annot_typename);1371setTypeAnnotation(Tok, Type);1372if (SS.isNotEmpty()) // it was a C++ qualified type name.1373Tok.setLocation(SS.getBeginLoc());1374// End location stays the same13751376// Replace the template-id annotation token, and possible the scope-specifier1377// that precedes it, with the typename annotation token.1378PP.AnnotateCachedTokens(Tok);1379}13801381/// Determine whether the given token can end a template argument.1382static bool isEndOfTemplateArgument(Token Tok) {1383// FIXME: Handle '>>>'.1384return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater,1385tok::greatergreatergreater);1386}13871388/// Parse a C++ template template argument.1389ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {1390if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&1391!Tok.is(tok::annot_cxxscope))1392return ParsedTemplateArgument();13931394// C++0x [temp.arg.template]p1:1395// A template-argument for a template template-parameter shall be the name1396// of a class template or an alias template, expressed as id-expression.1397//1398// We parse an id-expression that refers to a class template or alias1399// template. The grammar we parse is:1400//1401// nested-name-specifier[opt] template[opt] identifier ...[opt]1402//1403// followed by a token that terminates a template argument, such as ',',1404// '>', or (in some cases) '>>'.1405CXXScopeSpec SS; // nested-name-specifier, if present1406ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,1407/*ObjectHasErrors=*/false,1408/*EnteringContext=*/false);14091410ParsedTemplateArgument Result;1411SourceLocation EllipsisLoc;1412if (SS.isSet() && Tok.is(tok::kw_template)) {1413// Parse the optional 'template' keyword following the1414// nested-name-specifier.1415SourceLocation TemplateKWLoc = ConsumeToken();14161417if (Tok.is(tok::identifier)) {1418// We appear to have a dependent template name.1419UnqualifiedId Name;1420Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());1421ConsumeToken(); // the identifier14221423TryConsumeToken(tok::ellipsis, EllipsisLoc);14241425// If the next token signals the end of a template argument, then we have1426// a (possibly-dependent) template name that could be a template template1427// argument.1428TemplateTy Template;1429if (isEndOfTemplateArgument(Tok) &&1430Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc, Name,1431/*ObjectType=*/nullptr,1432/*EnteringContext=*/false, Template))1433Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);1434}1435} else if (Tok.is(tok::identifier)) {1436// We may have a (non-dependent) template name.1437TemplateTy Template;1438UnqualifiedId Name;1439Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());1440ConsumeToken(); // the identifier14411442TryConsumeToken(tok::ellipsis, EllipsisLoc);14431444if (isEndOfTemplateArgument(Tok)) {1445bool MemberOfUnknownSpecialization;1446TemplateNameKind TNK = Actions.isTemplateName(1447getCurScope(), SS,1448/*hasTemplateKeyword=*/false, Name,1449/*ObjectType=*/nullptr,1450/*EnteringContext=*/false, Template, MemberOfUnknownSpecialization);1451if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {1452// We have an id-expression that refers to a class template or1453// (C++0x) alias template.1454Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);1455}1456}1457}14581459// If this is a pack expansion, build it as such.1460if (EllipsisLoc.isValid() && !Result.isInvalid())1461Result = Actions.ActOnPackExpansion(Result, EllipsisLoc);14621463return Result;1464}14651466/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).1467///1468/// template-argument: [C++ 14.2]1469/// constant-expression1470/// type-id1471/// id-expression1472/// braced-init-list [C++26, DR]1473///1474ParsedTemplateArgument Parser::ParseTemplateArgument() {1475// C++ [temp.arg]p2:1476// In a template-argument, an ambiguity between a type-id and an1477// expression is resolved to a type-id, regardless of the form of1478// the corresponding template-parameter.1479//1480// Therefore, we initially try to parse a type-id - and isCXXTypeId might look1481// up and annotate an identifier as an id-expression during disambiguation,1482// so enter the appropriate context for a constant expression template1483// argument before trying to disambiguate.14841485EnterExpressionEvaluationContext EnterConstantEvaluated(1486Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated,1487/*LambdaContextDecl=*/nullptr,1488/*ExprContext=*/Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);1489if (isCXXTypeId(TypeIdAsTemplateArgument)) {1490TypeResult TypeArg = ParseTypeName(1491/*Range=*/nullptr, DeclaratorContext::TemplateArg);1492return Actions.ActOnTemplateTypeArgument(TypeArg);1493}14941495// Try to parse a template template argument.1496{1497TentativeParsingAction TPA(*this);14981499ParsedTemplateArgument TemplateTemplateArgument1500= ParseTemplateTemplateArgument();1501if (!TemplateTemplateArgument.isInvalid()) {1502TPA.Commit();1503return TemplateTemplateArgument;1504}15051506// Revert this tentative parse to parse a non-type template argument.1507TPA.Revert();1508}15091510// Parse a non-type template argument.1511ExprResult ExprArg;1512SourceLocation Loc = Tok.getLocation();1513if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))1514ExprArg = ParseBraceInitializer();1515else1516ExprArg = ParseConstantExpressionInExprEvalContext(MaybeTypeCast);1517if (ExprArg.isInvalid() || !ExprArg.get()) {1518return ParsedTemplateArgument();1519}15201521return ParsedTemplateArgument(ParsedTemplateArgument::NonType,1522ExprArg.get(), Loc);1523}15241525/// ParseTemplateArgumentList - Parse a C++ template-argument-list1526/// (C++ [temp.names]). Returns true if there was an error.1527///1528/// template-argument-list: [C++ 14.2]1529/// template-argument1530/// template-argument-list ',' template-argument1531///1532/// \param Template is only used for code completion, and may be null.1533bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,1534TemplateTy Template,1535SourceLocation OpenLoc) {15361537ColonProtectionRAIIObject ColonProtection(*this, false);15381539auto RunSignatureHelp = [&] {1540if (!Template)1541return QualType();1542CalledSignatureHelp = true;1543return Actions.CodeCompletion().ProduceTemplateArgumentSignatureHelp(1544Template, TemplateArgs, OpenLoc);1545};15461547do {1548PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);1549ParsedTemplateArgument Arg = ParseTemplateArgument();1550SourceLocation EllipsisLoc;1551if (TryConsumeToken(tok::ellipsis, EllipsisLoc))1552Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);15531554if (Arg.isInvalid()) {1555if (PP.isCodeCompletionReached() && !CalledSignatureHelp)1556RunSignatureHelp();1557return true;1558}15591560// Save this template argument.1561TemplateArgs.push_back(Arg);15621563// If the next token is a comma, consume it and keep reading1564// arguments.1565} while (TryConsumeToken(tok::comma));15661567return false;1568}15691570/// Parse a C++ explicit template instantiation1571/// (C++ [temp.explicit]).1572///1573/// explicit-instantiation:1574/// 'extern' [opt] 'template' declaration1575///1576/// Note that the 'extern' is a GNU extension and C++11 feature.1577Parser::DeclGroupPtrTy Parser::ParseExplicitInstantiation(1578DeclaratorContext Context, SourceLocation ExternLoc,1579SourceLocation TemplateLoc, SourceLocation &DeclEnd,1580ParsedAttributes &AccessAttrs, AccessSpecifier AS) {1581// This isn't really required here.1582ParsingDeclRAIIObject1583ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);1584ParsedTemplateInfo TemplateInfo(ExternLoc, TemplateLoc);1585return ParseDeclarationAfterTemplate(1586Context, TemplateInfo, ParsingTemplateParams, DeclEnd, AccessAttrs, AS);1587}15881589SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {1590if (TemplateParams)1591return getTemplateParamsRange(TemplateParams->data(),1592TemplateParams->size());15931594SourceRange R(TemplateLoc);1595if (ExternLoc.isValid())1596R.setBegin(ExternLoc);1597return R;1598}15991600void Parser::LateTemplateParserCallback(void *P, LateParsedTemplate &LPT) {1601((Parser *)P)->ParseLateTemplatedFuncDef(LPT);1602}16031604/// Late parse a C++ function template in Microsoft mode.1605void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {1606if (!LPT.D)1607return;16081609// Destroy TemplateIdAnnotations when we're done, if possible.1610DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);16111612// Get the FunctionDecl.1613FunctionDecl *FunD = LPT.D->getAsFunction();1614// Track template parameter depth.1615TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);16161617// To restore the context after late parsing.1618Sema::ContextRAII GlobalSavedContext(1619Actions, Actions.Context.getTranslationUnitDecl());16201621MultiParseScope Scopes(*this);16221623// Get the list of DeclContexts to reenter.1624SmallVector<DeclContext*, 4> DeclContextsToReenter;1625for (DeclContext *DC = FunD; DC && !DC->isTranslationUnit();1626DC = DC->getLexicalParent())1627DeclContextsToReenter.push_back(DC);16281629// Reenter scopes from outermost to innermost.1630for (DeclContext *DC : reverse(DeclContextsToReenter)) {1631CurTemplateDepthTracker.addDepth(1632ReenterTemplateScopes(Scopes, cast<Decl>(DC)));1633Scopes.Enter(Scope::DeclScope);1634// We'll reenter the function context itself below.1635if (DC != FunD)1636Actions.PushDeclContext(Actions.getCurScope(), DC);1637}16381639// Parsing should occur with empty FP pragma stack and FP options used in the1640// point of the template definition.1641Sema::FpPragmaStackSaveRAII SavedStack(Actions);1642Actions.resetFPOptions(LPT.FPO);16431644assert(!LPT.Toks.empty() && "Empty body!");16451646// Append the current token at the end of the new token stream so that it1647// doesn't get lost.1648LPT.Toks.push_back(Tok);1649PP.EnterTokenStream(LPT.Toks, true, /*IsReinject*/true);16501651// Consume the previously pushed token.1652ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);1653assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try) &&1654"Inline method not starting with '{', ':' or 'try'");16551656// Parse the method body. Function body parsing code is similar enough1657// to be re-used for method bodies as well.1658ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |1659Scope::CompoundStmtScope);16601661// Recreate the containing function DeclContext.1662Sema::ContextRAII FunctionSavedContext(Actions, FunD->getLexicalParent());16631664Actions.ActOnStartOfFunctionDef(getCurScope(), FunD);16651666if (Tok.is(tok::kw_try)) {1667ParseFunctionTryBlock(LPT.D, FnScope);1668} else {1669if (Tok.is(tok::colon))1670ParseConstructorInitializer(LPT.D);1671else1672Actions.ActOnDefaultCtorInitializers(LPT.D);16731674if (Tok.is(tok::l_brace)) {1675assert((!isa<FunctionTemplateDecl>(LPT.D) ||1676cast<FunctionTemplateDecl>(LPT.D)1677->getTemplateParameters()1678->getDepth() == TemplateParameterDepth - 1) &&1679"TemplateParameterDepth should be greater than the depth of "1680"current template being instantiated!");1681ParseFunctionStatementBody(LPT.D, FnScope);1682Actions.UnmarkAsLateParsedTemplate(FunD);1683} else1684Actions.ActOnFinishFunctionBody(LPT.D, nullptr);1685}1686}16871688/// Lex a delayed template function for late parsing.1689void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {1690tok::TokenKind kind = Tok.getKind();1691if (!ConsumeAndStoreFunctionPrologue(Toks)) {1692// Consume everything up to (and including) the matching right brace.1693ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);1694}16951696// If we're in a function-try-block, we need to store all the catch blocks.1697if (kind == tok::kw_try) {1698while (Tok.is(tok::kw_catch)) {1699ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);1700ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);1701}1702}1703}17041705/// We've parsed something that could plausibly be intended to be a template1706/// name (\p LHS) followed by a '<' token, and the following code can't possibly1707/// be an expression. Determine if this is likely to be a template-id and if so,1708/// diagnose it.1709bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) {1710TentativeParsingAction TPA(*this);1711// FIXME: We could look at the token sequence in a lot more detail here.1712if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater,1713StopAtSemi | StopBeforeMatch)) {1714TPA.Commit();17151716SourceLocation Greater;1717ParseGreaterThanInTemplateList(Less, Greater, true, false);1718Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS,1719Less, Greater);1720return true;1721}17221723// There's no matching '>' token, this probably isn't supposed to be1724// interpreted as a template-id. Parse it as an (ill-formed) comparison.1725TPA.Revert();1726return false;1727}17281729void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) {1730assert(Tok.is(tok::less) && "not at a potential angle bracket");17311732bool DependentTemplateName = false;1733if (!Actions.mightBeIntendedToBeTemplateName(PotentialTemplateName,1734DependentTemplateName))1735return;17361737// OK, this might be a name that the user intended to be parsed as a1738// template-name, followed by a '<' token. Check for some easy cases.17391740// If we have potential_template<>, then it's supposed to be a template-name.1741if (NextToken().is(tok::greater) ||1742(getLangOpts().CPlusPlus11 &&1743NextToken().isOneOf(tok::greatergreater, tok::greatergreatergreater))) {1744SourceLocation Less = ConsumeToken();1745SourceLocation Greater;1746ParseGreaterThanInTemplateList(Less, Greater, true, false);1747Actions.diagnoseExprIntendedAsTemplateName(1748getCurScope(), PotentialTemplateName, Less, Greater);1749// FIXME: Perform error recovery.1750PotentialTemplateName = ExprError();1751return;1752}17531754// If we have 'potential_template<type-id', assume it's supposed to be a1755// template-name if there's a matching '>' later on.1756{1757// FIXME: Avoid the tentative parse when NextToken() can't begin a type.1758TentativeParsingAction TPA(*this);1759SourceLocation Less = ConsumeToken();1760if (isTypeIdUnambiguously() &&1761diagnoseUnknownTemplateId(PotentialTemplateName, Less)) {1762TPA.Commit();1763// FIXME: Perform error recovery.1764PotentialTemplateName = ExprError();1765return;1766}1767TPA.Revert();1768}17691770// Otherwise, remember that we saw this in case we see a potentially-matching1771// '>' token later on.1772AngleBracketTracker::Priority Priority =1773(DependentTemplateName ? AngleBracketTracker::DependentName1774: AngleBracketTracker::PotentialTypo) |1775(Tok.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess1776: AngleBracketTracker::NoSpaceBeforeLess);1777AngleBrackets.add(*this, PotentialTemplateName.get(), Tok.getLocation(),1778Priority);1779}17801781bool Parser::checkPotentialAngleBracketDelimiter(1782const AngleBracketTracker::Loc &LAngle, const Token &OpToken) {1783// If a comma in an expression context is followed by a type that can be a1784// template argument and cannot be an expression, then this is ill-formed,1785// but might be intended to be part of a template-id.1786if (OpToken.is(tok::comma) && isTypeIdUnambiguously() &&1787diagnoseUnknownTemplateId(LAngle.TemplateName, LAngle.LessLoc)) {1788AngleBrackets.clear(*this);1789return true;1790}17911792// If a context that looks like a template-id is followed by '()', then1793// this is ill-formed, but might be intended to be a template-id1794// followed by '()'.1795if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) &&1796NextToken().is(tok::r_paren)) {1797Actions.diagnoseExprIntendedAsTemplateName(1798getCurScope(), LAngle.TemplateName, LAngle.LessLoc,1799OpToken.getLocation());1800AngleBrackets.clear(*this);1801return true;1802}18031804// After a '>' (etc), we're no longer potentially in a construct that's1805// intended to be treated as a template-id.1806if (OpToken.is(tok::greater) ||1807(getLangOpts().CPlusPlus11 &&1808OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater)))1809AngleBrackets.clear(*this);1810return false;1811}181218131814