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