clang 23.0.0git
PPCaching.cpp
Go to the documentation of this file.
1//===--- PPCaching.cpp - Handle caching lexed tokens ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements pieces of the Preprocessor interface that manage the
10// caching of lexed tokens.
11//
12//===----------------------------------------------------------------------===//
13
15using namespace clang;
16
17std::pair<Preprocessor::CachedTokensTy::size_type, bool>
18Preprocessor::LastBacktrackPos() {
19 assert(isBacktrackEnabled());
20 auto BacktrackPos = BacktrackPositions.back();
21 bool Unannotated =
22 static_cast<CachedTokensTy::difference_type>(BacktrackPos) < 0;
23 return {Unannotated ? ~BacktrackPos : BacktrackPos, Unannotated};
24}
25
26// EnableBacktrackAtThisPos - From the point that this method is called, and
27// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
28// keeps track of the lexed tokens so that a subsequent Backtrack() call will
29// make the Preprocessor re-lex the same tokens.
30//
31// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
32// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
33// be combined with the EnableBacktrackAtThisPos calls in reverse order.
35 assert(LexLevel == 0 && "cannot use lookahead while lexing");
36 BacktrackPositions.push_back(Unannotated ? ~CachedLexPos : CachedLexPos);
37 if (Unannotated)
38 UnannotatedBacktrackTokens.emplace_back(CachedTokens, CachedTokens.size());
39 EnterCachingLexMode();
40}
41
42Preprocessor::CachedTokensTy Preprocessor::PopUnannotatedBacktrackTokens() {
43 assert(isUnannotatedBacktrackEnabled() && "missing unannotated tokens?");
44 auto [UnannotatedTokens, NumCachedToks] =
45 std::move(UnannotatedBacktrackTokens.back());
46 UnannotatedBacktrackTokens.pop_back();
47 // If another unannotated backtrack is active, propagate any tokens that were
48 // lexed (not cached) since EnableBacktrackAtThisPos was last called.
50 UnannotatedBacktrackTokens.back().first.append(
51 UnannotatedTokens.begin() + NumCachedToks, UnannotatedTokens.end());
52 return std::move(UnannotatedTokens);
53}
54
55// Disable the last EnableBacktrackAtThisPos call.
57 assert(isBacktrackEnabled() && "EnableBacktrackAtThisPos was not called!");
58 auto [BacktrackPos, Unannotated] = LastBacktrackPos();
59 BacktrackPositions.pop_back();
60 if (Unannotated)
61 PopUnannotatedBacktrackTokens();
62}
63
64// Make Preprocessor re-lex the tokens that were lexed since
65// EnableBacktrackAtThisPos() was previously called.
67 assert(isBacktrackEnabled() && "EnableBacktrackAtThisPos was not called!");
68 auto [BacktrackPos, Unannotated] = LastBacktrackPos();
69 BacktrackPositions.pop_back();
70 CachedLexPos = BacktrackPos;
71 if (Unannotated)
72 CachedTokens = PopUnannotatedBacktrackTokens();
74}
75
76void Preprocessor::CachingLex(Token &Result) {
77 if (!InCachingLexMode())
78 return;
79
80 // The assert in EnterCachingLexMode should prevent this from happening.
81 assert(LexLevel == 1 &&
82 "should not use token caching within the preprocessor");
83
84 if (CachedLexPos < CachedTokens.size()) {
85 Result = CachedTokens[CachedLexPos++];
87 return;
88 }
89
90 ExitCachingLexMode();
91 Lex(Result);
92
93 if (isBacktrackEnabled()) {
94 // Cache the lexed token.
95 EnterCachingLexModeUnchecked();
96 CachedTokens.push_back(Result);
97 ++CachedLexPos;
99 UnannotatedBacktrackTokens.back().first.push_back(Result);
100 return;
101 }
102
103 if (CachedLexPos < CachedTokens.size()) {
104 EnterCachingLexModeUnchecked();
105 } else {
106 // All cached tokens were consumed.
107 CachedTokens.clear();
108 CachedLexPos = 0;
109 }
110}
111
112void Preprocessor::EnterCachingLexMode() {
113 // The caching layer sits on top of all the other lexers, so it's incorrect
114 // to cache tokens while inside a nested lex action. The cached tokens would
115 // be retained after returning to the enclosing lex action and, at best,
116 // would appear at the wrong position in the token stream.
117 assert(LexLevel == 0 &&
118 "entered caching lex mode while lexing something else");
119
120 if (InCachingLexMode())
121 return;
122
123 EnterCachingLexModeUnchecked();
124}
125
126void Preprocessor::EnterCachingLexModeUnchecked() {
127 assert(!InCachingLexMode() && "already in caching lex mode");
128 PushIncludeMacroStack();
129 CurLexerCallback = CLK_CachingLexer;
130}
131
132
133const Token &Preprocessor::PeekAhead(unsigned N) {
134 assert(CachedLexPos + N > CachedTokens.size() && "Confused caching.");
135 ExitCachingLexMode();
136 for (size_t C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
137 CachedTokens.push_back(Token());
138 Lex(CachedTokens.back());
140 UnannotatedBacktrackTokens.back().first.push_back(CachedTokens.back());
141 }
142 EnterCachingLexMode();
143 return CachedTokens.back();
144}
145
146void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
147 assert(Tok.isAnnotation() && "Expected annotation token");
148 assert(CachedLexPos != 0 && "Expected to have some cached tokens");
149 assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc()
150 && "The annotation should be until the most recent cached token");
151
152 // Start from the end of the cached tokens list and look for the token
153 // that is the beginning of the annotation token.
154 for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
155 CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
156 if (AnnotBegin->getLocation() == Tok.getLocation()) {
157 assert((!isBacktrackEnabled() || LastBacktrackPos().first <= i) &&
158 "The backtrack pos points inside the annotated tokens!");
159 // Replace the cached tokens with the single annotation token.
160 if (i < CachedLexPos)
161 CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos);
162 *AnnotBegin = Tok;
163 CachedLexPos = i;
164 return;
165 }
166 }
167}
168
170 // There's currently no cached token...
171 if (!CachedLexPos)
172 return false;
173
174 const Token LastCachedTok = CachedTokens[CachedLexPos - 1];
175 if (LastCachedTok.getKind() != Tok.getKind())
176 return false;
177
178 SourceLocation::IntTy RelOffset = 0;
179 if ((!getSourceManager().isInSameSLocAddrSpace(
180 Tok.getLocation(), getLastCachedTokenLocation(), &RelOffset)) ||
181 RelOffset)
182 return false;
183
184 return true;
185}
186
188 assert(CachedLexPos != 0 && "Expected to have some cached tokens");
189 CachedTokens.insert(CachedTokens.begin() + CachedLexPos - 1, NewToks.begin(),
190 NewToks.end());
191 CachedTokens.erase(CachedTokens.begin() + CachedLexPos - 1 + NewToks.size());
192 CachedLexPos += NewToks.size() - 1;
193}
Token Tok
The Token.
Result
Implement __builtin_bit_cast and related operations.
Defines the clang::Preprocessor interface.
bool IsPreviousCachedToken(const Token &Tok) const
Whether Tok is the most recent token (CachedLexPos - 1) in CachedTokens.
void CommitBacktrackedTokens()
Disable the last EnableBacktrackAtThisPos call.
Definition PPCaching.cpp:56
void Lex(Token &Result)
Lex the next token for this preprocessor.
void Backtrack()
Make Preprocessor re-lex the tokens that were lexed since EnableBacktrackAtThisPos() was previously c...
Definition PPCaching.cpp:66
SourceManager & getSourceManager() const
bool isBacktrackEnabled() const
True if EnableBacktrackAtThisPos() was called and caching of tokens is on.
bool isUnannotatedBacktrackEnabled() const
True if EnableBacktrackAtThisPos() was called and caching of unannotated tokens is on.
void recomputeCurLexerKind()
Recompute the current lexer kind based on the CurLexer/ CurTokenLexer pointers.
void ReplacePreviousCachedToken(ArrayRef< Token > NewToks)
Replace token in CachedLexPos - 1 in CachedTokens by the tokens in NewToks.
void EnableBacktrackAtThisPos(bool Unannotated=false)
From the point that this method is called, and until CommitBacktrackedTokens() or Backtrack() is call...
Definition PPCaching.cpp:34
SourceLocation getLastCachedTokenLocation() const
Get the location of the last cached token, suitable for setting the end location of an annotation tok...
Token - This structure provides full information about a lexed token.
Definition Token.h:36
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition Token.h:142
SourceLocation getAnnotationEndLoc() const
Definition Token.h:156
tok::TokenKind getKind() const
Definition Token.h:99
@ IsReinjected
Definition Token.h:89
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition Token.h:131
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
SmallVector< Token, 4 > CachedTokens
A set of tokens that has been cached for later parsing.
Definition DeclSpec.h:1256