summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-27 23:10:48 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-27 23:10:48 +0000
commit333489bba35d91e4ddb101f441087177c492d090 (patch)
tree6b658646aed7c601a730536e09816cecc7ff0c65 /clang/lib/Parse/Parser.cpp
parent669f1d0b0b7ab0fd05f4cf672eab6dbe3f358953 (diff)
downloadbcm5719-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.cpp38
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
OpenPOWER on IntegriCloud