summaryrefslogtreecommitdiff
path: root/include/clang/Basic/SourceManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Basic/SourceManager.h')
-rw-r--r--include/clang/Basic/SourceManager.h206
1 files changed, 140 insertions, 66 deletions
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 985ddd641271c..bcb2d561a4e4d 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -102,7 +102,39 @@ namespace SrcMgr {
/// NumLines - The number of lines in this ContentCache. This is only valid
/// if SourceLineCache is non-null.
- unsigned NumLines;
+ unsigned NumLines : 31;
+
+ /// \brief Indicates whether the buffer itself was provided to override
+ /// the actual file contents.
+ ///
+ /// When true, the original entry may be a virtual file that does not
+ /// exist.
+ unsigned BufferOverridden : 1;
+
+ ContentCache(const FileEntry *Ent = 0)
+ : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
+ SourceLineCache(0), NumLines(0), BufferOverridden(false) {}
+
+ ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
+ : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
+ SourceLineCache(0), NumLines(0), BufferOverridden(false) {}
+
+ ~ContentCache();
+
+ /// The copy ctor does not allow copies where source object has either
+ /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
+ /// is not transferred, so this is a logical error.
+ ContentCache(const ContentCache &RHS)
+ : Buffer(0, false), SourceLineCache(0), BufferOverridden(false)
+ {
+ OrigEntry = RHS.OrigEntry;
+ ContentsEntry = RHS.ContentsEntry;
+
+ assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 &&
+ "Passed ContentCache object cannot own a buffer.");
+
+ NumLines = RHS.NumLines;
+ }
/// getBuffer - Returns the memory buffer for the associated content.
///
@@ -159,31 +191,6 @@ namespace SrcMgr {
return (Buffer.getInt() & DoNotFreeFlag) == 0;
}
- ContentCache(const FileEntry *Ent = 0)
- : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
- SourceLineCache(0), NumLines(0) {}
-
- ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
- : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
- SourceLineCache(0), NumLines(0) {}
-
- ~ContentCache();
-
- /// The copy ctor does not allow copies where source object has either
- /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
- /// is not transferred, so this is a logical error.
- ContentCache(const ContentCache &RHS)
- : Buffer(0, false), SourceLineCache(0)
- {
- OrigEntry = RHS.OrigEntry;
- ContentsEntry = RHS.ContentsEntry;
-
- assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 &&
- "Passed ContentCache object cannot own a buffer.");
-
- NumLines = RHS.NumLines;
- }
-
private:
// Disable assignments.
ContentCache &operator=(const ContentCache& RHS);
@@ -293,6 +300,11 @@ namespace SrcMgr {
SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid();
}
+ bool isFunctionMacroExpansion() const {
+ return getExpansionLocStart().isValid() &&
+ getExpansionLocStart() != getExpansionLocEnd();
+ }
+
/// create - Return a ExpansionInfo for an expansion. Start and End specify
/// the expansion range (where the macro is expanded), and SpellingLoc
/// specifies the spelling location (where the characters from the token
@@ -431,8 +443,7 @@ public:
// to determine which came first. This will also take care the case where
// one of the locations points at the inclusion/expansion point of the other
// in which case its FileID will come before the other.
- if (LOffset == ROffset &&
- (LQueryFID != CommonFID || RQueryFID != CommonFID))
+ if (LOffset == ROffset)
return IsLQFIDBeforeRQFID;
return LOffset < ROffset;
@@ -472,7 +483,7 @@ public:
/// the case of a macro expansion, for example, the spelling location indicates
/// where the expanded token came from and the expansion location specifies
/// where it was expanded.
-class SourceManager : public llvm::RefCountedBase<SourceManager> {
+class SourceManager : public RefCountedBase<SourceManager> {
/// \brief DiagnosticsEngine object.
DiagnosticsEngine &Diag;
@@ -508,7 +519,7 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> {
///
/// Negative FileIDs are indexes into this table. To get from ID to an index,
/// use (-ID - 2).
- std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable;
+ mutable std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable;
/// \brief The starting offset of the next local SLocEntry.
///
@@ -565,11 +576,13 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> {
// Cache for the "fake" buffer used for error-recovery purposes.
mutable llvm::MemoryBuffer *FakeBufferForRecovery;
+ mutable SrcMgr::ContentCache *FakeContentCacheForRecovery;
+
/// \brief Lazily computed map of macro argument chunks to their expanded
/// source location.
typedef std::map<unsigned, SourceLocation> MacroArgsMap;
- mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap;
+ mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap;
// SourceManager doesn't support copy construction.
explicit SourceManager(const SourceManager&);
@@ -607,12 +620,19 @@ public:
FileID getMainFileID() const { return MainFileID; }
/// createMainFileID - Create the FileID for the main source file.
- FileID createMainFileID(const FileEntry *SourceFile) {
+ FileID createMainFileID(const FileEntry *SourceFile,
+ SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
- MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
+ MainFileID = createFileID(SourceFile, SourceLocation(), Kind);
return MainFileID;
}
+ /// \brief Set the file ID for the main source file.
+ void setMainFileID(FileID FID) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
+ MainFileID = FID;
+ }
+
/// \brief Set the file ID for the precompiled preamble.
void setPreambleFileID(FileID Preamble) {
assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
@@ -641,8 +661,9 @@ public:
/// specified memory buffer. This does no caching of the buffer and takes
/// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
- int LoadedID = 0, unsigned LoadedOffset = 0) {
- return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
+ int LoadedID = 0, unsigned LoadedOffset = 0,
+ SourceLocation IncludeLoc = SourceLocation()) {
+ return createFileID(createMemBufferContentCache(Buffer), IncludeLoc,
SrcMgr::C_User, LoadedID, LoadedOffset);
}
@@ -738,13 +759,19 @@ public:
if (MyInvalid || !Entry.isFile())
return 0;
- return Entry.getFile().getContentCache()->OrigEntry;
+ const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache();
+ if (!Content)
+ return 0;
+ return Content->OrigEntry;
}
/// Returns the FileEntry record for the provided SLocEntry.
const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
{
- return sloc.getFile().getContentCache()->OrigEntry;
+ const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache();
+ if (!Content)
+ return 0;
+ return Content->OrigEntry;
}
/// getBufferData - Return a StringRef to the source buffer data for the
@@ -755,7 +782,7 @@ public:
StringRef getBufferData(FileID FID, bool *Invalid = 0) const;
/// \brief Get the number of FileIDs (files and macros) that were created
- /// during preprocessing of \arg FID, including it.
+ /// during preprocessing of \p FID, including it.
unsigned getNumCreatedFIDsForFileID(FileID FID) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
@@ -766,7 +793,7 @@ public:
}
/// \brief Set the number of FileIDs (files and macros) that were created
- /// during preprocessing of \arg FID, including it.
+ /// during preprocessing of \p FID, including it.
void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const {
bool Invalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
@@ -807,8 +834,20 @@ public:
unsigned FileOffset = Entry.getOffset();
return SourceLocation::getFileLoc(FileOffset);
}
+
+ /// \brief Return the source location corresponding to the last byte of the
+ /// specified file.
+ SourceLocation getLocForEndOfFile(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return SourceLocation();
+
+ unsigned FileOffset = Entry.getOffset();
+ return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID) - 1);
+ }
- /// \brief Returns the include location if \arg FID is a #include'd file
+ /// \brief Returns the include location if \p FID is a #include'd file
/// otherwise it returns an invalid location.
SourceLocation getIncludeLoc(FileID FID) const {
bool Invalid = false;
@@ -828,7 +867,7 @@ public:
return getExpansionLocSlowCase(Loc);
}
- /// \brief Given \arg Loc, if it is a macro location return the expansion
+ /// \brief Given \p Loc, if it is a macro location return the expansion
/// location or the spelling location, depending on if it comes from a
/// macro argument or not.
SourceLocation getFileLoc(SourceLocation Loc) const {
@@ -868,7 +907,11 @@ public:
/// offset from the start of the buffer of the location.
std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
- return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset());
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &E = getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return std::make_pair(FileID(), 0);
+ return std::make_pair(FID, Loc.getOffset()-E.getOffset());
}
/// getDecomposedExpansionLoc - Decompose the specified location into a raw
@@ -877,7 +920,10 @@ public:
std::pair<FileID, unsigned>
getDecomposedExpansionLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
- const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return std::make_pair(FileID(), 0);
unsigned Offset = Loc.getOffset()-E->getOffset();
if (Loc.isFileID())
@@ -892,7 +938,10 @@ public:
std::pair<FileID, unsigned>
getDecomposedSpellingLoc(SourceLocation Loc) const {
FileID FID = getFileID(Loc);
- const SrcMgr::SLocEntry *E = &getSLocEntry(FID);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return std::make_pair(FileID(), 0);
unsigned Offset = Loc.getOffset()-E->getOffset();
if (Loc.isFileID())
@@ -914,10 +963,10 @@ public:
/// expanded.
bool isMacroArgExpansion(SourceLocation Loc) const;
- /// \brief Returns true if \arg Loc is inside the [\arg Start, +\arg Length)
+ /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length)
/// chunk of the source location address space.
- /// If it's true and \arg RelativeOffset is non-null, it will be set to the
- /// relative offset of \arg Loc inside the chunk.
+ /// If it's true and \p RelativeOffset is non-null, it will be set to the
+ /// relative offset of \p Loc inside the chunk.
bool isInSLocAddrSpace(SourceLocation Loc,
SourceLocation Start, unsigned Length,
unsigned *RelativeOffset = 0) const {
@@ -938,10 +987,10 @@ public:
return false;
}
- /// \brief Return true if both \arg LHS and \arg RHS are in the local source
- /// location address space or the loaded one. If it's true and
- /// \arg RelativeOffset is non-null, it will be set to the offset of \arg RHS
- /// relative to \arg LHS.
+ /// \brief Return true if both \p LHS and \p RHS are in the local source
+ /// location address space or the loaded one. If it's true and \p
+ /// RelativeOffset is non-null, it will be set to the offset of \p RHS
+ /// relative to \p LHS.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS,
int *RelativeOffset) const {
unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset();
@@ -1041,12 +1090,17 @@ public:
return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
}
- /// \brief The size of the SLocEnty that \arg FID represents.
+ /// \brief Returns whether \p Loc is expanded from a macro in a system header.
+ bool isInSystemMacro(SourceLocation loc) {
+ return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc));
+ }
+
+ /// \brief The size of the SLocEnty that \p FID represents.
unsigned getFileIDSize(FileID FID) const;
- /// \brief Given a specific FileID, returns true if \arg Loc is inside that
- /// FileID chunk and sets relative offset (offset of \arg Loc from beginning
- /// of FileID) to \arg relativeOffset.
+ /// \brief Given a specific FileID, returns true if \p Loc is inside that
+ /// FileID chunk and sets relative offset (offset of \p Loc from beginning
+ /// of FileID) to \p relativeOffset.
bool isInFileID(SourceLocation Loc, FileID FID,
unsigned *RelativeOffset = 0) const {
unsigned Offs = Loc.getOffset();
@@ -1124,12 +1178,12 @@ public:
/// first inclusion.
FileID translateFile(const FileEntry *SourceFile) const;
- /// \brief Get the source location in \arg FID for the given line:col.
- /// Returns null location if \arg FID is not a file SLocEntry.
+ /// \brief Get the source location in \p FID for the given line:col.
+ /// Returns null location if \p FID is not a file SLocEntry.
SourceLocation translateLineCol(FileID FID,
unsigned Line, unsigned Col) const;
- /// \brief If \arg Loc points inside a function macro argument, the returned
+ /// \brief If \p Loc points inside a function macro argument, the returned
/// location will be the macro location in which the argument was expanded.
/// If a macro argument is used multiple times, the expanded location will
/// be at the first expansion of the argument.
@@ -1205,14 +1259,19 @@ public:
unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();}
/// \brief Get a loaded SLocEntry. This is exposed for indexing.
- const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid=0) const {
+ const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index,
+ bool *Invalid = 0) const {
assert(Index < LoadedSLocEntryTable.size() && "Invalid index");
- if (!SLocEntryLoaded[Index])
- ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2));
- return LoadedSLocEntryTable[Index];
+ if (SLocEntryLoaded[Index])
+ return LoadedSLocEntryTable[Index];
+ return loadSLocEntry(Index, Invalid);
}
const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const {
+ if (FID.ID == 0 || FID.ID == -1) {
+ if (Invalid) *Invalid = true;
+ return LocalSLocEntryTable[0];
+ }
return getSLocEntryByID(FID.ID);
}
@@ -1233,18 +1292,32 @@ public:
std::pair<int, unsigned>
AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize);
- /// \brief Returns true if \arg Loc came from a PCH/Module.
+ /// \brief Returns true if \p Loc came from a PCH/Module.
bool isLoadedSourceLocation(SourceLocation Loc) const {
return Loc.getOffset() >= CurrentLoadedOffset;
}
- /// \brief Returns true if \arg Loc did not come from a PCH/Module.
+ /// \brief Returns true if \p Loc did not come from a PCH/Module.
bool isLocalSourceLocation(SourceLocation Loc) const {
return Loc.getOffset() < NextLocalOffset;
}
+ /// \brief Returns true if \p FID came from a PCH/Module.
+ bool isLoadedFileID(FileID FID) const {
+ assert(FID.ID != -1 && "Using FileID sentinel value");
+ return FID.ID < 0;
+ }
+
+ /// \brief Returns true if \p FID did not come from a PCH/Module.
+ bool isLocalFileID(FileID FID) const {
+ return !isLoadedFileID(FID);
+ }
+
private:
const llvm::MemoryBuffer *getFakeBufferForRecovery() const;
+ const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const;
+
+ const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const;
/// \brief Get the entry with the given unwrapped FileID.
const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const {
@@ -1254,8 +1327,9 @@ private:
return getLocalSLocEntry(static_cast<unsigned>(ID));
}
- const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const {
- return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2));
+ const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID,
+ bool *Invalid = 0) const {
+ return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid);
}
/// createExpansionLoc - Implements the common elements of storing an