diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-17 23:15:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-17 23:15:12 +0000 |
commit | 67a65640918dc52e362181099bfc9044313a99e6 (patch) | |
tree | f1addf579c5492a610c1e1982990cc1ac9410ce0 /clang/lib/Parse/ParseDeclCXX.cpp | |
parent | 79d10a2f4321b5acd275c7145ff5c56f3429fb10 (diff) | |
download | bcm5719-llvm-67a65640918dc52e362181099bfc9044313a99e6.tar.gz bcm5719-llvm-67a65640918dc52e362181099bfc9044313a99e6.zip |
Implement basic parsing and semantic analysis for explicit
specialization of class templates, e.g.,
template<typename T> class X;
template<> class X<int> { /* blah */ };
Each specialization is a different *Decl node (naturally), and can
have different members. We keep track of forward declarations and
definitions as for other class/struct/union types.
This is only the basic framework: we still have to deal with checking
the template headers properly, improving recovery when there are
failures, handling nested name specifiers, etc.
llvm-svn: 64848
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d6b83f3fb2d..e36bc40bac3 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -310,17 +310,69 @@ 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)) Diag(Tok, diag::err_expected_ident); } - // Parse the (optional) class name. - // FIXME: Alternatively, parse a simple-template-id. + + // 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; if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); 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); + + 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; + } + } } // There are three options here. If we have 'struct foo;', then @@ -347,7 +399,23 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, // Create the tag portion of the class or class template. DeclTy *TagOrTempDecl; - if (TemplateParams && TK != Action::TK_Reference) + if (Template && 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. + TagOrTempDecl + = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK, + StartLoc, SS, /*Range*/ + Template, NameLoc, + LAngleLoc, TemplateArgsPtr, + &TemplateArgLocations[0], + RAngleLoc, Attr, + Action::MultiTemplateParamsArg(Actions, + TemplateParams? &(*TemplateParams)[0] : 0, + TemplateParams? TemplateParams->size() : 0)); + + else if (TemplateParams && TK != Action::TK_Reference) TagOrTempDecl = Actions.ActOnClassTemplate(CurScope, TagType, TK, StartLoc, SS, Name, NameLoc, Attr, Action::MultiTemplateParamsArg(Actions, |