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