diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-27 23:10:48 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-27 23:10:48 +0000 |
commit | 333489bba35d91e4ddb101f441087177c492d090 (patch) | |
tree | 6b658646aed7c601a730536e09816cecc7ff0c65 /clang/lib/Parse/Parser.cpp | |
parent | 669f1d0b0b7ab0fd05f4cf672eab6dbe3f358953 (diff) | |
download | bcm5719-llvm-333489bba35d91e4ddb101f441087177c492d090.tar.gz bcm5719-llvm-333489bba35d91e4ddb101f441087177c492d090.zip |
Initial implementation of parsing, semantic analysis, and template
instantiation for C++ typename-specifiers such as
typename T::type
The parsing of typename-specifiers is relatively easy thanks to
annotation tokens. When we see the "typename", we parse the
typename-specifier and produce a typename annotation token. There are
only a few places where we need to handle this. We currently parse the
typename-specifier form that terminates in an identifier, but not the
simple-template-id form, e.g.,
typename T::template apply<U, V>
Parsing of nested-name-specifiers has a similar problem, since at this
point we don't have any representation of a class template
specialization whose template-name is unknown.
Semantic analysis is only partially complete, with some support for
template instantiation that works for simple examples.
llvm-svn: 67875
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 5ce8b3dbcd8..7f2c5d307b7 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -795,10 +795,42 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. bool Parser::TryAnnotateTypeOrScopeToken() { - assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) && + assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) + || Tok.is(tok::kw_typename)) && "Cannot be a type or scope token!"); - // FIXME: Implement template-ids + if (Tok.is(tok::kw_typename)) { + // Parse a C++ typename-specifier, e.g., "typename T::type". + // + // typename-specifier: + // 'typename' '::' [opt] nested-name-specifier identifier + // 'typename' '::' [opt] nested-name-specifier template [opt] + // simple-template-id [TODO] + SourceLocation TypenameLoc = ConsumeToken(); + CXXScopeSpec SS; + bool HadNestedNameSpecifier = ParseOptionalCXXScopeSpecifier(SS); + if (!HadNestedNameSpecifier) { + Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); + return false; + } + + TypeResult Ty; + if (Tok.is(tok::identifier)) { + // FIXME: check whether the next token is '<', first! + Ty = Actions.ActOnTypenameType(TypenameLoc, SS, *Tok.getIdentifierInfo(), + Tok.getLocation()); + // FIXME: better error recovery! + Tok.setKind(tok::annot_typename); + Tok.setAnnotationValue(Ty.get()); + Tok.setAnnotationEndLoc(Tok.getLocation()); + Tok.setLocation(TypenameLoc); + PP.AnnotateCachedTokens(Tok); + return true; + } + + return false; + } + CXXScopeSpec SS; if (getLang().CPlusPlus) ParseOptionalCXXScopeSpecifier(SS); @@ -841,7 +873,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { // template-id, is not part of the annotation. Fall through to // push that token back into the stream and complete the C++ scope // specifier annotation. - } + } if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId |