diff options
Diffstat (limited to 'lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 197 |
1 files changed, 98 insertions, 99 deletions
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 2e0411e..f146669 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" -#include "RAIIObjectsForParser.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ASTConsumer.h" using namespace clang; /// \brief Parse a template declaration, explicit instantiation, or @@ -172,16 +172,6 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, /// \brief Parse a single declaration that declares a template, /// template specialization, or explicit instantiation of a template. /// -/// \param TemplateParams if non-NULL, the template parameter lists -/// that preceded this declaration. In this case, the declaration is a -/// template declaration, out-of-line definition of a template, or an -/// explicit template specialization. When NULL, the declaration is an -/// explicit template instantiation. -/// -/// \param TemplateLoc when TemplateParams is NULL, the location of -/// the 'template' keyword that indicates that we have an explicit -/// template instantiation. -/// /// \param DeclEnd will receive the source location of the last token /// within this declaration. /// @@ -208,7 +198,7 @@ Parser::ParseSingleDeclarationAfterTemplate( } ParsedAttributesWithRange prefixAttrs(AttrFactory); - MaybeParseCXX0XAttributes(prefixAttrs); + MaybeParseCXX11Attributes(prefixAttrs); if (Tok.is(tok::kw_using)) return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd, @@ -218,22 +208,27 @@ Parser::ParseSingleDeclarationAfterTemplate( // the template parameters. ParsingDeclSpec DS(*this, &DiagsFromTParams); - // Move the attributes from the prefix into the DS. - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) - ProhibitAttributes(prefixAttrs); - else - DS.takeAttributesFrom(prefixAttrs); - ParseDeclarationSpecifiers(DS, TemplateInfo, AS, getDeclSpecContextFromDeclaratorContext(Context)); if (Tok.is(tok::semi)) { + ProhibitAttributes(prefixAttrs); DeclEnd = ConsumeToken(); - Decl *Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + Decl *Decl = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS, DS, + TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams + : MultiTemplateParamsArg(), + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation); DS.complete(Decl); return Decl; } + // Move the attributes from the prefix into the DS. + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + ProhibitAttributes(prefixAttrs); + else + DS.takeAttributesFrom(prefixAttrs); + // Parse the declarator. ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context); ParseDeclarator(DeclaratorInfo); @@ -250,27 +245,6 @@ Parser::ParseSingleDeclarationAfterTemplate( if (DeclaratorInfo.isFunctionDeclarator()) MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); - // If we have a declaration or declarator list, handle it. - if (isDeclarationAfterDeclarator()) { - // Parse this declaration. - Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, - TemplateInfo); - - if (Tok.is(tok::comma)) { - Diag(Tok, diag::err_multiple_template_declarators) - << (int)TemplateInfo.Kind; - SkipUntil(tok::semi, true, false); - return ThisDecl; - } - - // Eat the semi colon after the declaration. - ExpectAndConsumeSemi(diag::err_expected_semi_declaration); - if (LateParsedAttrs.size() > 0) - ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); - DeclaratorInfo.complete(ThisDecl); - return ThisDecl; - } - if (DeclaratorInfo.isFunctionDeclarator() && isStartOfFunctionDefinition(DeclaratorInfo)) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -285,12 +259,23 @@ Parser::ParseSingleDeclarationAfterTemplate( &LateParsedAttrs); } - if (DeclaratorInfo.isFunctionDeclarator()) - Diag(Tok, diag::err_expected_fn_body); - else - Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); - SkipUntil(tok::semi); - return 0; + // Parse this declaration. + Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, + TemplateInfo); + + if (Tok.is(tok::comma)) { + Diag(Tok, diag::err_multiple_template_declarators) + << (int)TemplateInfo.Kind; + SkipUntil(tok::semi, true, false); + return ThisDecl; + } + + // Eat the semi colon after the declaration. + ExpectAndConsumeSemi(diag::err_expected_semi_declaration); + if (LateParsedAttrs.size() > 0) + ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); + DeclaratorInfo.complete(ThisDecl); + return ThisDecl; } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in @@ -357,7 +342,7 @@ Parser::ParseTemplateParameterList(unsigned Depth, SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true); } - // Did we find a comma or the end of the template parmeter list? + // Did we find a comma or the end of the template parameter list? if (Tok.is(tok::comma)) { ConsumeToken(); } else if (Tok.is(tok::greater) || Tok.is(tok::greatergreater)) { @@ -491,7 +476,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { EllipsisLoc = ConsumeToken(); Diag(EllipsisLoc, - getLangOpts().CPlusPlus0x + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); } @@ -578,7 +563,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { EllipsisLoc = ConsumeToken(); Diag(EllipsisLoc, - getLangOpts().CPlusPlus0x + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); } @@ -675,52 +660,17 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { DefaultArg.take()); } -/// \brief Parses a template-id that after the template name has -/// already been parsed. -/// -/// This routine takes care of parsing the enclosed template argument -/// list ('<' template-parameter-list [opt] '>') and placing the -/// results into a form that can be transferred to semantic analysis. +/// \brief Parses a '>' at the end of a template list. /// -/// \param Template the template declaration produced by isTemplateName -/// -/// \param TemplateNameLoc the source location of the template name +/// If this function encounters '>>', '>>>', '>=', or '>>=', it tries +/// to determine if these tokens were supposed to be a '>' followed by +/// '>', '>>', '>=', or '>='. It emits an appropriate diagnostic if necessary. /// -/// \param SS if non-NULL, the nested-name-specifier preceding the -/// template name. +/// \param RAngleLoc the location of the consumed '>'. /// -/// \param ConsumeLastToken if true, then we will consume the last -/// token that forms the template-id. Otherwise, we will leave the -/// last token in the stream (e.g., so that it can be replaced with an -/// annotation token). -bool -Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, - SourceLocation TemplateNameLoc, - const CXXScopeSpec &SS, - bool ConsumeLastToken, - SourceLocation &LAngleLoc, - TemplateArgList &TemplateArgs, - SourceLocation &RAngleLoc) { - assert(Tok.is(tok::less) && "Must have already parsed the template-name"); - - // Consume the '<'. - LAngleLoc = ConsumeToken(); - - // Parse the optional template-argument-list. - bool Invalid = false; - { - GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) - Invalid = ParseTemplateArgumentList(TemplateArgs); - - if (Invalid) { - // Try to find the closing '>'. - SkipUntil(tok::greater, true, !ConsumeLastToken); - - return true; - } - } - +/// \param ConsumeLastToken if true, the '>' is not consumed. +bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, + bool ConsumeLastToken) { // What will be left once we've consumed the '>'. tok::TokenKind RemainingToken; const char *ReplacementStr = "> >"; @@ -788,7 +738,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; - if (getLangOpts().CPlusPlus0x && Tok.is(tok::greatergreater)) + if (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)) DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) DiagId = diag::err_right_angle_bracket_equal_needs_space; @@ -819,10 +769,59 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, Tok.setLength(1); Tok.setLocation(RAngleLoc); } - return false; } + +/// \brief Parses a template-id that after the template name has +/// already been parsed. +/// +/// This routine takes care of parsing the enclosed template argument +/// list ('<' template-parameter-list [opt] '>') and placing the +/// results into a form that can be transferred to semantic analysis. +/// +/// \param Template the template declaration produced by isTemplateName +/// +/// \param TemplateNameLoc the source location of the template name +/// +/// \param SS if non-NULL, the nested-name-specifier preceding the +/// template name. +/// +/// \param ConsumeLastToken if true, then we will consume the last +/// token that forms the template-id. Otherwise, we will leave the +/// last token in the stream (e.g., so that it can be replaced with an +/// annotation token). +bool +Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, + SourceLocation TemplateNameLoc, + const CXXScopeSpec &SS, + bool ConsumeLastToken, + SourceLocation &LAngleLoc, + TemplateArgList &TemplateArgs, + SourceLocation &RAngleLoc) { + assert(Tok.is(tok::less) && "Must have already parsed the template-name"); + + // Consume the '<'. + LAngleLoc = ConsumeToken(); + + // Parse the optional template-argument-list. + bool Invalid = false; + { + GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); + if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) + Invalid = ParseTemplateArgumentList(TemplateArgs); + + if (Invalid) { + // Try to find the closing '>'. + SkipUntil(tok::greater, true, !ConsumeLastToken); + + return true; + } + } + + return ParseGreaterThanInTemplateList(RAngleLoc, ConsumeLastToken); +} + /// \brief Replace the tokens that form a simple-template-id with an /// annotation token containing the complete template-id. /// @@ -839,7 +838,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, /// \param Template the declaration of the template named by the first /// token (an identifier), as returned from \c Action::isTemplateName(). /// -/// \param TemplateNameKind the kind of template that \p Template +/// \param TNK the kind of template that \p Template /// refers to, as returned from \c Action::isTemplateName(). /// /// \param SS if non-NULL, the nested-name-specifier that precedes @@ -1201,7 +1200,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { /// explicit-instantiation: /// 'extern' [opt] 'template' declaration /// -/// Note that the 'extern' is a GNU extension and C++0x feature. +/// Note that the 'extern' is a GNU extension and C++11 feature. Decl *Parser::ParseExplicitInstantiation(unsigned Context, SourceLocation ExternLoc, SourceLocation TemplateLoc, @@ -1306,7 +1305,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false); // Consume the previously pushed token. - ConsumeAnyToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Inline method not starting with '{', ':' or 'try'"); |