| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | #include "clang/Lex/Preprocessor.h" |
| 15 | using namespace clang; |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | void Preprocessor::EnableBacktrackAtThisPos() { |
| 26 | BacktrackPositions.push_back(CachedLexPos); |
| 27 | EnterCachingLexMode(); |
| 28 | } |
| 29 | |
| 30 | |
| 31 | void Preprocessor::CommitBacktrackedTokens() { |
| 32 | (0) . __assert_fail ("!BacktrackPositions.empty() && \"EnableBacktrackAtThisPos was not called!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 33, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!BacktrackPositions.empty() |
| 33 | (0) . __assert_fail ("!BacktrackPositions.empty() && \"EnableBacktrackAtThisPos was not called!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 33, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "EnableBacktrackAtThisPos was not called!"); |
| 34 | BacktrackPositions.pop_back(); |
| 35 | } |
| 36 | |
| 37 | Preprocessor::CachedTokensRange Preprocessor::LastCachedTokenRange() { |
| 38 | assert(isBacktrackEnabled()); |
| 39 | auto PrevCachedLexPos = BacktrackPositions.back(); |
| 40 | return CachedTokensRange{PrevCachedLexPos, CachedLexPos}; |
| 41 | } |
| 42 | |
| 43 | void Preprocessor::EraseCachedTokens(CachedTokensRange TokenRange) { |
| 44 | assert(TokenRange.Begin <= TokenRange.End); |
| 45 | if (CachedLexPos == TokenRange.Begin && TokenRange.Begin != TokenRange.End) { |
| 46 | |
| 47 | |
| 48 | assert(!CachedTokenRangeToErase); |
| 49 | CachedTokenRangeToErase = TokenRange; |
| 50 | return; |
| 51 | } |
| 52 | |
| 53 | assert(TokenRange.End == CachedLexPos); |
| 54 | CachedTokens.erase(CachedTokens.begin() + TokenRange.Begin, |
| 55 | CachedTokens.begin() + TokenRange.End); |
| 56 | CachedLexPos = TokenRange.Begin; |
| 57 | ExitCachingLexMode(); |
| 58 | } |
| 59 | |
| 60 | |
| 61 | |
| 62 | void Preprocessor::Backtrack() { |
| 63 | (0) . __assert_fail ("!BacktrackPositions.empty() && \"EnableBacktrackAtThisPos was not called!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 64, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!BacktrackPositions.empty() |
| 64 | (0) . __assert_fail ("!BacktrackPositions.empty() && \"EnableBacktrackAtThisPos was not called!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 64, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "EnableBacktrackAtThisPos was not called!"); |
| 65 | CachedLexPos = BacktrackPositions.back(); |
| 66 | BacktrackPositions.pop_back(); |
| 67 | recomputeCurLexerKind(); |
| 68 | } |
| 69 | |
| 70 | void Preprocessor::CachingLex(Token &Result) { |
| 71 | if (!InCachingLexMode()) |
| 72 | return; |
| 73 | |
| 74 | if (CachedLexPos < CachedTokens.size()) { |
| 75 | Result = CachedTokens[CachedLexPos++]; |
| 76 | |
| 77 | |
| 78 | if (CachedTokenRangeToErase && |
| 79 | CachedTokenRangeToErase->End == CachedLexPos) { |
| 80 | EraseCachedTokens(*CachedTokenRangeToErase); |
| 81 | CachedTokenRangeToErase = None; |
| 82 | } |
| 83 | return; |
| 84 | } |
| 85 | |
| 86 | ExitCachingLexMode(); |
| 87 | Lex(Result); |
| 88 | |
| 89 | if (isBacktrackEnabled()) { |
| 90 | |
| 91 | EnterCachingLexMode(); |
| 92 | CachedTokens.push_back(Result); |
| 93 | ++CachedLexPos; |
| 94 | return; |
| 95 | } |
| 96 | |
| 97 | if (CachedLexPos < CachedTokens.size()) { |
| 98 | EnterCachingLexMode(); |
| 99 | } else { |
| 100 | |
| 101 | CachedTokens.clear(); |
| 102 | CachedLexPos = 0; |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | void Preprocessor::EnterCachingLexMode() { |
| 107 | if (InCachingLexMode()) { |
| 108 | (0) . __assert_fail ("CurLexerKind == CLK_CachingLexer && \"Unexpected lexer kind\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 108, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurLexerKind == CLK_CachingLexer && "Unexpected lexer kind"); |
| 109 | return; |
| 110 | } |
| 111 | |
| 112 | PushIncludeMacroStack(); |
| 113 | CurLexerKind = CLK_CachingLexer; |
| 114 | } |
| 115 | |
| 116 | |
| 117 | const Token &Preprocessor::PeekAhead(unsigned N) { |
| 118 | (0) . __assert_fail ("CachedLexPos + N > CachedTokens.size() && \"Confused caching.\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 118, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CachedLexPos + N > CachedTokens.size() && "Confused caching."); |
| 119 | ExitCachingLexMode(); |
| 120 | for (size_t C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) { |
| 121 | CachedTokens.push_back(Token()); |
| 122 | Lex(CachedTokens.back()); |
| 123 | } |
| 124 | EnterCachingLexMode(); |
| 125 | return CachedTokens.back(); |
| 126 | } |
| 127 | |
| 128 | void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) { |
| 129 | (0) . __assert_fail ("Tok.isAnnotation() && \"Expected annotation token\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 129, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Tok.isAnnotation() && "Expected annotation token"); |
| 130 | (0) . __assert_fail ("CachedLexPos != 0 && \"Expected to have some cached tokens\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 130, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CachedLexPos != 0 && "Expected to have some cached tokens"); |
| 131 | (0) . __assert_fail ("CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() && \"The annotation should be until the most recent cached token\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 132, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() |
| 132 | (0) . __assert_fail ("CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() && \"The annotation should be until the most recent cached token\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 132, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "The annotation should be until the most recent cached token"); |
| 133 | |
| 134 | |
| 135 | |
| 136 | for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) { |
| 137 | CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1; |
| 138 | if (AnnotBegin->getLocation() == Tok.getLocation()) { |
| 139 | (0) . __assert_fail ("(BacktrackPositions.empty() || BacktrackPositions.back() <= i) && \"The backtrack pos points inside the annotated tokens!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 140, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((BacktrackPositions.empty() || BacktrackPositions.back() <= i) && |
| 140 | (0) . __assert_fail ("(BacktrackPositions.empty() || BacktrackPositions.back() <= i) && \"The backtrack pos points inside the annotated tokens!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 140, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "The backtrack pos points inside the annotated tokens!"); |
| 141 | |
| 142 | if (i < CachedLexPos) |
| 143 | CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos); |
| 144 | *AnnotBegin = Tok; |
| 145 | CachedLexPos = i; |
| 146 | return; |
| 147 | } |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | bool Preprocessor::IsPreviousCachedToken(const Token &Tok) const { |
| 152 | |
| 153 | if (!CachedLexPos) |
| 154 | return false; |
| 155 | |
| 156 | const Token LastCachedTok = CachedTokens[CachedLexPos - 1]; |
| 157 | if (LastCachedTok.getKind() != Tok.getKind()) |
| 158 | return false; |
| 159 | |
| 160 | int RelOffset = 0; |
| 161 | if ((!getSourceManager().isInSameSLocAddrSpace( |
| 162 | Tok.getLocation(), getLastCachedTokenLocation(), &RelOffset)) || |
| 163 | RelOffset) |
| 164 | return false; |
| 165 | |
| 166 | return true; |
| 167 | } |
| 168 | |
| 169 | void Preprocessor::ReplacePreviousCachedToken(ArrayRef<Token> NewToks) { |
| 170 | (0) . __assert_fail ("CachedLexPos != 0 && \"Expected to have some cached tokens\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPCaching.cpp", 170, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CachedLexPos != 0 && "Expected to have some cached tokens"); |
| 171 | CachedTokens.insert(CachedTokens.begin() + CachedLexPos - 1, NewToks.begin(), |
| 172 | NewToks.end()); |
| 173 | CachedTokens.erase(CachedTokens.begin() + CachedLexPos - 1 + NewToks.size()); |
| 174 | CachedLexPos += NewToks.size() - 1; |
| 175 | } |
| 176 | |