diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-11-08 16:45:02 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-11-08 16:45:02 +0000 |
commit | eb83ecde1a822b1c38cd060a85a08c1ac9f82cf8 (patch) | |
tree | 88e967a9d871a2ea4e6d9272c20fbc057543d2c4 /lib/Parse/Parser.cpp | |
parent | 3604e3895ecd850291b518e5a82246c888ce9d0f (diff) |
Implement support for C++ nested-name-specifiers ('foo::bar::x') in the Parser side.
No Sema functionality change, just the signatures of the Action/Sema methods.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58913 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r-- | lib/Parse/Parser.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 625da6c281..ee4cd7b554 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -706,3 +706,74 @@ Parser::ExprResult Parser::ParseSimpleAsm() { return Result; } +/// TryAnnotateTypeOrScopeToken - If the current token position is on a +/// typename (possibly qualified in C++) or a C++ scope specifier not followed +/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens +/// with a single annotation token representing the typename or C++ scope +/// respectively. +/// This simplifies handling of C++ scope specifiers and allows efficient +/// backtracking without the need to re-parse and resolve nested-names and +/// typenames. +void Parser::TryAnnotateTypeOrScopeToken() { + if (Tok.is(tok::annot_qualtypename) || Tok.is(tok::annot_cxxscope)) + return; + + CXXScopeSpec SS; + if (isTokenCXXScopeSpecifier()) + ParseCXXScopeSpecifier(SS); + + if (Tok.is(tok::identifier)) { + TypeTy *Ty = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope, &SS); + if (Ty) { + // This is a typename. Replace the current token in-place with an + // annotation type token. + Tok.setKind(tok::annot_qualtypename); + Tok.setAnnotationValue(Ty); + Tok.setAnnotationEndLoc(Tok.getLocation()); + if (SS.isNotEmpty()) // it was a C++ qualified type name. + Tok.setLocation(SS.getBeginLoc()); + + // In case the tokens were cached, have Preprocessor replace them with the + // annotation token. + PP.AnnotateCachedTokens(Tok); + return; + } + } + + if (SS.isNotEmpty()) { + // A C++ scope specifier that isn't followed by a typename. + // Push the current token back into the token stream and use an annotation + // scope token for current token. + PP.EnterToken(Tok); + Tok.setKind(tok::annot_cxxscope); + Tok.setAnnotationValue(SS.getScopeRep()); + Tok.setAnnotationRange(SS.getRange()); + + // In case the tokens were cached, have Preprocessor replace them with the + // annotation token. + PP.AnnotateCachedTokens(Tok); + } +} + +/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only +/// annotates C++ scope specifiers. +void Parser::TryAnnotateScopeToken() { + if (Tok.is(tok::annot_cxxscope)) + return; + + if (isTokenCXXScopeSpecifier()) { + CXXScopeSpec SS; + ParseCXXScopeSpecifier(SS); + + // Push the current token back into the token stream and use an annotation + // scope token for current token. + PP.EnterToken(Tok); + Tok.setKind(tok::annot_cxxscope); + Tok.setAnnotationValue(SS.getScopeRep()); + Tok.setAnnotationRange(SS.getRange()); + + // In case the tokens were cached, have Preprocessor replace them with the + // annotation token. + PP.AnnotateCachedTokens(Tok); + } +} |