diff options
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 105 |
1 files changed, 40 insertions, 65 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index e36bc40bac..3ef3f93fdf 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -309,75 +309,42 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, // Parse the (optional) nested-name-specifier. CXXScopeSpec SS; - if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) { - // FIXME: can we get a class template specialization or - // template-id token here? - if (Tok.isNot(tok::identifier)) + if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) Diag(Tok, diag::err_expected_ident); - } - - - // These variables encode the simple-template-id that we might end - // up parsing below. We don't translate this into a type - // automatically because (1) we want to create a separate - // declaration for each specialization, and (2) we want to retain - // more information about source locations that types provide. - DeclTy *Template = 0; - SourceLocation LAngleLoc, RAngleLoc; - TemplateArgList TemplateArgs; - TemplateArgIsTypeList TemplateArgIsType; - TemplateArgLocationList TemplateArgLocations; - ASTTemplateArgsPtr TemplateArgsPtr(Actions, 0, 0, 0); - // Parse the (optional) class name or simple-template-id. IdentifierInfo *Name = 0; SourceLocation NameLoc; + TemplateIdAnnotation *TemplateId = 0; if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); + } else if (Tok.is(tok::annot_template_id)) { + TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); + NameLoc = ConsumeToken(); - if (Tok.is(tok::less)) { - // This is a simple-template-id. - Action::TemplateNameKind TNK - = Actions.isTemplateName(*Name, CurScope, Template, &SS); - - bool Invalid = false; - - // Parse the enclosed template argument list. - if (TNK != Action::TNK_Non_template) - Invalid = ParseTemplateIdAfterTemplateName(Template, NameLoc, - &SS, true, LAngleLoc, - TemplateArgs, - TemplateArgIsType, - TemplateArgLocations, - RAngleLoc); + if (TemplateId->Kind != TNK_Class_template) { + // The template-name in the simple-template-id refers to + // something other than a class template. Give an appropriate + // error message and skip to the ';'. + SourceRange Range(NameLoc); + if (SS.isNotEmpty()) + Range.setBegin(SS.getBeginLoc()); + + Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template) + << Name << static_cast<int>(TemplateId->Kind) << Range; - TemplateArgsPtr.reset(&TemplateArgs[0], &TemplateArgIsType[0], - TemplateArgs.size()); - - if (TNK != Action::TNK_Class_template) { - // The template-name in the simple-template-id refers to - // something other than a class template. Give an appropriate - // error message and skip to the ';'. - SourceRange Range(NameLoc); - if (SS.isNotEmpty()) - Range.setBegin(SS.getBeginLoc()); - else if (!Invalid) - - Diag(LAngleLoc, diag::err_template_spec_syntax_non_template) - << Name << static_cast<int>(TNK) << Range; - - DS.SetTypeSpecError(); - SkipUntil(tok::semi, false, true); - return; - } + DS.SetTypeSpecError(); + SkipUntil(tok::semi, false, true); + TemplateId->Destroy(); + return; } } // There are three options here. If we have 'struct foo;', then // this is a forward declaration. If we have 'struct foo {...' or - // 'struct fo :...' then this is a definition. Otherwise we have + // 'struct foo :...' then this is a definition. Otherwise we have // something like 'struct foo xyz', a reference. Action::TagKind TK; if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))) @@ -387,35 +354,43 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, else TK = Action::TK_Reference; - if (!Name && TK != Action::TK_Definition) { + if (!Name && !TemplateId && TK != Action::TK_Definition) { // We have a declaration or reference to an anonymous class. Diag(StartLoc, diag::err_anon_type_definition) << DeclSpec::getSpecifierName(TagType); // Skip the rest of this declarator, up until the comma or semicolon. SkipUntil(tok::comma, true); + + if (TemplateId) + TemplateId->Destroy(); return; } // Create the tag portion of the class or class template. DeclTy *TagOrTempDecl; - if (Template && TK != Action::TK_Reference) + if (TemplateId && TK != Action::TK_Reference) { // Explicit specialization or class template partial // specialization. Let semantic analysis decide. - - // FIXME: we want a source range covering the simple-template-id. + ASTTemplateArgsPtr TemplateArgsPtr(Actions, + TemplateId->getTemplateArgs(), + TemplateId->getTemplateArgIsType(), + TemplateId->NumArgs); TagOrTempDecl = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK, - StartLoc, SS, /*Range*/ - Template, NameLoc, - LAngleLoc, TemplateArgsPtr, - &TemplateArgLocations[0], - RAngleLoc, Attr, + StartLoc, SS, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->getTemplateArgLocations(), + TemplateId->RAngleLoc, + Attr, Action::MultiTemplateParamsArg(Actions, TemplateParams? &(*TemplateParams)[0] : 0, TemplateParams? TemplateParams->size() : 0)); - - else if (TemplateParams && TK != Action::TK_Reference) + TemplateId->Destroy(); + } else if (TemplateParams && TK != Action::TK_Reference) TagOrTempDecl = Actions.ActOnClassTemplate(CurScope, TagType, TK, StartLoc, SS, Name, NameLoc, Attr, Action::MultiTemplateParamsArg(Actions, |