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