clang  3.9.0
PreprocessingRecord.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
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 
23 
24 
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 
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>
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 
68  SourceManager &SM) {
69  assert(FID.isValid());
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.
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.
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>
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>
157 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 
174  explicit PPEntityComp(const SourceManager &SM) : SM(SM) { }
175 
176  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 
182  bool operator()(PreprocessedEntity *L, SourceLocation RHS) const {
183  SourceLocation LHS = getLoc(L);
184  return SM.isBeforeInTranslationUnit(LHS, RHS);
185  }
186 
187  bool operator()(SourceLocation LHS, PreprocessedEntity *R) const {
188  SourceLocation RHS = getLoc(R);
189  return SM.isBeforeInTranslationUnit(LHS, RHS);
190  }
191 
192  SourceLocation getLoc(PreprocessedEntity *PPE) const {
193  SourceRange Range = PPE->getSourceRange();
194  return (Range.*getRangeLoc)();
195  }
196 };
197 
198 }
199 
200 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 
231 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
246  assert(Entity);
247  SourceLocation BeginLoc = Entity->getSourceRange().getBegin();
248 
249  if (isa<MacroDefinitionRecord>(Entity)) {
250  assert((PreprocessedEntities.empty() ||
251  !SourceMgr.isBeforeInTranslationUnit(
252  BeginLoc,
253  PreprocessedEntities.back()->getSourceRange().getBegin())) &&
254  "a macro definition was encountered out-of-order");
255  PreprocessedEntities.push_back(Entity);
256  return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
257  }
258 
259  // Check normal case, this entity begin location is after the previous one.
260  if (PreprocessedEntities.empty() ||
261  !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
262  PreprocessedEntities.back()->getSourceRange().getBegin())) {
263  PreprocessedEntities.push_back(Entity);
264  return getPPEntityID(PreprocessedEntities.size()-1, /*isLoaded=*/false);
265  }
266 
267  // The entity's location is not after the previous one; this can happen with
268  // include directives that form the filename using macros, e.g:
269  // "#include MACRO(STUFF)"
270  // or with macro expansions inside macro arguments where the arguments are
271  // not expanded in the same order as listed, e.g:
272  // \code
273  // #define M1 1
274  // #define M2 2
275  // #define FM(x,y) y x
276  // FM(M1, M2)
277  // \endcode
278 
280 
281  // Usually there are few macro expansions when defining the filename, do a
282  // linear search for a few entities.
283  unsigned count = 0;
284  for (pp_iter RI = PreprocessedEntities.end(),
285  Begin = PreprocessedEntities.begin();
286  RI != Begin && count < 4; --RI, ++count) {
287  pp_iter I = RI;
288  --I;
289  if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
290  (*I)->getSourceRange().getBegin())) {
291  pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
292  return getPPEntityID(insertI - PreprocessedEntities.begin(),
293  /*isLoaded=*/false);
294  }
295  }
296 
297  // Linear search unsuccessful. Do a binary search.
298  pp_iter I = std::upper_bound(PreprocessedEntities.begin(),
299  PreprocessedEntities.end(),
300  BeginLoc,
301  PPEntityComp<&SourceRange::getBegin>(SourceMgr));
302  pp_iter insertI = PreprocessedEntities.insert(I, Entity);
303  return getPPEntityID(insertI - PreprocessedEntities.begin(),
304  /*isLoaded=*/false);
305 }
306 
309  assert(!ExternalSource &&
310  "Preprocessing record already has an external source");
311  ExternalSource = &Source;
312 }
313 
314 unsigned PreprocessingRecord::allocateLoadedEntities(unsigned NumEntities) {
315  unsigned Result = LoadedPreprocessedEntities.size();
316  LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
317  + NumEntities);
318  return Result;
319 }
320 
321 void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
322  MacroDefinitionRecord *Def) {
323  MacroDefinitions[Macro] = Def;
324 }
325 
326 /// \brief Retrieve the preprocessed entity at the given ID.
327 PreprocessedEntity *PreprocessingRecord::getPreprocessedEntity(PPEntityID PPID){
328  if (PPID.ID < 0) {
329  unsigned Index = -PPID.ID - 1;
330  assert(Index < LoadedPreprocessedEntities.size() &&
331  "Out-of bounds loaded preprocessed entity");
332  return getLoadedPreprocessedEntity(Index);
333  }
334 
335  if (PPID.ID == 0)
336  return nullptr;
337  unsigned Index = PPID.ID - 1;
338  assert(Index < PreprocessedEntities.size() &&
339  "Out-of bounds local preprocessed entity");
340  return PreprocessedEntities[Index];
341 }
342 
343 /// \brief Retrieve the loaded preprocessed entity at the given index.
345 PreprocessingRecord::getLoadedPreprocessedEntity(unsigned Index) {
346  assert(Index < LoadedPreprocessedEntities.size() &&
347  "Out-of bounds loaded preprocessed entity");
348  assert(ExternalSource && "No external source to load from");
349  PreprocessedEntity *&Entity = LoadedPreprocessedEntities[Index];
350  if (!Entity) {
351  Entity = ExternalSource->ReadPreprocessedEntity(Index);
352  if (!Entity) // Failed to load.
353  Entity = new (*this)
355  }
356  return Entity;
357 }
358 
362  MacroDefinitions.find(MI);
363  if (Pos == MacroDefinitions.end())
364  return nullptr;
365 
366  return Pos->second;
367 }
368 
369 void PreprocessingRecord::addMacroExpansion(const Token &Id,
370  const MacroInfo *MI,
371  SourceRange Range) {
372  // We don't record nested macro expansions.
373  if (Id.getLocation().isMacroID())
374  return;
375 
376  if (MI->isBuiltinMacro())
377  addPreprocessedEntity(new (*this)
379  else if (MacroDefinitionRecord *Def = findMacroDefinition(MI))
380  addPreprocessedEntity(new (*this) MacroExpansion(Def, Range));
381 }
382 
383 void PreprocessingRecord::Ifdef(SourceLocation Loc, const Token &MacroNameTok,
384  const MacroDefinition &MD) {
385  // This is not actually a macro expansion but record it as a macro reference.
386  if (MD)
387  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
388  MacroNameTok.getLocation());
389 }
390 
391 void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
392  const MacroDefinition &MD) {
393  // This is not actually a macro expansion but record it as a macro reference.
394  if (MD)
395  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
396  MacroNameTok.getLocation());
397 }
398 
399 void PreprocessingRecord::Defined(const Token &MacroNameTok,
400  const MacroDefinition &MD,
401  SourceRange Range) {
402  // This is not actually a macro expansion but record it as a macro reference.
403  if (MD)
404  addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
405  MacroNameTok.getLocation());
406 }
407 
408 void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) {
409  SkippedRanges.push_back(Range);
410 }
411 
412 void PreprocessingRecord::MacroExpands(const Token &Id,
413  const MacroDefinition &MD,
414  SourceRange Range,
415  const MacroArgs *Args) {
416  addMacroExpansion(Id, MD.getMacroInfo(), Range);
417 }
418 
419 void PreprocessingRecord::MacroDefined(const Token &Id,
420  const MacroDirective *MD) {
421  const MacroInfo *MI = MD->getMacroInfo();
423  MacroDefinitionRecord *Def =
424  new (*this) MacroDefinitionRecord(Id.getIdentifierInfo(), R);
426  MacroDefinitions[MI] = Def;
427 }
428 
429 void PreprocessingRecord::MacroUndefined(const Token &Id,
430  const MacroDefinition &MD) {
431  MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
432 }
433 
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) {
445 
446  switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
447  case tok::pp_include:
449  break;
450 
451  case tok::pp_import:
453  break;
454 
455  case tok::pp_include_next:
457  break;
458 
459  case tok::pp___include_macros:
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  }
477  = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled,
478  (bool)Imported,
479  File, SourceRange(HashLoc, EndLoc));
481 }
482 
484  return BumpAlloc.getTotalMemory()
485  + llvm::capacity_in_bytes(MacroDefinitions)
486  + llvm::capacity_in_bytes(PreprocessedEntities)
487  + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
488 }
SourceLocation getEnd() const
SourceLocation getBegin() const
bool isMacroID() const
Defines the clang::MacroInfo and clang::MacroDirective classes.
A description of the current definition of a macro.
Definition: MacroInfo.h:563
Indicates a problem trying to load the preprocessed entity.
Base class that describes a preprocessed entity, which may be a preprocessor directive or macro expan...
virtual PreprocessedEntity * ReadPreprocessedEntity(unsigned Index)=0
Read a preallocated preprocessed entity from the external source.
SourceRange getSourceRange() const LLVM_READONLY
Retrieve the source range that covers this entire preprocessed entity.
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
Definition: MacroInfo.h:120
Records the presence of a preprocessor directive.
Iteration over the preprocessed entities.
Record the location of a macro definition.
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
Describes a module or submodule.
Definition: Basic/Module.h:47
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
Definition: MacroInfo.h:579
llvm::iterator_range< iterator > getPreprocessedEntitiesInRange(SourceRange R)
Returns a range of preprocessed entities that source range R encompasses.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
A record of the steps taken while preprocessing a source file, including the various preprocessing di...
virtual std::pair< unsigned, unsigned > findPreprocessedEntitiesInRange(SourceRange Range)=0
Returns a pair of [Begin, End) indices of preallocated preprocessed entities that Range encompasses...
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location...
bool isLoadedSourceLocation(SourceLocation Loc) const
Returns true if Loc came from a PCH/Module.
detail::InMemoryDirectory::const_iterator I
bool isInvalid() const
Records the location of a macro expansion.
PreprocessingRecord(SourceManager &SM)
Construct a new preprocessing record.
A GNU #include_next directive.
const SmallVectorImpl< AnnotatedLine * >::const_iterator End
std::pair< int, int > Result
virtual Optional< bool > isPreprocessedEntityInFileID(unsigned Index, FileID FID)
Optionally returns true or false if the preallocated preprocessed entity with index Index came from f...
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
void * Allocate(unsigned Size, unsigned Align=8)
Allocate memory in the preprocessing record.
Represents a character-granular source range.
SourceLocation getEnd() const
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, SourceManager &SM)
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Definition: MacroArgs.h:29
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:123
Record the location of an inclusion directive, such as an #include or #import statement.
InclusionKind
The kind of inclusion directives known to the preprocessor.
InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind, StringRef FileName, bool InQuotes, bool ImportedModule, const FileEntry *File, SourceRange Range)
const SourceManager & SM
Definition: Format.cpp:1184
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Definition: MacroInfo.h:307
StringRef FileName
Definition: Format.cpp:1313
Kind
Encodes a location in the source.
const TemplateArgument * iterator
Definition: Type.h:4233
const std::string ID
bool isCharRange() const
bool isValid() const
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:53
void forAllDefinitions(Fn F) const
Definition: MacroInfo.h:599
An abstract class that should be subclassed by any external source of preprocessing record entries...
SourceLocation getDefinitionEndLoc() const
Return the location of the last token in the macro.
Definition: MacroInfo.h:126
SourceLocation getBegin() const
bool isEntityInFileID(iterator PPEI, FileID FID)
Returns true if the preprocessed entity that PPEI iterator points to is coming from the file FID...
A Clang #__include_macros directive.
bool isLocalSourceLocation(SourceLocation Loc) const
Returns true if Loc did not come from a PCH/Module.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
const MacroInfo * getMacroInfo() const
Definition: MacroInfo.h:403
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:34
PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity)
Add a new preprocessed entity to this record.
bool isInvalid() const
An Objective-C #import directive.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
Definition: MacroInfo.h:212
bool isInvalid() const
MacroDefinitionRecord * findMacroDefinition(const MacroInfo *MI)
Retrieve the macro definition that corresponds to the given MacroInfo.
void SetExternalSource(ExternalPreprocessingRecordSource &Source)
Set the external source for preprocessed entities.
A trivial tuple used to represent a source range.
bool isValid() const
This class handles loading and caching of source files into memory.
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:176
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.