diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp | 97 |
1 files changed, 72 insertions, 25 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index dfb4785..8387c88 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -196,12 +196,18 @@ Parser::ParseSingleDeclarationAfterTemplate( return 0; } + ParsedAttributesWithRange prefixAttrs; + MaybeParseCXX0XAttributes(prefixAttrs); + + if (Tok.is(tok::kw_using)) + return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd, + prefixAttrs); + // Parse the declaration specifiers, stealing the accumulated // diagnostics from the template parameters. ParsingDeclSpec DS(DiagsFromTParams); - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) - DS.AddAttributes(ParseCXX0XAttributes().AttrList); + DS.takeAttributesFrom(prefixAttrs); ParseDeclarationSpecifiers(DS, TemplateInfo, AS, getDeclSpecContextFromDeclaratorContext(Context)); @@ -240,7 +246,7 @@ Parser::ParseSingleDeclarationAfterTemplate( // Eat the semi colon after the declaration. ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); - DS.complete(ThisDecl); + DeclaratorInfo.complete(ThisDecl); return ThisDecl; } @@ -337,7 +343,7 @@ Parser::ParseTemplateParameterList(unsigned Depth, // subsumed by whatever goes on in ParseTemplateParameter. // TODO: This could match >>, and it would be nice to avoid those // silly errors with template <vec<T>>. - // Diag(Tok.getLocation(), diag::err_expected_comma_greater); + Diag(Tok.getLocation(), diag::err_expected_comma_greater); SkipUntil(tok::greater, true, true); return false; } @@ -415,12 +421,14 @@ bool Parser::isStartOfTemplateTypeParameter() { /// parameter-declaration /// /// type-parameter: (see below) -/// 'class' ...[opt][C++0x] identifier[opt] +/// 'class' ...[opt] identifier[opt] /// 'class' identifier[opt] '=' type-id -/// 'typename' ...[opt][C++0x] identifier[opt] +/// 'typename' ...[opt] identifier[opt] /// 'typename' identifier[opt] '=' type-id -/// 'template' ...[opt][C++0x] '<' template-parameter-list '>' 'class' identifier[opt] -/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression +/// 'template' '<' template-parameter-list '>' +/// 'class' ...[opt] identifier[opt] +/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] +/// = id-expression Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) { if (isStartOfTemplateTypeParameter()) return ParseTypeParameter(Depth, Position); @@ -459,7 +467,7 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { EllipsisLoc = ConsumeToken(); if (!getLang().CPlusPlus0x) - Diag(EllipsisLoc, diag::err_variadic_templates); + Diag(EllipsisLoc, diag::ext_variadic_templates); } // Grab the template parameter name (if given) @@ -496,8 +504,10 @@ Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { /// template parameters. /// /// type-parameter: [C++ temp.param] -/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] -/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression +/// 'template' '<' template-parameter-list '>' 'class' +/// ...[opt] identifier[opt] +/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] +/// = id-expression Decl * Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { assert(Tok.is(tok::kw_template) && "Expected 'template' keyword"); @@ -521,8 +531,17 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { << PP.getSpelling(Tok); return 0; } - SourceLocation ClassLoc = ConsumeToken(); + ConsumeToken(); + // Parse the ellipsis, if given. + SourceLocation EllipsisLoc; + if (Tok.is(tok::ellipsis)) { + EllipsisLoc = ConsumeToken(); + + if (!getLang().CPlusPlus0x) + Diag(EllipsisLoc, diag::ext_variadic_templates); + } + // Get the identifier, if given. SourceLocation NameLoc; IdentifierInfo* ParamName = 0; @@ -540,7 +559,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { TemplateParamsTy *ParamList = Actions.ActOnTemplateParameterList(Depth, SourceLocation(), TemplateLoc, LAngleLoc, - &TemplateParams[0], + TemplateParams.data(), TemplateParams.size(), RAngleLoc); @@ -563,9 +582,9 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { } return Actions.ActOnTemplateTemplateParameter(getCurScope(), TemplateLoc, - ParamList, ParamName, - NameLoc, Depth, Position, - EqualLoc, DefaultArg); + ParamList, EllipsisLoc, + ParamName, NameLoc, Depth, + Position, EqualLoc, DefaultArg); } /// ParseNonTypeTemplateParameter - Handle the parsing of non-type @@ -576,8 +595,6 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { /// parameter-declaration Decl * Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { - SourceLocation StartLoc = Tok.getLocation(); - // Parse the declaration-specifiers (i.e., the type). // FIXME: The type should probably be restricted in some way... Not all // declarators (parts of declarators?) are accepted for parameters. @@ -658,7 +675,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, bool Invalid = false; { GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - if (Tok.isNot(tok::greater)) + if (Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater)) Invalid = ParseTemplateArgumentList(TemplateArgs); if (Invalid) { @@ -888,7 +905,7 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { // We parse an id-expression that refers to a class template or template // alias. The grammar we parse is: // - // nested-name-specifier[opt] template[opt] identifier + // nested-name-specifier[opt] template[opt] identifier ...[opt] // // followed by a token that terminates a template argument, such as ',', // '>', or (in some cases) '>>'. @@ -896,6 +913,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + ParsedTemplateArgument Result; + SourceLocation EllipsisLoc; if (SS.isSet() && Tok.is(tok::kw_template)) { // Parse the optional 'template' keyword following the // nested-name-specifier. @@ -907,6 +926,10 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier + // Parse the ellipsis. + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + // If the next token signals the end of a template argument, // then we have a dependent template name that could be a template // template argument. @@ -917,7 +940,7 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { /*ObjectType=*/ ParsedType(), /*EnteringContext=*/false, Template)) - return ParsedTemplateArgument(SS, Template, Name.StartLocation); + Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); } } else if (Tok.is(tok::identifier)) { // We may have a (non-dependent) template name. @@ -926,6 +949,10 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); // the identifier + // Parse the ellipsis. + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + if (isEndOfTemplateArgument(Tok)) { bool MemberOfUnknownSpecialization; TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS, @@ -938,13 +965,16 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) { // We have an id-expression that refers to a class template or // (C++0x) template alias. - return ParsedTemplateArgument(SS, Template, Name.StartLocation); + Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); } } } - // We don't have a template template argument. - return ParsedTemplateArgument(); + // If this is a pack expansion, build it as such. + if (EllipsisLoc.isValid() && !Result.isInvalid()) + Result = Actions.ActOnPackExpansion(Result, EllipsisLoc); + + return Result; } /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]). @@ -962,7 +992,8 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // Therefore, we initially try to parse a type-id. if (isCXXTypeId(TypeIdAsTemplateArgument)) { SourceLocation Loc = Tok.getLocation(); - TypeResult TypeArg = ParseTypeName(); + TypeResult TypeArg = ParseTypeName(/*Range=*/0, + Declarator::TemplateTypeArgContext); if (TypeArg.isInvalid()) return ParsedTemplateArgument(); @@ -1037,6 +1068,11 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { while (true) { ParsedTemplateArgument Arg = ParseTemplateArgument(); + if (Tok.is(tok::ellipsis)) { + SourceLocation EllipsisLoc = ConsumeToken(); + Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc); + } + if (Arg.isInvalid()) { SkipUntil(tok::comma, tok::greater, true, true); return true; @@ -1075,3 +1111,14 @@ Decl *Parser::ParseExplicitInstantiation(SourceLocation ExternLoc, ParsingTemplateParams, DeclEnd, AS_none); } + +SourceRange Parser::ParsedTemplateInfo::getSourceRange() const { + if (TemplateParams) + return getTemplateParamsRange(TemplateParams->data(), + TemplateParams->size()); + + SourceRange R(TemplateLoc); + if (ExternLoc.isValid()) + R.setBegin(ExternLoc); + return R; +} |