22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/Optional.h" 24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/ADT/iterator_range.h" 26 #include "llvm/Support/Capacity.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/ErrorHandling.h" 37 using namespace clang;
44 bool InQuotes,
bool ImportedModule,
47 Kind(Kind), ImportedModule(ImportedModule), File(File) {
48 char *Memory = (
char *)PPRec.
Allocate(FileName.size() + 1,
alignof(char));
49 memcpy(Memory, FileName.data(), FileName.size());
50 Memory[FileName.size()] = 0;
51 this->FileName = StringRef(Memory, FileName.size());
58 llvm::iterator_range<PreprocessingRecord::iterator>
63 if (CachedRangeQuery.Range == Range) {
64 return llvm::make_range(
iterator(
this, CachedRangeQuery.Result.first),
65 iterator(
this, CachedRangeQuery.Result.second));
68 std::pair<int, int> Res = getPreprocessedEntitiesInRangeSlow(Range);
70 CachedRangeQuery.Range =
Range;
71 CachedRangeQuery.Result = Res;
73 return llvm::make_range(
iterator(
this, Res.first),
103 if (
unsigned(-Pos-1) >= LoadedPreprocessedEntities.size()) {
104 assert(0 &&
"Out-of bounds loaded preprocessed entity");
107 assert(ExternalSource &&
"No external source to load from");
108 unsigned LoadedIndex = LoadedPreprocessedEntities.size()+Pos;
116 if (IsInFile.hasValue())
117 return IsInFile.getValue();
122 getLoadedPreprocessedEntity(LoadedIndex),
126 if (
unsigned(Pos) >= PreprocessedEntities.size()) {
127 assert(0 &&
"Out-of bounds local preprocessed entity");
137 PreprocessingRecord::getPreprocessedEntitiesInRangeSlow(
SourceRange Range) {
141 std::pair<unsigned, unsigned>
142 Local = findLocalPreprocessedEntitiesInRange(Range);
146 return std::make_pair(Local.first, Local.second);
148 std::pair<unsigned, unsigned>
152 if (Loaded.first == Loaded.second)
153 return std::make_pair(Local.first, Local.second);
155 unsigned TotalLoaded = LoadedPreprocessedEntities.size();
158 if (Local.first == Local.second)
159 return std::make_pair(
int(Loaded.first)-TotalLoaded,
160 int(Loaded.second)-TotalLoaded);
163 return std::make_pair(
int(Loaded.first)-TotalLoaded, Local.second);
166 std::pair<unsigned, unsigned>
167 PreprocessingRecord::findLocalPreprocessedEntitiesInRange(
170 return std::make_pair(0,0);
173 unsigned Begin = findBeginLocalPreprocessedEntity(Range.
getBegin());
174 unsigned End = findEndLocalPreprocessedEntity(Range.
getEnd());
175 return std::make_pair(Begin, End);
180 template <SourceLocation (SourceRange::*getRangeLoc)() const>
181 struct PPEntityComp {
204 return (Range.*getRangeLoc)();
210 unsigned PreprocessingRecord::findBeginLocalPreprocessedEntity(
212 if (SourceMgr.isLoadedSourceLocation(Loc))
215 size_t Count = PreprocessedEntities.size();
217 std::vector<PreprocessedEntity *>::const_iterator
218 First = PreprocessedEntities.begin();
219 std::vector<PreprocessedEntity *>::const_iterator I;
228 std::advance(I, Half);
229 if (SourceMgr.isBeforeInTranslationUnit((*I)->getSourceRange().getEnd(),
233 Count = Count - Half - 1;
238 return First - PreprocessedEntities.begin();
242 PreprocessingRecord::findEndLocalPreprocessedEntity(
SourceLocation Loc)
const {
243 if (SourceMgr.isLoadedSourceLocation(Loc))
246 auto I = llvm::upper_bound(PreprocessedEntities, Loc,
247 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
248 return I - PreprocessedEntities.begin();
251 PreprocessingRecord::PPEntityID
256 if (isa<MacroDefinitionRecord>(Entity)) {
257 assert((PreprocessedEntities.empty() ||
258 !SourceMgr.isBeforeInTranslationUnit(
260 PreprocessedEntities.back()->getSourceRange().getBegin())) &&
261 "a macro definition was encountered out-of-order");
262 PreprocessedEntities.push_back(Entity);
263 return getPPEntityID(PreprocessedEntities.size()-1,
false);
267 if (PreprocessedEntities.empty() ||
268 !SourceMgr.isBeforeInTranslationUnit(BeginLoc,
269 PreprocessedEntities.back()->getSourceRange().getBegin())) {
270 PreprocessedEntities.push_back(Entity);
271 return getPPEntityID(PreprocessedEntities.size()-1,
false);
286 using pp_iter = std::vector<PreprocessedEntity *>::iterator;
291 for (pp_iter RI = PreprocessedEntities.end(),
292 Begin = PreprocessedEntities.begin();
293 RI !=
Begin && count < 4; --RI, ++count) {
296 if (!SourceMgr.isBeforeInTranslationUnit(BeginLoc,
297 (*I)->getSourceRange().getBegin())) {
298 pp_iter insertI = PreprocessedEntities.insert(RI, Entity);
299 return getPPEntityID(insertI - PreprocessedEntities.begin(),
306 llvm::upper_bound(PreprocessedEntities, BeginLoc,
307 PPEntityComp<&SourceRange::getBegin>(SourceMgr));
308 pp_iter insertI = PreprocessedEntities.insert(I, Entity);
309 return getPPEntityID(insertI - PreprocessedEntities.begin(),
315 assert(!ExternalSource &&
316 "Preprocessing record already has an external source");
317 ExternalSource = &Source;
320 unsigned PreprocessingRecord::allocateLoadedEntities(
unsigned NumEntities) {
321 unsigned Result = LoadedPreprocessedEntities.size();
322 LoadedPreprocessedEntities.resize(LoadedPreprocessedEntities.size()
327 unsigned PreprocessingRecord::allocateSkippedRanges(
unsigned NumRanges) {
328 unsigned Result = SkippedRanges.size();
329 SkippedRanges.resize(SkippedRanges.size() + NumRanges);
330 SkippedRangesAllLoaded =
false;
334 void PreprocessingRecord::ensureSkippedRangesLoaded() {
335 if (SkippedRangesAllLoaded || !ExternalSource)
337 for (
unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
339 SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
341 SkippedRangesAllLoaded =
true;
344 void PreprocessingRecord::RegisterMacroDefinition(
MacroInfo *Macro,
346 MacroDefinitions[Macro] = Def;
352 unsigned Index = -PPID.ID - 1;
353 assert(Index < LoadedPreprocessedEntities.size() &&
354 "Out-of bounds loaded preprocessed entity");
355 return getLoadedPreprocessedEntity(Index);
360 unsigned Index = PPID.ID - 1;
361 assert(Index < PreprocessedEntities.size() &&
362 "Out-of bounds local preprocessed entity");
363 return PreprocessedEntities[Index];
368 PreprocessingRecord::getLoadedPreprocessedEntity(
unsigned Index) {
369 assert(Index < LoadedPreprocessedEntities.size() &&
370 "Out-of bounds loaded preprocessed entity");
371 assert(ExternalSource &&
"No external source to load from");
374 Entity = ExternalSource->ReadPreprocessedEntity(Index);
384 llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *>::iterator Pos =
385 MacroDefinitions.find(MI);
386 if (Pos == MacroDefinitions.end())
392 void PreprocessingRecord::addMacroExpansion(
const Token &
Id,
422 void PreprocessingRecord::Defined(
const Token &MacroNameTok,
431 void PreprocessingRecord::SourceRangeSkipped(
SourceRange Range,
434 SkippedRanges.emplace_back(Range.
getBegin(), EndifLoc);
437 void PreprocessingRecord::MacroExpands(
const Token &Id,
444 void PreprocessingRecord::MacroDefined(
const Token &Id,
451 MacroDefinitions[MI] = Def;
454 void PreprocessingRecord::MacroUndefined(
const Token &Id,
460 void PreprocessingRecord::InclusionDirective(
462 const Token &IncludeTok,
467 StringRef SearchPath,
468 StringRef RelativePath,
491 llvm_unreachable(
"Unknown include directive kind");
498 EndLoc = FilenameRange.
getEnd();
505 (
bool)Imported, File,
511 return BumpAlloc.getTotalMemory()
512 + llvm::capacity_in_bytes(MacroDefinitions)
513 + llvm::capacity_in_bytes(PreprocessedEntities)
514 + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
515 + llvm::capacity_in_bytes(SkippedRanges);
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.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
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...
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
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...
static bool isInvalid(LocType Loc, bool *Invalid)
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.