summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-02-17 23:15:12 +0000
committerDouglas Gregor <dgregor@apple.com>2009-02-17 23:15:12 +0000
commit67a65640918dc52e362181099bfc9044313a99e6 (patch)
treef1addf579c5492a610c1e1982990cc1ac9410ce0 /clang/lib/Parse/ParseDeclCXX.cpp
parent79d10a2f4321b5acd275c7145ff5c56f3429fb10 (diff)
downloadbcm5719-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.cpp74
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,
OpenPOWER on IntegriCloud