diff options
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); + } +} |