diff options
Diffstat (limited to 'include/clang/Basic/SourceManager.h')
-rw-r--r-- | include/clang/Basic/SourceManager.h | 206 |
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 |