blob: f5e8cdc25d388f4723b5ec21c9e43f862c72cd7b [file] [log] [blame]
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +00001//===--- PPCaching.cpp - Handle caching lexed tokens ----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements pieces of the Preprocessor interface that manage the
11// caching of lexed tokens.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Lex/Preprocessor.h"
16using namespace clang;
17
James Dennett4a4f72d2013-11-27 01:27:40 +000018// EnableBacktrackAtThisPos - From the point that this method is called, and
19// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
20// keeps track of the lexed tokens so that a subsequent Backtrack() call will
21// make the Preprocessor re-lex the same tokens.
22//
23// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
24// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
25// be combined with the EnableBacktrackAtThisPos calls in reverse order.
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000026void Preprocessor::EnableBacktrackAtThisPos() {
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000027 BacktrackPositions.push_back(CachedLexPos);
28 EnterCachingLexMode();
29}
Argyrios Kyrtzidisa65490c2008-08-22 21:27:50 +000030
James Dennett4a4f72d2013-11-27 01:27:40 +000031// Disable the last EnableBacktrackAtThisPos call.
Argyrios Kyrtzidis75b34532008-08-24 12:29:43 +000032void Preprocessor::CommitBacktrackedTokens() {
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000033 assert(!BacktrackPositions.empty()
34 && "EnableBacktrackAtThisPos was not called!");
35 BacktrackPositions.pop_back();
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000036}
37
Alex Lorenz24a1bed2017-02-24 17:45:16 +000038Preprocessor::CachedTokensRange Preprocessor::LastCachedTokenRange() {
39 assert(isBacktrackEnabled());
40 auto PrevCachedLexPos = BacktrackPositions.back();
41 return CachedTokensRange{PrevCachedLexPos, CachedLexPos};
42}
43
44void Preprocessor::EraseCachedTokens(CachedTokensRange TokenRange) {
45 assert(TokenRange.Begin <= TokenRange.End);
46 if (CachedLexPos == TokenRange.Begin && TokenRange.Begin != TokenRange.End) {
47 // We have backtracked to the start of the token range as we want to consume
48 // them again. Erase the tokens only after consuming then.
49 assert(!CachedTokenRangeToErase);
50 CachedTokenRangeToErase = TokenRange;
51 return;
52 }
53 // The cached tokens were committed, so they should be erased now.
54 assert(TokenRange.End == CachedLexPos);
55 CachedTokens.erase(CachedTokens.begin() + TokenRange.Begin,
56 CachedTokens.begin() + TokenRange.End);
57 CachedLexPos = TokenRange.Begin;
58 ExitCachingLexMode();
59}
60
James Dennett4a4f72d2013-11-27 01:27:40 +000061// Make Preprocessor re-lex the tokens that were lexed since
62// EnableBacktrackAtThisPos() was previously called.
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000063void Preprocessor::Backtrack() {
64 assert(!BacktrackPositions.empty()
65 && "EnableBacktrackAtThisPos was not called!");
66 CachedLexPos = BacktrackPositions.back();
67 BacktrackPositions.pop_back();
Douglas Gregor8d76cca2012-01-04 06:20:15 +000068 recomputeCurLexerKind();
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000069}
Argyrios Kyrtzidisa65490c2008-08-22 21:27:50 +000070
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000071void Preprocessor::CachingLex(Token &Result) {
Argyrios Kyrtzidisc2924de2010-07-12 18:49:30 +000072 if (!InCachingLexMode())
73 return;
74
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000075 if (CachedLexPos < CachedTokens.size()) {
76 Result = CachedTokens[CachedLexPos++];
Alex Lorenz24a1bed2017-02-24 17:45:16 +000077 // Erase the some of the cached tokens after they are consumed when
78 // asked to do so.
79 if (CachedTokenRangeToErase &&
80 CachedTokenRangeToErase->End == CachedLexPos) {
81 EraseCachedTokens(*CachedTokenRangeToErase);
82 CachedTokenRangeToErase = None;
83 }
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000084 return;
85 }
86
87 ExitCachingLexMode();
Argyrios Kyrtzidisd1d239f2010-07-12 21:41:41 +000088 Lex(Result);
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000089
Argyrios Kyrtzidis4a1049c2012-04-04 02:57:01 +000090 if (isBacktrackEnabled()) {
91 // Cache the lexed token.
92 EnterCachingLexMode();
93 CachedTokens.push_back(Result);
94 ++CachedLexPos;
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000095 return;
96 }
97
Argyrios Kyrtzidis4a1049c2012-04-04 02:57:01 +000098 if (CachedLexPos < CachedTokens.size()) {
99 EnterCachingLexMode();
100 } else {
101 // All cached tokens were consumed.
102 CachedTokens.clear();
103 CachedLexPos = 0;
104 }
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +0000105}
106
107void Preprocessor::EnterCachingLexMode() {
108 if (InCachingLexMode())
109 return;
110
Ted Kremenek50b4f482008-11-12 22:21:57 +0000111 PushIncludeMacroStack();
Douglas Gregor8d76cca2012-01-04 06:20:15 +0000112 CurLexerKind = CLK_CachingLexer;
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +0000113}
114
115
116const Token &Preprocessor::PeekAhead(unsigned N) {
117 assert(CachedLexPos + N > CachedTokens.size() && "Confused caching.");
118 ExitCachingLexMode();
Erik Verbruggene4fd6522016-10-26 13:06:13 +0000119 for (size_t C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +0000120 CachedTokens.push_back(Token());
121 Lex(CachedTokens.back());
122 }
123 EnterCachingLexMode();
124 return CachedTokens.back();
125}
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000126
127void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
Chris Lattner5a7971e2009-01-26 19:29:26 +0000128 assert(Tok.isAnnotation() && "Expected annotation token");
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000129 assert(CachedLexPos != 0 && "Expected to have some cached tokens");
Sebastian Redlb0e3e1b2010-02-08 19:35:18 +0000130 assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc()
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000131 && "The annotation should be until the most recent cached token");
132
133 // Start from the end of the cached tokens list and look for the token
134 // that is the beginning of the annotation token.
135 for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
136 CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
137 if (AnnotBegin->getLocation() == Tok.getLocation()) {
Reid Klecknerae818502016-10-20 20:53:20 +0000138 assert((BacktrackPositions.empty() || BacktrackPositions.back() <= i) &&
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000139 "The backtrack pos points inside the annotated tokens!");
140 // Replace the cached tokens with the single annotation token.
Nuno Lopesbd2cd922009-07-26 16:36:45 +0000141 if (i < CachedLexPos)
142 CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos);
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000143 *AnnotBegin = Tok;
144 CachedLexPos = i;
145 return;
146 }
Chandler Carruthc4399b12013-11-27 01:40:12 +0000147 }
148}
Bruno Cardoso Lopes428a5aa2016-01-31 00:47:51 +0000149
150bool Preprocessor::IsPreviousCachedToken(const Token &Tok) const {
151 // There's currently no cached token...
152 if (!CachedLexPos)
153 return false;
154
155 const Token LastCachedTok = CachedTokens[CachedLexPos - 1];
156 if (LastCachedTok.getKind() != Tok.getKind())
157 return false;
158
159 int RelOffset = 0;
160 if ((!getSourceManager().isInSameSLocAddrSpace(
161 Tok.getLocation(), getLastCachedTokenLocation(), &RelOffset)) ||
162 RelOffset)
163 return false;
164
165 return true;
166}
167
168void Preprocessor::ReplacePreviousCachedToken(ArrayRef<Token> NewToks) {
169 assert(CachedLexPos != 0 && "Expected to have some cached tokens");
170 CachedTokens.insert(CachedTokens.begin() + CachedLexPos - 1, NewToks.begin(),
171 NewToks.end());
172 CachedTokens.erase(CachedTokens.begin() + CachedLexPos - 1 + NewToks.size());
173 CachedLexPos += NewToks.size() - 1;
174}