Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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
5.27k
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
833
      Kind(Kind), ImportedModule(ImportedModule), File(File) {
48
833
  char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
49
833
  memcpy(Memory, FileName.data(), FileName.size());
50
833
  Memory[FileName.size()] = 0;
51
833
  this->FileName = StringRef(Memory, FileName.size());
52
833
}
53
54
2.04k
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.56k
PreprocessingRecord::getPreprocessedEntitiesInRange(SourceRange Range) {
60
9.56k
  if (Range.isInvalid())
61
0
    return llvm::make_range(iterator(), iterator());
62
9.56k
63
9.56k
  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
1.16k
68
1.16k
  std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
69
1.16k
70
1.16k
  CachedRangeQuery.Range = Range;
71
1.16k
  CachedRangeQuery.Result = Res;
72
1.16k
73
1.16k
  return llvm::make_range(iterator(this, Res.first),
74
1.16k
                          iterator(this, Res.second));
75
1.16k
}
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
5.93k
83
5.93k
  SourceLocation Loc = PPE->getSourceRange().getBegin();
84
5.93k
  if (Loc.isInvalid())
85
0
    return false;
86
5.93k
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
9.42k
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
3.49k
112
3.49k
    // See if the external source can see if the entity is in the file without
113
3.49k
    // 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
0
119
0
    // The external source did not provide a definite answer, go and deserialize
120
0
    // the entity to check it.
121
0
    return isPreprocessedEntityIfInFileID(
122
0
                                       getLoadedPreprocessedEntity(LoadedIndex),
123
0
                                          FID, SourceMgr);
124
0
  }
125
217
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.16k
PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(SourceRange Range) {
138
1.16k
  assert(Range.isValid());
139
1.16k
  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
140
1.16k
141
1.16k
  std::pair<unsigned, unsigned>
142
1.16k
    Local = findLocalPreprocessedEntitiesInRange(Range);
143
1.16k
144
1.16k
  // Check if range spans local entities.
145
1.16k
  if (!ExternalSource || 
SourceMgr.isLocalSourceLocation(Range.getBegin())900
)
146
332
    return std::make_pair(Local.first, Local.second);
147
835
148
835
  std::pair<unsigned, unsigned>
149
835
    Loaded = ExternalSource->findPreprocessedEntitiesInRange(Range);
150
835
151
835
  // Check if range spans local entities.
152
835
  if (Loaded.first == Loaded.second)
153
43
    return std::make_pair(Local.first, Local.second);
154
792
155
792
  unsigned TotalLoaded = LoadedPreprocessedEntities.size();
156
792
157
792
  // 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
0
162
0
  // 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.16k
                                                      SourceRange Range) const {
169
1.16k
  if (Range.isInvalid())
170
0
    return std::make_pair(0,0);
171
1.16k
  assert(!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(),Range.getBegin()));
172
1.16k
173
1.16k
  unsigned Begin = findBeginLocalPreprocessedEntity(Range.getBegin());
174
1.16k
  unsigned End = findEndLocalPreprocessedEntity(Range.getEnd());
175
1.16k
  return std::make_pair(Begin, End);
176
1.16k
}
177
178
namespace {
179
180
template <SourceLocation (SourceRange::*getRangeLoc)() const>
181
struct PPEntityComp {
182
  const SourceManager &SM;
183
184
332
  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.35k
  bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
198
2.35k
    SourceLocation RHS = getLoc(R);
199
2.35k
    return SM.isBeforeInTranslationUnit(LHS, RHS);
200
2.35k
  }
201
202
2.35k
  SourceLocation getLoc(PreprocessedEntity *PPE) const {
203
2.35k
    SourceRange Range = PPE->getSourceRange();
204
2.35k
    return (Range.*getRangeLoc)();
205
2.35k
  }
206
};
207
208
} // namespace
209
210
unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
211
1.16k
                                                     SourceLocation Loc) const {
212
1.16k
  if (SourceMgr.isLoadedSourceLocation(Loc))
213
835
    return 0;
214
332
215
332
  size_t Count = PreprocessedEntities.size();
216
332
  size_t Half;
217
332
  std::vector<PreprocessedEntity *>::const_iterator
218
332
    First = PreprocessedEntities.begin();
219
332
  std::vector<PreprocessedEntity *>::const_iterator I;
220
332
221
332
  // Do a binary search manually instead of using std::lower_bound because
222
332
  // The end locations of entities may be unordered (when a macro expansion
223
332
  // is inside another macro argument), but for this case it is not important
224
332
  // whether we get the first macro expansion or its containing macro.
225
2.70k
  while (Count > 0) {
226
2.37k
    Half = Count/2;
227
2.37k
    I = First;
228
2.37k
    std::advance(I, Half);
229
2.37k
    if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
230
2.37k
                                            Loc)){
231
2.02k
      First = I;
232
2.02k
      ++First;
233
2.02k
      Count = Count - Half - 1;
234
2.02k
    } else
235
350
      Count = Half;
236
2.37k
  }
237
332
238
332
  return First - PreprocessedEntities.begin();
239
332
}
240
241
unsigned
242
1.16k
PreprocessingRecord::findEndLocalPreprocessedEntity(SourceLocation Loc) const {
243
1.16k
  if (SourceMgr.isLoadedSourceLocation(Loc))
244
835
    return 0;
245
332
246
332
  auto I = llvm::upper_bound(PreprocessedEntities, Loc,
247
332
                             PPEntityComp<&SourceRange::getBegin>(SourceMgr));
248
332
  return I - PreprocessedEntities.begin();
249
332
}
250
251
PreprocessingRecord::PPEntityID
252
581k
PreprocessingRecord::addPreprocessedEntity(PreprocessedEntity *Entity) {
253
581k
  assert(Entity);
254
581k
  SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
255
581k
256
581k
  if (isa<MacroDefinitionRecord>(Entity)) {
257
579k
    assert((PreprocessedEntities.empty() ||
258
579k
            !SourceMgr.isBeforeInTranslationUnit(
259
579k
                BeginLoc,
260
579k
                PreprocessedEntities.back()->getSourceRange().getBegin())) &&
261
579k
           "a macro definition was encountered out-of-order");
262
579k
    PreprocessedEntities.push_back(Entity);
263
579k
    return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
264
579k
  }
265
2.00k
266
2.00k
  // Check normal case, this entity begin location is after the previous one.
267
2.00k
  if (PreprocessedEntities.empty() ||
268
2.00k
      !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
269
2.00k
                   PreprocessedEntities.back()->getSourceRange().getBegin())) {
270
2.00k
    PreprocessedEntities.push_back(Entity);
271
2.00k
    return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
272
2.00k
  }
273
3
274
3
  // The entity's location is not after the previous one; this can happen with
275
3
  // include directives that form the filename using macros, e.g:
276
3
  // "#include MACRO(STUFF)"
277
3
  // or with macro expansions inside macro arguments where the arguments are
278
3
  // not expanded in the same order as listed, e.g:
279
3
  // \code
280
3
  //  #define M1 1
281
3
  //  #define M2 2
282
3
  //  #define FM(x,y) y x
283
3
  //  FM(M1, M2)
284
3
  // \endcode
285
3
286
3
  using pp_iter = std::vector<PreprocessedEntity *>::iterator;
287
3
288
3
  // Usually there are few macro expansions when defining the filename, do a
289
3
  // 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
7
                                           (*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
3
304
3
  // Linear search unsuccessful. Do a binary search.
305
3
  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
549
                                    ExternalPreprocessingRecordSource &Source) {
315
549
  assert(!ExternalSource &&
316
549
         "Preprocessing record already has an external source");
317
549
  ExternalSource = &Source;
318
549
}
319
320
690
unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
321
690
  unsigned Result = LoadedPreprocessedEntities.size();
322
690
  LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
323
690
                                    + NumEntities);
324
690
  return Result;
325
690
}
326
327
81
unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
328
81
  unsigned Result = SkippedRanges.size();
329
81
  SkippedRanges.resize(SkippedRanges.size() + NumRanges);
330
81
  SkippedRangesAllLoaded = false;
331
81
  return Result;
332
81
}
333
334
264
void PreprocessingRecord::ensureSkippedRangesLoaded() {
335
264
  if (SkippedRangesAllLoaded || 
!ExternalSource14
)
336
250
    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
225k
PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
351
225k
  if (PPID.ID < 0) {
352
55.0k
    unsigned Index = -PPID.ID - 1;
353
55.0k
    assert(Index < LoadedPreprocessedEntities.size() &&
354
55.0k
           "Out-of bounds loaded preprocessed entity");
355
55.0k
    return getLoadedPreprocessedEntity(Index);
356
55.0k
  }
357
170k
358
170k
  if (PPID.ID == 0)
359
0
    return nullptr;
360
170k
  unsigned Index = PPID.ID - 1;
361
170k
  assert(Index < PreprocessedEntities.size() &&
362
170k
         "Out-of bounds local preprocessed entity");
363
170k
  return PreprocessedEntities[Index];
364
170k
}
365
366
/// Retrieve the loaded preprocessed entity at the given index.
367
PreprocessedEntity *
368
55.0k
PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
369
55.0k
  assert(Index < LoadedPreprocessedEntities.size() &&
370
55.0k
         "Out-of bounds loaded preprocessed entity");
371
55.0k
  assert(ExternalSource && "No external source to load from");
372
55.0k
  PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
373
55.0k
  if (!Entity) {
374
48.5k
    Entity = ExternalSource->ReadPreprocessedEntity(Index);
375
48.5k
    if (!Entity) // Failed to load.
376
0
      Entity = new (*this)
377
0
         PreprocessedEntity(PreprocessedEntity::InvalidKind, SourceRange());
378
48.5k
  }
379
55.0k
  return Entity;
380
55.0k
}
381
382
MacroDefinitionRecord *
383
45.6k
PreprocessingRecord::findMacroDefinition(const MacroInfo *MI) {
384
45.6k
  llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
385
45.6k
      MacroDefinitions.find(MI);
386
45.6k
  if (Pos == MacroDefinitions.end())
387
12
    return nullptr;
388
45.6k
389
45.6k
  return Pos->second;
390
45.6k
}
391
392
void PreprocessingRecord::addMacroExpansion(const Token &Id,
393
                                            const MacroInfo *MI,
394
1.32k
                                            SourceRange Range) {
395
1.32k
  // We don't record nested macro expansions.
396
1.32k
  if (Id.getLocation().isMacroID())
397
85
    return;
398
1.23k
399
1.23k
  if (MI->isBuiltinMacro())
400
60
    addPreprocessedEntity(new (*this)
401
60
                              MacroExpansion(Id.getIdentifierInfo(), Range));
402
1.17k
  else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
403
1.17k
    addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
404
1.23k
}
405
406
void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
407
169
                                const MacroDefinition &MD) {
408
169
  // 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
179
                                 const MacroDefinition &MD) {
416
179
  // This is not actually a macro expansion but record it as a macro reference.
417
179
  if (MD)
418
47
    addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
419
47
                      MacroNameTok.getLocation());
420
179
}
421
422
void PreprocessingRecord::Defined(const Token &MacroNameTok,
423
                                  const MacroDefinition &MD,
424
83
                                  SourceRange Range) {
425
83
  // 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
170
                                             SourceLocation EndifLoc) {
433
170
  assert(Range.isValid());
434
170
  SkippedRanges.emplace_back(Range.getBegin(), EndifLoc);
435
170
}
436
437
void PreprocessingRecord::MacroExpands(const Token &Id,
438
                                       const MacroDefinition &MD,
439
                                       SourceRange Range,
440
1.10k
                                       const MacroArgs *Args) {
441
1.10k
  addMacroExpansion(Id, MD.getMacroInfo(), Range);
442
1.10k
}
443
444
void PreprocessingRecord::MacroDefined(const Token &Id,
445
579k
                                       const MacroDirective *MD) {
446
579k
  const MacroInfo *MI = MD->getMacroInfo();
447
579k
  SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc());
448
579k
  MacroDefinitionRecord *Def =
449
579k
      new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
450
579k
  addPreprocessedEntity(Def);
451
579k
  MacroDefinitions[MI] = Def;
452
579k
}
453
454
void PreprocessingRecord::MacroUndefined(const Token &Id,
455
                                         const MacroDefinition &MD,
456
70
                                         const MacroDirective *Undef) {
457
70
  MD.forAllDefinitions([&](MacroInfo *MI) 
{ MacroDefinitions.erase(MI); }66
);
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
768
    SrcMgr::CharacteristicKind FileType) {
471
768
  InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
472
768
473
768
  switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
474
768
  case tok::pp_include:
475
630
    Kind = InclusionDirective::Include;
476
630
    break;
477
768
478
768
  case tok::pp_import:
479
138
    Kind = InclusionDirective::Import;
480
138
    break;
481
768
482
768
  case tok::pp_include_next:
483
0
    Kind = InclusionDirective::IncludeNext;
484
0
    break;
485
768
486
768
  case tok::pp___include_macros:
487
0
    Kind = InclusionDirective::IncludeMacros;
488
0
    break;
489
768
490
768
  default:
491
0
    llvm_unreachable("Unknown include directive kind");
492
768
  }
493
768
494
768
  SourceLocation EndLoc;
495
768
  if (!IsAngled) {
496
675
    EndLoc = FilenameRange.getBegin();
497
675
  } else {
498
93
    EndLoc = FilenameRange.getEnd();
499
93
    if (FilenameRange.isCharRange())
500
93
      EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects
501
93
                                            // a token range.
502
93
  }
503
768
  clang::InclusionDirective *ID =
504
768
      new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
505
768
                                            (bool)Imported, File,
506
768
                                            SourceRange(HashLoc, EndLoc));
507
768
  addPreprocessedEntity(ID);
508
768
}
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
}