Clang Project

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