From 08b2c3743a29a2dddcf72e95f747760e213cdde7 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 19 Nov 2008 15:22:16 +0000 Subject: [PATCH] Fix this: With this snippet: void f(a::b); An assert is hit: Assertion failed: CachedTokens[CachedLexPos-1].getLocation() == Tok.getAnnotationEndLoc() && "The annotation should be until the most recent cached token", file ..\..\lib\Lex\PPCaching.cpp, line 98 Introduce Preprocessor::RevertCachedTokens that reverts a specific number of tokens when backtracking is enabled. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59636 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/Preprocessor.h | 14 ++++++++++++++ lib/Parse/Parser.cpp | 18 ++++++++++++------ test/SemaCXX/nested-name-spec.cpp | 3 +++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 9af53bf494..4d31be4ecf 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -369,6 +369,20 @@ public: return PeekAhead(N+1); } + /// RevertCachedTokens - When backtracking is enabled and tokens are cached, + /// this allows to revert a specific number of tokens. + /// Note that the number of tokens being reverted should be up to the last + /// backtrack position, not more. + void RevertCachedTokens(unsigned N) { + assert(isBacktrackEnabled() && + "Should only be called when tokens are cached for backtracking"); + assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back()) + && "Should revert tokens up to the last backtrack position, not more"); + assert(signed(CachedLexPos) - signed(N) >= 0 && + "Corrupted backtrack positions ?"); + CachedLexPos -= N; + } + /// EnterToken - Enters a token in the token stream to be lexed next. If /// BackTrack() is called afterwards, the token will remain at the insertion /// point. diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 86526cc158..861609ce75 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -731,9 +731,12 @@ void Parser::TryAnnotateTypeOrScopeToken() { 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); + // Push the current token back into the token stream (or revert it if it is + // cached) and use an annotation scope token for current token. + if (PP.isBacktrackEnabled()) + PP.RevertCachedTokens(1); + else + PP.EnterToken(Tok); Tok.setKind(tok::annot_cxxscope); Tok.setAnnotationValue(SS.getScopeRep()); Tok.setAnnotationRange(SS.getRange()); @@ -754,9 +757,12 @@ void Parser::TryAnnotateScopeToken() { 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); + // Push the current token back into the token stream (or revert it if it is + // cached) and use an annotation scope token for current token. + if (PP.isBacktrackEnabled()) + PP.RevertCachedTokens(1); + else + PP.EnterToken(Tok); Tok.setKind(tok::annot_cxxscope); Tok.setAnnotationValue(SS.getScopeRep()); Tok.setAnnotationRange(SS.getRange()); diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index cf0500dffe..b22d8dc3d4 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -63,3 +63,6 @@ void f3() { { typedef A::C A; A::ax = 0; } // expected-error {{no member named 'ax'}} { typedef A::C A; A::cx = 0; } } + +// make sure the following doesn't hit any asserts +void f4(undef::C); // expected-error {{use of undeclared identifier 'undef'}} // expected-error {{expected ')'}} expected-error {{to match this '('}} // expected-error {{variable has incomplete type 'void'}} -- 2.40.0