23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ADT/Optional.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/ADT/iterator_range.h" 27 #include "llvm/Support/Capacity.h" 28 #include "llvm/Support/Casting.h" 29 #include "llvm/Support/ErrorHandling.h" 38 using namespace clang;
45 bool InQuotes,
bool ImportedModule,
48 Kind(Kind), ImportedModule(ImportedModule), File(File) {
49 char *Memory = (
char *)PPRec.
Allocate(FileName.size() + 1,
alignof(char));
50 memcpy(Memory, FileName.data(), FileName.size());
51 Memory[FileName.size()] = 0;
52 this->FileName = StringRef(Memory, FileName.size());
59 llvm::iterator_range<PreprocessingRecord::iterator>
64 if (CachedRangeQuery.Range == Range) {
65 return llvm::make_range(
iterator(
this, CachedRangeQuery.Result.first),
66 iterator(
this, CachedRangeQuery.Result.second));
69 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
71 CachedRangeQuery.Range =
Range;
72 CachedRangeQuery.Result = Res;
74 return llvm::make_range(
iterator(
this, Res.first),
104 if (
unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
105 assert(0 &&
"Out-of bounds loaded preprocessed entity");
108 assert(ExternalSource &&
"No external source to load from");
109 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
117 if (IsInFile.hasValue())
118 return IsInFile.getValue();
123 getLoadedPreprocessedEntity(LoadedIndex),
127 if (
unsigned(Pos) >= PreprocessedEntities.size()) {
128 assert(0 &&
"Out-of bounds local preprocessed entity");
138 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(
SourceRange Range) {
142 std::pair<unsigned, unsigned>
143 Local = findLocalPreprocessedEntitiesInRange(Range);
147 return std::make_pair(Local.first, Local.second);
149 std::pair<unsigned, unsigned>
153 if (Loaded.first == Loaded.second)
154 return std::make_pair(Local.first, Local.second);
156 unsigned TotalLoaded = LoadedPreprocessedEntities.size();
159 if (Local.first == Local.second)
160 return std::make_pair(
int(Loaded.first)-TotalLoaded,
161 int(Loaded.second)-TotalLoaded);
164 return std::make_pair(
int(Loaded.first)-TotalLoaded, Local.second);
167 std::pair<unsigned, unsigned>
168 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
171 return std::make_pair(0,0);
174 unsigned Begin = findBeginLocalPreprocessedEntity(Range.
getBegin());
175 unsigned End = findEndLocalPreprocessedEntity(Range.
getEnd());
176 return std::make_pair(Begin, End);
181 template <SourceLocation (SourceRange::*getRangeLoc)() const>
182 struct PPEntityComp {
205 return (Range.*getRangeLoc)();
211 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
213 if (SourceMgr.isLoadedSourceLocation(Loc))
216 size_t Count = PreprocessedEntities.size();
218 std::vector<PreprocessedEntity *>::const_iterator
219 First = PreprocessedEntities.begin();
220 std::vector<PreprocessedEntity *>::const_iterator I;
229 std::advance(I, Half);
230 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
234 Count = Count - Half - 1;
239 return First - PreprocessedEntities.begin();
242 unsigned PreprocessingRecord::findEndLocalPreprocessedEntity(
244 if (SourceMgr.isLoadedSourceLocation(Loc))
247 std::vector<PreprocessedEntity *>::const_iterator
248 I = std::upper_bound(PreprocessedEntities.begin(),
249 PreprocessedEntities.end(),
251 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
252 return I - PreprocessedEntities.begin();
255 PreprocessingRecord::PPEntityID
260 if (isa<MacroDefinitionRecord>(Entity)) {
261 assert((PreprocessedEntities.empty() ||
262 !SourceMgr.isBeforeInTranslationUnit(
264 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
265 "a macro definition was encountered out-of-order");
266 PreprocessedEntities.push_back(Entity);
267 return getPPEntityID(PreprocessedEntities.size()-1,
false);
271 if (PreprocessedEntities.empty() ||
272 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
273 PreprocessedEntities.back()->getSourceRange().getBegin())) {
274 PreprocessedEntities.push_back(Entity);
275 return getPPEntityID(PreprocessedEntities.size()-1,
false);
290 using pp_iter = std::vector<PreprocessedEntity *>::iterator;
295 for (pp_iter RI = PreprocessedEntities.end(),
296 Begin = PreprocessedEntities.begin();
297 RI !=
Begin && count < 4; --RI, ++count) {
300 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
301 (*I)->getSourceRange().getBegin())) {
302 pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
303 return getPPEntityID(insertI - PreprocessedEntities.begin(),
309 pp_iter I = std::upper_bound(PreprocessedEntities.begin(),
310 PreprocessedEntities.end(),
312 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
313 pp_iter insertI = PreprocessedEntities.insert(I, Entity);
314 return getPPEntityID(insertI - PreprocessedEntities.begin(),
320 assert(!ExternalSource &&
321 "Preprocessing record already has an external source");
322 ExternalSource = &Source;
325 unsigned PreprocessingRecord::allocateLoadedEntities(
unsigned NumEntities) {
326 unsigned Result = LoadedPreprocessedEntities.size();
327 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
332 void PreprocessingRecord::RegisterMacroDefinition(
MacroInfo *Macro,
334 MacroDefinitions[Macro] = Def;
340 unsigned Index = -PPID.ID - 1;
341 assert(Index < LoadedPreprocessedEntities.size() &&
342 "Out-of bounds loaded preprocessed entity");
343 return getLoadedPreprocessedEntity(Index);
348 unsigned Index = PPID.ID - 1;
349 assert(Index < PreprocessedEntities.size() &&
350 "Out-of bounds local preprocessed entity");
351 return PreprocessedEntities[Index];
356 PreprocessingRecord::getLoadedPreprocessedEntity(
unsigned Index) {
357 assert(Index < LoadedPreprocessedEntities.size() &&
358 "Out-of bounds loaded preprocessed entity");
359 assert(ExternalSource &&
"No external source to load from");
362 Entity = ExternalSource->ReadPreprocessedEntity(Index);
372 llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
373 MacroDefinitions.find(MI);
374 if (Pos == MacroDefinitions.end())
380 void PreprocessingRecord::addMacroExpansion(
const Token &
Id,
410 void PreprocessingRecord::Defined(
const Token &MacroNameTok,
419 void PreprocessingRecord::SourceRangeSkipped(
SourceRange Range,
421 SkippedRanges.emplace_back(Range.
getBegin(), EndifLoc);
424 void PreprocessingRecord::MacroExpands(
const Token &Id,
431 void PreprocessingRecord::MacroDefined(
const Token &Id,
438 MacroDefinitions[MI] = Def;
441 void PreprocessingRecord::MacroUndefined(
const Token &Id,
447 void PreprocessingRecord::InclusionDirective(
449 const Token &IncludeTok,
454 StringRef SearchPath,
455 StringRef RelativePath,
460 case tok::pp_include:
468 case tok::pp_include_next:
472 case tok::pp___include_macros:
477 llvm_unreachable(
"Unknown include directive kind");
484 EndLoc = FilenameRange.
getEnd();
491 (
bool)Imported, File,
497 return BumpAlloc.getTotalMemory()
498 + llvm::capacity_in_bytes(MacroDefinitions)
499 + llvm::capacity_in_bytes(PreprocessedEntities)
500 + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
Defines the SourceManager interface.
bool isLocalSourceLocation(SourceLocation Loc) const
Returns true if Loc did not come from a PCH/Module.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
Defines the clang::MacroInfo and clang::MacroDirective classes.
A description of the current definition of a macro.
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...
size_t getTotalMemory() const
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.
Records the presence of a preprocessor directive.
SourceLocation getBegin() const
Iteration over the preprocessed entities.
Record the location of a macro definition.
Token - This structure provides full information about a lexed token.
Describes a module or submodule.
llvm::iterator_range< iterator > getPreprocessedEntitiesInRange(SourceRange R)
Returns a range of preprocessed entities that source range R encompasses.
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...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
virtual ~ExternalPreprocessingRecordSource()
Records the location of a macro expansion.
PreprocessingRecord(SourceManager &SM)
Construct a new preprocessing record.
A GNU #include_next directive.
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.
static bool isPreprocessedEntityIfInFileID(PreprocessedEntity *PPE, FileID FID, SourceManager &SM)
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Record the location of an inclusion directive, such as an #include or #import statement.
InclusionKind
The kind of inclusion directives known to the preprocessor.
SourceLocation getEnd() const
InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind, StringRef FileName, bool InQuotes, bool ImportedModule, const FileEntry *File, SourceRange Range)
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Encodes a location in the source.
IdentifierInfo * getIdentifierInfo() const
Cached information about one file (either on disk or in the virtual file system). ...
An abstract class that should be subclassed by any external source of preprocessing record entries...
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location...
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.
const MacroInfo * getMacroInfo() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
Encapsulates the data about a macro definition (e.g.
PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity)
Add a new preprocessed entity to this record.
An Objective-C #import directive.
SourceLocation getEnd() const
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
Defines the clang::TokenKind enum and support functions.
SourceLocation getDefinitionEndLoc() const
Return the location of the last token in the macro.
Defines the clang::SourceLocation class and associated facilities.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
MacroDefinitionRecord * findMacroDefinition(const MacroInfo *MI)
Retrieve the macro definition that corresponds to the given MacroInfo.
void forAllDefinitions(Fn F) const
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
void SetExternalSource(ExternalPreprocessingRecordSource &Source)
Set the external source for preprocessed entities.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
This class handles loading and caching of source files into memory.