diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-12-18 19:37:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-12-18 19:37:40 +0000 |
commit | 55ad91fecb076c4afadb2cf0591e1bc94db6df0b (patch) | |
tree | 6ee2558608a2372f2d130e18adc9b7fa3f0b45d7 /clang/lib/Parse/ParseTemplate.cpp | |
parent | 9443f0ea5e233948c36b180b8551987df0fbdd45 (diff) | |
download | bcm5719-llvm-55ad91fecb076c4afadb2cf0591e1bc94db6df0b.tar.gz bcm5719-llvm-55ad91fecb076c4afadb2cf0591e1bc94db6df0b.zip |
Ultrasimplistic sketch for the parsing of C++ template-ids. This won't
become useful or correct until we (1) parse template arguments
correctly, (2) have some way to turn template-ids into types,
declarators, etc., and (3) have a real representation of templates.
llvm-svn: 61208
Diffstat (limited to 'clang/lib/Parse/ParseTemplate.cpp')
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 108 |
1 files changed, 106 insertions, 2 deletions
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index d21dc4aa6d6..5d0c4b5350a 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -46,8 +46,19 @@ Parser::DeclTy *Parser::ParseTemplateDeclaration(unsigned Context) { // Try to parse the template parameters, and the declaration if // successful. DeclTy *TemplateDecl = 0; - if(ParseTemplateParameters(0)) + if (Tok.is(tok::less) && NextToken().is(tok::greater)) { + // This is a template specialization. Just consume the angle + // brackets and parse the declaration or function definition that + // follows. + // FIXME: Record somehow that we're in an explicit specialization. + ConsumeToken(); + ConsumeToken(); + TemplateParmScope.Exit(); TemplateDecl = ParseDeclarationOrFunctionDefinition(); + } else { + if(ParseTemplateParameters(0)) + TemplateDecl = ParseDeclarationOrFunctionDefinition(); + } return TemplateDecl; } @@ -243,7 +254,7 @@ Parser::DeclTy* Parser::ParseTemplateTemplateParameter() { /// ParseNonTypeTemplateParameter - Handle the parsing of non-type /// template parameters (e.g., in "template<int Size> class array;"). - +/// /// template-parameter: /// ... /// parameter-declaration @@ -289,3 +300,96 @@ Parser::DeclTy* Parser::ParseNonTypeTemplateParameter() { return Param; } + +/// AnnotateTemplateIdToken - The current token is an identifier that +/// refers to the template declaration Template, and is followed by a +/// '<'. Turn this template-id into a template-id annotation token. +void Parser::AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS) { + assert(getLang().CPlusPlus && "Can only annotate template-ids in C++"); + assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) && + "Parser isn't at the beginning of a template-id"); + + // Consume the template-name. + SourceLocation TemplateNameLoc = ConsumeToken(); + + // Consume the '<'. + SourceLocation LAngleLoc = ConsumeToken(); + + // Parse the optional template-argument-list. + TemplateArgList TemplateArgs; + if (Tok.isNot(tok::greater) && ParseTemplateArgumentList(TemplateArgs)) { + // Try to find the closing '>'. + SkipUntil(tok::greater, true, true); + + // FIXME: What's our recovery strategy for failed template-argument-lists? + return; + } + + if (Tok.isNot(tok::greater)) + return; + + // Determine the location of the '>'. We won't actually consume this + // token, because we'll be replacing it with the template-id. + SourceLocation RAngleLoc = Tok.getLocation(); + + Tok.setKind(tok::annot_template_id); + Tok.setAnnotationEndLoc(RAngleLoc); + Tok.setLocation(TemplateNameLoc); + if (SS && SS->isNotEmpty()) + Tok.setLocation(SS->getBeginLoc()); + + TemplateIdAnnotation *TemplateId + = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) + + sizeof(TemplateArgTy*) * TemplateArgs.size()); + TemplateId->TemplateNameLoc = TemplateNameLoc; + TemplateId->Template = Template; + TemplateId->LAngleLoc = LAngleLoc; + TemplateId->NumArgs = TemplateArgs.size(); + TemplateArgTy **Args = (TemplateArgTy**)(TemplateId + 1); + for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) + Args[Arg] = TemplateArgs[Arg]; + Tok.setAnnotationValue(TemplateId); + + // In case the tokens were cached, have Preprocessor replace them with the + // annotation token. + PP.AnnotateCachedTokens(Tok); +} + +/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]). +/// +/// template-argument: [C++ 14.2] +/// assignment-expression +/// type-id +/// id-expression +Parser::OwningTemplateArgResult Parser::ParseTemplateArgument() { + // FIXME: Implement this! + return TemplateArgError(); +} + +/// ParseTemplateArgumentList - Parse a C++ template-argument-list +/// (C++ [temp.names]). Returns true if there was an error. +/// +/// template-argument-list: [C++ 14.2] +/// template-argument +/// template-argument-list ',' template-argument +bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { + while (true) { + OwningTemplateArgResult Arg = ParseTemplateArgument(); + if (Arg.isInvalid()) { + SkipUntil(tok::comma, tok::greater, true, true); + return true; + } + else + TemplateArgs.push_back(Arg.release()); + + // If the next token is a comma, consume it and keep reading + // arguments. + if (Tok.isNot(tok::comma)) break; + + // Consume the comma. + ConsumeToken(); + } + + return Tok.isNot(tok::greater); +} + |