annotate clang/lib/Lex/PreprocessingRecord.cpp @ 266:00f31e85ec16 default tip

Added tag current for changeset 31d058e83c98
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Oct 2023 10:13:55 +0900
parents 1f2b6ac9f198
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===- PreprocessingRecord.cpp - Record of Preprocessing ------------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // This file implements the PreprocessingRecord class, which maintains a record
anatofuz
parents:
diff changeset
10 // of what occurred during preprocessing, and its helpers.
anatofuz
parents:
diff changeset
11 //
anatofuz
parents:
diff changeset
12 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 #include "clang/Lex/PreprocessingRecord.h"
anatofuz
parents:
diff changeset
15 #include "clang/Basic/IdentifierTable.h"
anatofuz
parents:
diff changeset
16 #include "clang/Basic/LLVM.h"
anatofuz
parents:
diff changeset
17 #include "clang/Basic/SourceLocation.h"
anatofuz
parents:
diff changeset
18 #include "clang/Basic/SourceManager.h"
anatofuz
parents:
diff changeset
19 #include "clang/Basic/TokenKinds.h"
anatofuz
parents:
diff changeset
20 #include "clang/Lex/MacroInfo.h"
anatofuz
parents:
diff changeset
21 #include "clang/Lex/Token.h"
anatofuz
parents:
diff changeset
22 #include "llvm/ADT/DenseMap.h"
anatofuz
parents:
diff changeset
23 #include "llvm/ADT/StringRef.h"
anatofuz
parents:
diff changeset
24 #include "llvm/ADT/iterator_range.h"
anatofuz
parents:
diff changeset
25 #include "llvm/Support/Capacity.h"
anatofuz
parents:
diff changeset
26 #include "llvm/Support/Casting.h"
anatofuz
parents:
diff changeset
27 #include "llvm/Support/ErrorHandling.h"
anatofuz
parents:
diff changeset
28 #include <algorithm>
anatofuz
parents:
diff changeset
29 #include <cassert>
anatofuz
parents:
diff changeset
30 #include <cstddef>
anatofuz
parents:
diff changeset
31 #include <cstring>
anatofuz
parents:
diff changeset
32 #include <iterator>
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
33 #include <optional>
150
anatofuz
parents:
diff changeset
34 #include <utility>
anatofuz
parents:
diff changeset
35 #include <vector>
anatofuz
parents:
diff changeset
36
anatofuz
parents:
diff changeset
37 using namespace clang;
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() =
anatofuz
parents:
diff changeset
40 default;
anatofuz
parents:
diff changeset
41
anatofuz
parents:
diff changeset
42 InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
anatofuz
parents:
diff changeset
43 InclusionKind Kind, StringRef FileName,
anatofuz
parents:
diff changeset
44 bool InQuotes, bool ImportedModule,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
45 OptionalFileEntryRef File,
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
46 SourceRange Range)
150
anatofuz
parents:
diff changeset
47 : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
anatofuz
parents:
diff changeset
48 Kind(Kind), ImportedModule(ImportedModule), File(File) {
anatofuz
parents:
diff changeset
49 char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
anatofuz
parents:
diff changeset
50 memcpy(Memory, FileName.data(), FileName.size());
anatofuz
parents:
diff changeset
51 Memory[FileName.size()] = 0;
anatofuz
parents:
diff changeset
52 this->FileName = StringRef(Memory, FileName.size());
anatofuz
parents:
diff changeset
53 }
anatofuz
parents:
diff changeset
54
anatofuz
parents:
diff changeset
55 PreprocessingRecord::PreprocessingRecord(SourceManager &SM) : SourceMgr(SM) {}
anatofuz
parents:
diff changeset
56
anatofuz
parents:
diff changeset
57 /// Returns a pair of [Begin, End) iterators of preprocessed entities
anatofuz
parents:
diff changeset
58 /// that source range \p Range encompasses.
anatofuz
parents:
diff changeset
59 llvm::iterator_range<PreprocessingRecord::iterator>
anatofuz
parents:
diff changeset
60 PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
anatofuz
parents:
diff changeset
61 if (Range.isInvalid())
anatofuz
parents:
diff changeset
62 return llvm::make_range(iterator(), iterator());
anatofuz
parents:
diff changeset
63
anatofuz
parents:
diff changeset
64 if (CachedRangeQuery.Range == Range) {
anatofuz
parents:
diff changeset
65 return llvm::make_range(iterator(this, CachedRangeQuery.Result.first),
anatofuz
parents:
diff changeset
66 iterator(this, CachedRangeQuery.Result.second));
anatofuz
parents:
diff changeset
67 }
anatofuz
parents:
diff changeset
68
anatofuz
parents:
diff changeset
69 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 CachedRangeQuery.Range = Range;
anatofuz
parents:
diff changeset
72 CachedRangeQuery.Result = Res;
anatofuz
parents:
diff changeset
73
anatofuz
parents:
diff changeset
74 return llvm::make_range(iterator(this, Res.first),
anatofuz
parents:
diff changeset
75 iterator(this, Res.second));
anatofuz
parents:
diff changeset
76 }
anatofuz
parents:
diff changeset
77
anatofuz
parents:
diff changeset
78 static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID,
anatofuz
parents:
diff changeset
79 SourceManager &SM) {
anatofuz
parents:
diff changeset
80 assert(FID.isValid());
anatofuz
parents:
diff changeset
81 if (!PPE)
anatofuz
parents:
diff changeset
82 return false;
anatofuz
parents:
diff changeset
83
anatofuz
parents:
diff changeset
84 SourceLocation Loc = PPE->getSourceRange().getBegin();
anatofuz
parents:
diff changeset
85 if (Loc.isInvalid())
anatofuz
parents:
diff changeset
86 return false;
anatofuz
parents:
diff changeset
87
anatofuz
parents:
diff changeset
88 return SM.isInFileID(SM.getFileLoc(Loc), FID);
anatofuz
parents:
diff changeset
89 }
anatofuz
parents:
diff changeset
90
anatofuz
parents:
diff changeset
91 /// Returns true if the preprocessed entity that \arg PPEI iterator
anatofuz
parents:
diff changeset
92 /// points to is coming from the file \arg FID.
anatofuz
parents:
diff changeset
93 ///
anatofuz
parents:
diff changeset
94 /// Can be used to avoid implicit deserializations of preallocated
anatofuz
parents:
diff changeset
95 /// preprocessed entities if we only care about entities of a specific file
anatofuz
parents:
diff changeset
96 /// and not from files \#included in the range given at
anatofuz
parents:
diff changeset
97 /// \see getPreprocessedEntitiesInRange.
anatofuz
parents:
diff changeset
98 bool PreprocessingRecord::isEntityInFileID(iterator PPEI, FileID FID) {
anatofuz
parents:
diff changeset
99 if (FID.isInvalid())
anatofuz
parents:
diff changeset
100 return false;
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102 int Pos = std::distance(iterator(this, 0), PPEI);
anatofuz
parents:
diff changeset
103 if (Pos < 0) {
anatofuz
parents:
diff changeset
104 if (unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
anatofuz
parents:
diff changeset
105 assert(0 && "Out-of bounds loaded preprocessed entity");
anatofuz
parents:
diff changeset
106 return false;
anatofuz
parents:
diff changeset
107 }
anatofuz
parents:
diff changeset
108 assert(ExternalSource && "No external source to load from");
anatofuz
parents:
diff changeset
109 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
anatofuz
parents:
diff changeset
110 if (PreprocessedEntity *PPE = LoadedPreprocessedEntities[LoadedIndex])
anatofuz
parents:
diff changeset
111 return isPreprocessedEntityIfInFileID(PPE, FID, SourceMgr);
anatofuz
parents:
diff changeset
112
anatofuz
parents:
diff changeset
113 // See if the external source can see if the entity is in the file without
anatofuz
parents:
diff changeset
114 // deserializing it.
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
115 if (std::optional<bool> IsInFile =
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
116 ExternalSource->isPreprocessedEntityInFileID(LoadedIndex, FID))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
117 return *IsInFile;
150
anatofuz
parents:
diff changeset
118
anatofuz
parents:
diff changeset
119 // The external source did not provide a definite answer, go and deserialize
anatofuz
parents:
diff changeset
120 // the entity to check it.
anatofuz
parents:
diff changeset
121 return isPreprocessedEntityIfInFileID(
anatofuz
parents:
diff changeset
122 getLoadedPreprocessedEntity(LoadedIndex),
anatofuz
parents:
diff changeset
123 FID, SourceMgr);
anatofuz
parents:
diff changeset
124 }
anatofuz
parents:
diff changeset
125
anatofuz
parents:
diff changeset
126 if (unsigned(Pos) >= PreprocessedEntities.size()) {
anatofuz
parents:
diff changeset
127 assert(0 && "Out-of bounds local preprocessed entity");
anatofuz
parents:
diff changeset
128 return false;
anatofuz
parents:
diff changeset
129 }
anatofuz
parents:
diff changeset
130 return isPreprocessedEntityIfInFileID(PreprocessedEntities[Pos],
anatofuz
parents:
diff changeset
131 FID, SourceMgr);
anatofuz
parents:
diff changeset
132 }
anatofuz
parents:
diff changeset
133
anatofuz
parents:
diff changeset
134 /// Returns a pair of [Begin, End) iterators of preprocessed entities
anatofuz
parents:
diff changeset
135 /// that source range \arg R encompasses.
anatofuz
parents:
diff changeset
136 std::pair<int, int>
anatofuz
parents:
diff changeset
137 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
anatofuz
parents:
diff changeset
138 assert(Range.isValid());
anatofuz
parents:
diff changeset
139 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
anatofuz
parents:
diff changeset
140
anatofuz
parents:
diff changeset
141 std::pair<unsigned, unsigned>
anatofuz
parents:
diff changeset
142 Local = findLocalPreprocessedEntitiesInRange(Range);
anatofuz
parents:
diff changeset
143
anatofuz
parents:
diff changeset
144 // Check if range spans local entities.
anatofuz
parents:
diff changeset
145 if (!ExternalSource || SourceMgr.isLocalSourceLocation(Range.getBegin()))
anatofuz
parents:
diff changeset
146 return std::make_pair(Local.first, Local.second);
anatofuz
parents:
diff changeset
147
anatofuz
parents:
diff changeset
148 std::pair<unsigned, unsigned>
anatofuz
parents:
diff changeset
149 Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
anatofuz
parents:
diff changeset
150
anatofuz
parents:
diff changeset
151 // Check if range spans local entities.
anatofuz
parents:
diff changeset
152 if (Loaded.first == Loaded.second)
anatofuz
parents:
diff changeset
153 return std::make_pair(Local.first, Local.second);
anatofuz
parents:
diff changeset
154
anatofuz
parents:
diff changeset
155 unsigned TotalLoaded = LoadedPreprocessedEntities.size();
anatofuz
parents:
diff changeset
156
anatofuz
parents:
diff changeset
157 // Check if range spans loaded entities.
anatofuz
parents:
diff changeset
158 if (Local.first == Local.second)
anatofuz
parents:
diff changeset
159 return std::make_pair(int(Loaded.first)-TotalLoaded,
anatofuz
parents:
diff changeset
160 int(Loaded.second)-TotalLoaded);
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 // Range spands loaded and local entities.
anatofuz
parents:
diff changeset
163 return std::make_pair(int(Loaded.first)-TotalLoaded, Local.second);
anatofuz
parents:
diff changeset
164 }
anatofuz
parents:
diff changeset
165
anatofuz
parents:
diff changeset
166 std::pair<unsigned, unsigned>
anatofuz
parents:
diff changeset
167 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
anatofuz
parents:
diff changeset
168 SourceRange Range) const {
anatofuz
parents:
diff changeset
169 if (Range.isInvalid())
anatofuz
parents:
diff changeset
170 return std::make_pair(0,0);
anatofuz
parents:
diff changeset
171 assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
anatofuz
parents:
diff changeset
172
anatofuz
parents:
diff changeset
173 unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
anatofuz
parents:
diff changeset
174 unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
anatofuz
parents:
diff changeset
175 return std::make_pair(Begin, End);
anatofuz
parents:
diff changeset
176 }
anatofuz
parents:
diff changeset
177
anatofuz
parents:
diff changeset
178 namespace {
anatofuz
parents:
diff changeset
179
anatofuz
parents:
diff changeset
180 template <SourceLocation (SourceRange::*getRangeLoc)() const>
anatofuz
parents:
diff changeset
181 struct PPEntityComp {
anatofuz
parents:
diff changeset
182 const SourceManager &SM;
anatofuz
parents:
diff changeset
183
anatofuz
parents:
diff changeset
184 explicit PPEntityComp(const SourceManager &SM) : SM(SM) {}
anatofuz
parents:
diff changeset
185
anatofuz
parents:
diff changeset
186 bool operator()(PreprocessedEntity *L, PreprocessedEntity *R) const {
anatofuz
parents:
diff changeset
187 SourceLocation LHS = getLoc(L);
anatofuz
parents:
diff changeset
188 SourceLocation RHS = getLoc(R);
anatofuz
parents:
diff changeset
189 return SM.isBeforeInTranslationUnit(LHS, RHS);
anatofuz
parents:
diff changeset
190 }
anatofuz
parents:
diff changeset
191
anatofuz
parents:
diff changeset
192 bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
anatofuz
parents:
diff changeset
193 SourceLocation LHS = getLoc(L);
anatofuz
parents:
diff changeset
194 return SM.isBeforeInTranslationUnit(LHS, RHS);
anatofuz
parents:
diff changeset
195 }
anatofuz
parents:
diff changeset
196
anatofuz
parents:
diff changeset
197 bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
anatofuz
parents:
diff changeset
198 SourceLocation RHS = getLoc(R);
anatofuz
parents:
diff changeset
199 return SM.isBeforeInTranslationUnit(LHS, RHS);
anatofuz
parents:
diff changeset
200 }
anatofuz
parents:
diff changeset
201
anatofuz
parents:
diff changeset
202 SourceLocation getLoc(PreprocessedEntity *PPE) const {
anatofuz
parents:
diff changeset
203 SourceRange Range = PPE->getSourceRange();
anatofuz
parents:
diff changeset
204 return (Range.*getRangeLoc)();
anatofuz
parents:
diff changeset
205 }
anatofuz
parents:
diff changeset
206 };
anatofuz
parents:
diff changeset
207
anatofuz
parents:
diff changeset
208 } // namespace
anatofuz
parents:
diff changeset
209
anatofuz
parents:
diff changeset
210 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
anatofuz
parents:
diff changeset
211 SourceLocation Loc) const {
anatofuz
parents:
diff changeset
212 if (SourceMgr.isLoadedSourceLocation(Loc))
anatofuz
parents:
diff changeset
213 return 0;
anatofuz
parents:
diff changeset
214
anatofuz
parents:
diff changeset
215 size_t Count = PreprocessedEntities.size();
anatofuz
parents:
diff changeset
216 size_t Half;
anatofuz
parents:
diff changeset
217 std::vector<PreprocessedEntity *>::const_iterator
anatofuz
parents:
diff changeset
218 First = PreprocessedEntities.begin();
anatofuz
parents:
diff changeset
219 std::vector<PreprocessedEntity *>::const_iterator I;
anatofuz
parents:
diff changeset
220
anatofuz
parents:
diff changeset
221 // Do a binary search manually instead of using std::lower_bound because
anatofuz
parents:
diff changeset
222 // The end locations of entities may be unordered (when a macro expansion
anatofuz
parents:
diff changeset
223 // is inside another macro argument), but for this case it is not important
anatofuz
parents:
diff changeset
224 // whether we get the first macro expansion or its containing macro.
anatofuz
parents:
diff changeset
225 while (Count > 0) {
anatofuz
parents:
diff changeset
226 Half = Count/2;
anatofuz
parents:
diff changeset
227 I = First;
anatofuz
parents:
diff changeset
228 std::advance(I, Half);
anatofuz
parents:
diff changeset
229 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
anatofuz
parents:
diff changeset
230 Loc)){
anatofuz
parents:
diff changeset
231 First = I;
anatofuz
parents:
diff changeset
232 ++First;
anatofuz
parents:
diff changeset
233 Count = Count - Half - 1;
anatofuz
parents:
diff changeset
234 } else
anatofuz
parents:
diff changeset
235 Count = Half;
anatofuz
parents:
diff changeset
236 }
anatofuz
parents:
diff changeset
237
anatofuz
parents:
diff changeset
238 return First - PreprocessedEntities.begin();
anatofuz
parents:
diff changeset
239 }
anatofuz
parents:
diff changeset
240
anatofuz
parents:
diff changeset
241 unsigned
anatofuz
parents:
diff changeset
242 PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
anatofuz
parents:
diff changeset
243 if (SourceMgr.isLoadedSourceLocation(Loc))
anatofuz
parents:
diff changeset
244 return 0;
anatofuz
parents:
diff changeset
245
anatofuz
parents:
diff changeset
246 auto I = llvm::upper_bound(PreprocessedEntities, Loc,
anatofuz
parents:
diff changeset
247 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
anatofuz
parents:
diff changeset
248 return I - PreprocessedEntities.begin();
anatofuz
parents:
diff changeset
249 }
anatofuz
parents:
diff changeset
250
anatofuz
parents:
diff changeset
251 PreprocessingRecord::PPEntityID
anatofuz
parents:
diff changeset
252 PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
anatofuz
parents:
diff changeset
253 assert(Entity);
anatofuz
parents:
diff changeset
254 SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
anatofuz
parents:
diff changeset
255
anatofuz
parents:
diff changeset
256 if (isa<MacroDefinitionRecord>(Entity)) {
anatofuz
parents:
diff changeset
257 assert((PreprocessedEntities.empty() ||
anatofuz
parents:
diff changeset
258 !SourceMgr.isBeforeInTranslationUnit(
anatofuz
parents:
diff changeset
259 BeginLoc,
anatofuz
parents:
diff changeset
260 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
anatofuz
parents:
diff changeset
261 "a macro definition was encountered out-of-order");
anatofuz
parents:
diff changeset
262 PreprocessedEntities.push_back(Entity);
anatofuz
parents:
diff changeset
263 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
anatofuz
parents:
diff changeset
264 }
anatofuz
parents:
diff changeset
265
anatofuz
parents:
diff changeset
266 // Check normal case, this entity begin location is after the previous one.
anatofuz
parents:
diff changeset
267 if (PreprocessedEntities.empty() ||
anatofuz
parents:
diff changeset
268 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
anatofuz
parents:
diff changeset
269 PreprocessedEntities.back()->getSourceRange().getBegin())) {
anatofuz
parents:
diff changeset
270 PreprocessedEntities.push_back(Entity);
anatofuz
parents:
diff changeset
271 return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
anatofuz
parents:
diff changeset
272 }
anatofuz
parents:
diff changeset
273
anatofuz
parents:
diff changeset
274 // The entity's location is not after the previous one; this can happen with
anatofuz
parents:
diff changeset
275 // include directives that form the filename using macros, e.g:
anatofuz
parents:
diff changeset
276 // "#include MACRO(STUFF)"
anatofuz
parents:
diff changeset
277 // or with macro expansions inside macro arguments where the arguments are
anatofuz
parents:
diff changeset
278 // not expanded in the same order as listed, e.g:
anatofuz
parents:
diff changeset
279 // \code
anatofuz
parents:
diff changeset
280 // #define M1 1
anatofuz
parents:
diff changeset
281 // #define M2 2
anatofuz
parents:
diff changeset
282 // #define FM(x,y) y x
anatofuz
parents:
diff changeset
283 // FM(M1, M2)
anatofuz
parents:
diff changeset
284 // \endcode
anatofuz
parents:
diff changeset
285
anatofuz
parents:
diff changeset
286 using pp_iter = std::vector<PreprocessedEntity *>::iterator;
anatofuz
parents:
diff changeset
287
anatofuz
parents:
diff changeset
288 // Usually there are few macro expansions when defining the filename, do a
anatofuz
parents:
diff changeset
289 // linear search for a few entities.
anatofuz
parents:
diff changeset
290 unsigned count = 0;
anatofuz
parents:
diff changeset
291 for (pp_iter RI = PreprocessedEntities.end(),
anatofuz
parents:
diff changeset
292 Begin = PreprocessedEntities.begin();
anatofuz
parents:
diff changeset
293 RI != Begin && count < 4; --RI, ++count) {
anatofuz
parents:
diff changeset
294 pp_iter I = RI;
anatofuz
parents:
diff changeset
295 --I;
anatofuz
parents:
diff changeset
296 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
anatofuz
parents:
diff changeset
297 (*I)->getSourceRange().getBegin())) {
anatofuz
parents:
diff changeset
298 pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
anatofuz
parents:
diff changeset
299 return getPPEntityID(insertI - PreprocessedEntities.begin(),
anatofuz
parents:
diff changeset
300 /*isLoaded=*/false);
anatofuz
parents:
diff changeset
301 }
anatofuz
parents:
diff changeset
302 }
anatofuz
parents:
diff changeset
303
anatofuz
parents:
diff changeset
304 // Linear search unsuccessful. Do a binary search.
anatofuz
parents:
diff changeset
305 pp_iter I =
anatofuz
parents:
diff changeset
306 llvm::upper_bound(PreprocessedEntities, BeginLoc,
anatofuz
parents:
diff changeset
307 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
anatofuz
parents:
diff changeset
308 pp_iter insertI = PreprocessedEntities.insert(I, Entity);
anatofuz
parents:
diff changeset
309 return getPPEntityID(insertI - PreprocessedEntities.begin(),
anatofuz
parents:
diff changeset
310 /*isLoaded=*/false);
anatofuz
parents:
diff changeset
311 }
anatofuz
parents:
diff changeset
312
anatofuz
parents:
diff changeset
313 void PreprocessingRecord::SetExternalSource(
anatofuz
parents:
diff changeset
314 ExternalPreprocessingRecordSource &Source) {
anatofuz
parents:
diff changeset
315 assert(!ExternalSource &&
anatofuz
parents:
diff changeset
316 "Preprocessing record already has an external source");
anatofuz
parents:
diff changeset
317 ExternalSource = &Source;
anatofuz
parents:
diff changeset
318 }
anatofuz
parents:
diff changeset
319
anatofuz
parents:
diff changeset
320 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
anatofuz
parents:
diff changeset
321 unsigned Result = LoadedPreprocessedEntities.size();
anatofuz
parents:
diff changeset
322 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
anatofuz
parents:
diff changeset
323 + NumEntities);
anatofuz
parents:
diff changeset
324 return Result;
anatofuz
parents:
diff changeset
325 }
anatofuz
parents:
diff changeset
326
anatofuz
parents:
diff changeset
327 unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
anatofuz
parents:
diff changeset
328 unsigned Result = SkippedRanges.size();
anatofuz
parents:
diff changeset
329 SkippedRanges.resize(SkippedRanges.size() + NumRanges);
anatofuz
parents:
diff changeset
330 SkippedRangesAllLoaded = false;
anatofuz
parents:
diff changeset
331 return Result;
anatofuz
parents:
diff changeset
332 }
anatofuz
parents:
diff changeset
333
anatofuz
parents:
diff changeset
334 void PreprocessingRecord::ensureSkippedRangesLoaded() {
anatofuz
parents:
diff changeset
335 if (SkippedRangesAllLoaded || !ExternalSource)
anatofuz
parents:
diff changeset
336 return;
anatofuz
parents:
diff changeset
337 for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
anatofuz
parents:
diff changeset
338 if (SkippedRanges[Index].isInvalid())
anatofuz
parents:
diff changeset
339 SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
anatofuz
parents:
diff changeset
340 }
anatofuz
parents:
diff changeset
341 SkippedRangesAllLoaded = true;
anatofuz
parents:
diff changeset
342 }
anatofuz
parents:
diff changeset
343
anatofuz
parents:
diff changeset
344 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
anatofuz
parents:
diff changeset
345 MacroDefinitionRecord *Def) {
anatofuz
parents:
diff changeset
346 MacroDefinitions[Macro] = Def;
anatofuz
parents:
diff changeset
347 }
anatofuz
parents:
diff changeset
348
anatofuz
parents:
diff changeset
349 /// Retrieve the preprocessed entity at the given ID.
anatofuz
parents:
diff changeset
350 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
anatofuz
parents:
diff changeset
351 if (PPID.ID < 0) {
anatofuz
parents:
diff changeset
352 unsigned Index = -PPID.ID - 1;
anatofuz
parents:
diff changeset
353 assert(Index < LoadedPreprocessedEntities.size() &&
anatofuz
parents:
diff changeset
354 "Out-of bounds loaded preprocessed entity");
anatofuz
parents:
diff changeset
355 return getLoadedPreprocessedEntity(Index);
anatofuz
parents:
diff changeset
356 }
anatofuz
parents:
diff changeset
357
anatofuz
parents:
diff changeset
358 if (PPID.ID == 0)
anatofuz
parents:
diff changeset
359 return nullptr;
anatofuz
parents:
diff changeset
360 unsigned Index = PPID.ID - 1;
anatofuz
parents:
diff changeset
361 assert(Index < PreprocessedEntities.size() &&
anatofuz
parents:
diff changeset
362 "Out-of bounds local preprocessed entity");
anatofuz
parents:
diff changeset
363 return PreprocessedEntities[Index];
anatofuz
parents:
diff changeset
364 }
anatofuz
parents:
diff changeset
365
anatofuz
parents:
diff changeset
366 /// Retrieve the loaded preprocessed entity at the given index.
anatofuz
parents:
diff changeset
367 PreprocessedEntity *
anatofuz
parents:
diff changeset
368 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
anatofuz
parents:
diff changeset
369 assert(Index < LoadedPreprocessedEntities.size() &&
anatofuz
parents:
diff changeset
370 "Out-of bounds loaded preprocessed entity");
anatofuz
parents:
diff changeset
371 assert(ExternalSource && "No external source to load from");
anatofuz
parents:
diff changeset
372 PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
anatofuz
parents:
diff changeset
373 if (!Entity) {
anatofuz
parents:
diff changeset
374 Entity = ExternalSource->ReadPreprocessedEntity(Index);
anatofuz
parents:
diff changeset
375 if (!Entity) // Failed to load.
anatofuz
parents:
diff changeset
376 Entity = new (*this)
anatofuz
parents:
diff changeset
377 PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
anatofuz
parents:
diff changeset
378 }
anatofuz
parents:
diff changeset
379 return Entity;
anatofuz
parents:
diff changeset
380 }
anatofuz
parents:
diff changeset
381
anatofuz
parents:
diff changeset
382 MacroDefinitionRecord *
anatofuz
parents:
diff changeset
383 PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
384 return MacroDefinitions.lookup(MI);
150
anatofuz
parents:
diff changeset
385 }
anatofuz
parents:
diff changeset
386
anatofuz
parents:
diff changeset
387 void PreprocessingRecord::addMacroExpansion(const Token &Id,
anatofuz
parents:
diff changeset
388 const MacroInfo *MI,
anatofuz
parents:
diff changeset
389 SourceRange Range) {
anatofuz
parents:
diff changeset
390 // We don't record nested macro expansions.
anatofuz
parents:
diff changeset
391 if (Id.getLocation().isMacroID())
anatofuz
parents:
diff changeset
392 return;
anatofuz
parents:
diff changeset
393
anatofuz
parents:
diff changeset
394 if (MI->isBuiltinMacro())
anatofuz
parents:
diff changeset
395 addPreprocessedEntity(new (*this)
anatofuz
parents:
diff changeset
396 MacroExpansion(Id.getIdentifierInfo(), Range));
anatofuz
parents:
diff changeset
397 else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
anatofuz
parents:
diff changeset
398 addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
anatofuz
parents:
diff changeset
399 }
anatofuz
parents:
diff changeset
400
anatofuz
parents:
diff changeset
401 void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
anatofuz
parents:
diff changeset
402 const MacroDefinition &MD) {
anatofuz
parents:
diff changeset
403 // This is not actually a macro expansion but record it as a macro reference.
anatofuz
parents:
diff changeset
404 if (MD)
anatofuz
parents:
diff changeset
405 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
anatofuz
parents:
diff changeset
406 MacroNameTok.getLocation());
anatofuz
parents:
diff changeset
407 }
anatofuz
parents:
diff changeset
408
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
409 void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
410 const MacroDefinition &MD) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
411 // This is not actually a macro expansion but record it as a macro reference.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
412 if (MD)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
413 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
414 MacroNameTok.getLocation());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
415 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
416
150
anatofuz
parents:
diff changeset
417 void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
anatofuz
parents:
diff changeset
418 const MacroDefinition &MD) {
anatofuz
parents:
diff changeset
419 // This is not actually a macro expansion but record it as a macro reference.
anatofuz
parents:
diff changeset
420 if (MD)
anatofuz
parents:
diff changeset
421 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
anatofuz
parents:
diff changeset
422 MacroNameTok.getLocation());
anatofuz
parents:
diff changeset
423 }
anatofuz
parents:
diff changeset
424
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
425 void PreprocessingRecord::Elifndef(SourceLocation Loc,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
426 const Token &MacroNameTok,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
427 const MacroDefinition &MD) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
428 // This is not actually a macro expansion but record it as a macro reference.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
429 if (MD)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
430 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
431 MacroNameTok.getLocation());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
432 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
433
150
anatofuz
parents:
diff changeset
434 void PreprocessingRecord::Defined(const Token &MacroNameTok,
anatofuz
parents:
diff changeset
435 const MacroDefinition &MD,
anatofuz
parents:
diff changeset
436 SourceRange Range) {
anatofuz
parents:
diff changeset
437 // This is not actually a macro expansion but record it as a macro reference.
anatofuz
parents:
diff changeset
438 if (MD)
anatofuz
parents:
diff changeset
439 addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
anatofuz
parents:
diff changeset
440 MacroNameTok.getLocation());
anatofuz
parents:
diff changeset
441 }
anatofuz
parents:
diff changeset
442
anatofuz
parents:
diff changeset
443 void PreprocessingRecord::SourceRangeSkipped(SourceRange Range,
anatofuz
parents:
diff changeset
444 SourceLocation EndifLoc) {
anatofuz
parents:
diff changeset
445 assert(Range.isValid());
anatofuz
parents:
diff changeset
446 SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
anatofuz
parents:
diff changeset
447 }
anatofuz
parents:
diff changeset
448
anatofuz
parents:
diff changeset
449 void PreprocessingRecord::MacroExpands(const Token &Id,
anatofuz
parents:
diff changeset
450 const MacroDefinition &MD,
anatofuz
parents:
diff changeset
451 SourceRange Range,
anatofuz
parents:
diff changeset
452 const MacroArgs *Args) {
anatofuz
parents:
diff changeset
453 addMacroExpansion(Id, MD.getMacroInfo(), Range);
anatofuz
parents:
diff changeset
454 }
anatofuz
parents:
diff changeset
455
anatofuz
parents:
diff changeset
456 void PreprocessingRecord::MacroDefined(const Token &Id,
anatofuz
parents:
diff changeset
457 const MacroDirective *MD) {
anatofuz
parents:
diff changeset
458 const MacroInfo *MI = MD->getMacroInfo();
anatofuz
parents:
diff changeset
459 SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
anatofuz
parents:
diff changeset
460 MacroDefinitionRecord *Def =
anatofuz
parents:
diff changeset
461 new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
anatofuz
parents:
diff changeset
462 addPreprocessedEntity(Def);
anatofuz
parents:
diff changeset
463 MacroDefinitions[MI] = Def;
anatofuz
parents:
diff changeset
464 }
anatofuz
parents:
diff changeset
465
anatofuz
parents:
diff changeset
466 void PreprocessingRecord::MacroUndefined(const Token &Id,
anatofuz
parents:
diff changeset
467 const MacroDefinition &MD,
anatofuz
parents:
diff changeset
468 const MacroDirective *Undef) {
anatofuz
parents:
diff changeset
469 MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
anatofuz
parents:
diff changeset
470 }
anatofuz
parents:
diff changeset
471
anatofuz
parents:
diff changeset
472 void PreprocessingRecord::InclusionDirective(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
473 SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
474 bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
475 StringRef SearchPath, StringRef RelativePath, const Module *Imported,
150
anatofuz
parents:
diff changeset
476 SrcMgr::CharacteristicKind FileType) {
anatofuz
parents:
diff changeset
477 InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
anatofuz
parents:
diff changeset
478
anatofuz
parents:
diff changeset
479 switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
anatofuz
parents:
diff changeset
480 case tok::pp_include:
anatofuz
parents:
diff changeset
481 Kind = InclusionDirective::Include;
anatofuz
parents:
diff changeset
482 break;
anatofuz
parents:
diff changeset
483
anatofuz
parents:
diff changeset
484 case tok::pp_import:
anatofuz
parents:
diff changeset
485 Kind = InclusionDirective::Import;
anatofuz
parents:
diff changeset
486 break;
anatofuz
parents:
diff changeset
487
anatofuz
parents:
diff changeset
488 case tok::pp_include_next:
anatofuz
parents:
diff changeset
489 Kind = InclusionDirective::IncludeNext;
anatofuz
parents:
diff changeset
490 break;
anatofuz
parents:
diff changeset
491
anatofuz
parents:
diff changeset
492 case tok::pp___include_macros:
anatofuz
parents:
diff changeset
493 Kind = InclusionDirective::IncludeMacros;
anatofuz
parents:
diff changeset
494 break;
anatofuz
parents:
diff changeset
495
anatofuz
parents:
diff changeset
496 default:
anatofuz
parents:
diff changeset
497 llvm_unreachable("Unknown include directive kind");
anatofuz
parents:
diff changeset
498 }
anatofuz
parents:
diff changeset
499
anatofuz
parents:
diff changeset
500 SourceLocation EndLoc;
anatofuz
parents:
diff changeset
501 if (!IsAngled) {
anatofuz
parents:
diff changeset
502 EndLoc = FilenameRange.getBegin();
anatofuz
parents:
diff changeset
503 } else {
anatofuz
parents:
diff changeset
504 EndLoc = FilenameRange.getEnd();
anatofuz
parents:
diff changeset
505 if (FilenameRange.isCharRange())
anatofuz
parents:
diff changeset
506 EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
anatofuz
parents:
diff changeset
507 // a token range.
anatofuz
parents:
diff changeset
508 }
anatofuz
parents:
diff changeset
509 clang::InclusionDirective *ID =
anatofuz
parents:
diff changeset
510 new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
anatofuz
parents:
diff changeset
511 (bool)Imported, File,
anatofuz
parents:
diff changeset
512 SourceRange(HashLoc, EndLoc));
anatofuz
parents:
diff changeset
513 addPreprocessedEntity(ID);
anatofuz
parents:
diff changeset
514 }
anatofuz
parents:
diff changeset
515
anatofuz
parents:
diff changeset
516 size_t PreprocessingRecord::getTotalMemory() const {
anatofuz
parents:
diff changeset
517 return BumpAlloc.getTotalMemory()
anatofuz
parents:
diff changeset
518 + llvm::capacity_in_bytes(MacroDefinitions)
anatofuz
parents:
diff changeset
519 + llvm::capacity_in_bytes(PreprocessedEntities)
anatofuz
parents:
diff changeset
520 + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
anatofuz
parents:
diff changeset
521 + llvm::capacity_in_bytes(SkippedRanges);
anatofuz
parents:
diff changeset
522 }