17 #include "llvm/Support/Capacity.h"
18 #include "llvm/Support/ErrorHandling.h"
20 using namespace clang;
28 bool InQuotes,
bool ImportedModule,
32 InQuotes(InQuotes), Kind(Kind), ImportedModule(ImportedModule), File(File)
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());
43 ExternalSource(nullptr) {
48 llvm::iterator_range<PreprocessingRecord::iterator>
53 if (CachedRangeQuery.Range == Range) {
54 return llvm::make_range(
iterator(
this, CachedRangeQuery.Result.first),
55 iterator(
this, CachedRangeQuery.Result.second));
58 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
60 CachedRangeQuery.Range =
Range;
61 CachedRangeQuery.Result = Res;
63 return llvm::make_range(
iterator(
this, Res.first),
93 if (
unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
94 assert(0 &&
"Out-of bounds loaded preprocessed entity");
97 assert(ExternalSource &&
"No external source to load from");
98 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
106 if (IsInFile.hasValue())
107 return IsInFile.getValue();
112 getLoadedPreprocessedEntity(LoadedIndex),
116 if (
unsigned(Pos) >= PreprocessedEntities.size()) {
117 assert(0 &&
"Out-of bounds local preprocessed entity");
127 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(
SourceRange Range) {
131 std::pair<unsigned, unsigned>
132 Local = findLocalPreprocessedEntitiesInRange(Range);
136 return std::make_pair(Local.first, Local.second);
138 std::pair<unsigned, unsigned>
142 if (Loaded.first == Loaded.second)
143 return std::make_pair(Local.first, Local.second);
145 unsigned TotalLoaded = LoadedPreprocessedEntities.size();
148 if (Local.first == Local.second)
149 return std::make_pair(
int(Loaded.first)-TotalLoaded,
150 int(Loaded.second)-TotalLoaded);
153 return std::make_pair(
int(Loaded.first)-TotalLoaded, Local.second);
156 std::pair<unsigned, unsigned>
157 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
160 return std::make_pair(0,0);
163 unsigned Begin = findBeginLocalPreprocessedEntity(Range.
getBegin());
164 unsigned End = findEndLocalPreprocessedEntity(Range.
getEnd());
165 return std::make_pair(Begin, End);
170 template <SourceLocation (SourceRange::*getRangeLoc)() const>
171 struct PPEntityComp {
194 return (Range.*getRangeLoc)();
200 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
205 size_t Count = PreprocessedEntities.size();
207 std::vector<PreprocessedEntity *>::const_iterator
208 First = PreprocessedEntities.begin();
209 std::vector<PreprocessedEntity *>::const_iterator
I;
218 std::advance(I, Half);
223 Count = Count - Half - 1;
228 return First - PreprocessedEntities.begin();
231 unsigned PreprocessingRecord::findEndLocalPreprocessedEntity(
236 std::vector<PreprocessedEntity *>::const_iterator
237 I = std::upper_bound(PreprocessedEntities.begin(),
238 PreprocessedEntities.end(),
240 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
241 return I - PreprocessedEntities.begin();
244 PreprocessingRecord::PPEntityID
249 if (isa<MacroDefinitionRecord>(Entity)) {
250 assert((PreprocessedEntities.empty() ||
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,
false);
260 if (PreprocessedEntities.empty() ||
262 PreprocessedEntities.back()->getSourceRange().getBegin())) {
263 PreprocessedEntities.push_back(Entity);
264 return getPPEntityID(PreprocessedEntities.size()-1,
false);
284 for (pp_iter RI = PreprocessedEntities.end(),
285 Begin = PreprocessedEntities.begin();
286 RI != Begin && count < 4; --RI, ++count) {
290 (*I)->getSourceRange().getBegin())) {
291 pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
292 return getPPEntityID(insertI - PreprocessedEntities.begin(),
298 pp_iter I = std::upper_bound(PreprocessedEntities.begin(),
299 PreprocessedEntities.end(),
301 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
302 pp_iter insertI = PreprocessedEntities.insert(I, Entity);
303 return getPPEntityID(insertI - PreprocessedEntities.begin(),
309 assert(!ExternalSource &&
310 "Preprocessing record already has an external source");
311 ExternalSource = &Source;
314 unsigned PreprocessingRecord::allocateLoadedEntities(
unsigned NumEntities) {
315 unsigned Result = LoadedPreprocessedEntities.size();
316 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
321 void PreprocessingRecord::RegisterMacroDefinition(
MacroInfo *Macro,
323 MacroDefinitions[Macro] = Def;
329 unsigned Index = -PPID.ID - 1;
330 assert(Index < LoadedPreprocessedEntities.size() &&
331 "Out-of bounds loaded preprocessed entity");
332 return getLoadedPreprocessedEntity(Index);
337 unsigned Index = PPID.ID - 1;
338 assert(Index < PreprocessedEntities.size() &&
339 "Out-of bounds local preprocessed entity");
340 return PreprocessedEntities[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");
362 MacroDefinitions.find(MI);
363 if (Pos == MacroDefinitions.end())
369 void PreprocessingRecord::addMacroExpansion(
const Token &Id,
399 void PreprocessingRecord::Defined(
const Token &MacroNameTok,
408 void PreprocessingRecord::SourceRangeSkipped(
SourceRange Range) {
409 SkippedRanges.push_back(Range);
412 void PreprocessingRecord::MacroExpands(
const Token &Id,
419 void PreprocessingRecord::MacroDefined(
const Token &Id,
426 MacroDefinitions[MI] = Def;
429 void PreprocessingRecord::MacroUndefined(
const Token &Id,
434 void PreprocessingRecord::InclusionDirective(
441 StringRef SearchPath,
442 StringRef RelativePath,
447 case tok::pp_include:
455 case tok::pp_include_next:
459 case tok::pp___include_macros:
464 llvm_unreachable(
"Unknown include directive kind");
471 EndLoc = FilenameRange.
getEnd();
484 return BumpAlloc.getTotalMemory()
485 + llvm::capacity_in_bytes(MacroDefinitions)
486 + llvm::capacity_in_bytes(PreprocessedEntities)
487 + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
SourceLocation getEnd() const
SourceLocation getBegin() const
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...
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.
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.
Describes a module or submodule.
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
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
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.
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 ...
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
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)
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Encodes a location in the source.
const TemplateArgument * iterator
Cached information about one file (either on disk or in the virtual file system). ...
void forAllDefinitions(Fn F) const
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.
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
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.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
size_t getTotalMemory() 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.
This class handles loading and caching of source files into memory.
IdentifierInfo * getIdentifierInfo() const
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.