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