diff options
22 files changed, 927 insertions, 479 deletions
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 6f72976bfc..20eebaff08 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -16,6 +16,7 @@ #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" @@ -984,6 +985,10 @@ public: StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); StoredDiagnostic(Diagnostic::Level Level, unsigned ID, llvm::StringRef Message); + StoredDiagnostic(Diagnostic::Level Level, unsigned ID, + llvm::StringRef Message, FullSourceLoc Loc, + llvm::ArrayRef<CharSourceRange> Ranges, + llvm::ArrayRef<FixItHint> Fixits); ~StoredDiagnostic(); /// \brief Evaluates true when this object stores a diagnostic. diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index ee5f96fe93..1cbcd4007f 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -35,8 +35,9 @@ class SourceManager; /// a source file (MemoryBuffer) along with its #include path and #line data. /// class FileID { - /// ID - Opaque identifier, 0 is "invalid". - unsigned ID; + /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is + /// something loaded from another module. + int ID; public: FileID() : ID(0) {} @@ -49,26 +50,38 @@ public: bool operator>(const FileID &RHS) const { return RHS < *this; } bool operator>=(const FileID &RHS) const { return RHS <= *this; } - static FileID getSentinel() { return get(~0U); } - unsigned getHashValue() const { return ID; } + static FileID getSentinel() { return get(-1); } + unsigned getHashValue() const { return static_cast<unsigned>(ID); } private: friend class SourceManager; friend class ASTWriter; friend class ASTReader; - static FileID get(unsigned V) { + static FileID get(int V) { FileID F; F.ID = V; return F; } - unsigned getOpaqueValue() const { return ID; } + int getOpaqueValue() const { return ID; } }; -/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes -/// a full include stack, line and column number information for a position in -/// an input translation unit. +/// \brief Encodes a location in the source. The SourceManager can decode this +/// to get at the full include stack, line and column information. +/// +/// Technically, a source location is simply an offset into the manager's view +/// of the input source, which is all input buffers (including macro +/// instantiations) concatenated in an effectively arbitrary order. The manager +/// actually maintains two blocks of input buffers. One, starting at offset 0 +/// and growing upwards, contains all buffers from this module. The other, +/// starting at the highest possible offset and growing downwards, contains +/// buffers of loaded modules. +/// +/// In addition, one bit of SourceLocation is used for quick access to the +/// information whether the location is in a file or a macro instantiation. +/// +/// It is important that this type remains small. It is currently 32 bits wide. class SourceLocation { unsigned ID; friend class SourceManager; @@ -77,21 +90,21 @@ class SourceLocation { }; public: - SourceLocation() : ID(0) {} // 0 is an invalid FileID. + SourceLocation() : ID(0) {} bool isFileID() const { return (ID & MacroIDBit) == 0; } bool isMacroID() const { return (ID & MacroIDBit) != 0; } - /// isValid - Return true if this is a valid SourceLocation object. Invalid - /// SourceLocations are often used when events have no corresponding location - /// in the source (e.g. a diagnostic is required for a command line option). + /// \brief Return true if this is a valid SourceLocation object. /// + /// Invalid SourceLocations are often used when events have no corresponding + /// location in the source (e.g. a diagnostic is required for a command line + /// option). bool isValid() const { return ID != 0; } bool isInvalid() const { return ID == 0; } private: - /// getOffset - Return the index for SourceManager's SLocEntryTable table, - /// note that this is not an index *into* it though. + /// \brief Return the offset into the manager's global input view. unsigned getOffset() const { return ID & ~MacroIDBit; } @@ -114,7 +127,8 @@ public: /// getFileLocWithOffset - Return a source location with the specified offset /// from this file SourceLocation. SourceLocation getFileLocWithOffset(int Offset) const { - assert(((getOffset()+Offset) & MacroIDBit) == 0 && "invalid location"); + assert(((getOffset()+Offset) & MacroIDBit) == 0 && + "offset overflow or macro loc"); SourceLocation L; L.ID = ID+Offset; return L; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 6301f31978..c08e691344 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -46,7 +46,7 @@ namespace SrcMgr { /// holds normal user code, system code, or system code which is implicitly /// 'extern "C"' in C++ mode. Entire directories can be tagged with this /// (this is maintained by DirectoryLookup and friends) as can specific - /// FileIDInfos when a #pragma system_header is seen or various other cases. + /// FileInfos when a #pragma system_header is seen or various other cases. /// enum CharacteristicKind { C_User, C_System, C_ExternCSystem @@ -356,11 +356,12 @@ class ExternalSLocEntrySource { public: virtual ~ExternalSLocEntrySource(); - /// \brief Read the source location entry with index ID. + /// \brief Read the source location entry with index ID, which will always be + /// less than -1. /// /// \returns true if an error occurred that prevented the source-location /// entry from being loaded. - virtual bool ReadSLocEntry(unsigned ID) = 0; + virtual bool ReadSLocEntry(int ID) = 0; }; @@ -414,8 +415,9 @@ public: }; -/// SourceManager - This file handles loading and caching of source files into -/// memory. This object owns the MemoryBuffer objects for all of the loaded +/// \brief This class handles loading and caching of source files into memory. +/// +/// This object owns the MemoryBuffer objects for all of the loaded /// files and assigns unique FileID's for each unique #include chain. /// /// The SourceManager can be queried for information about SourceLocation @@ -451,16 +453,33 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> { /// as they do not refer to a file. std::vector<SrcMgr::ContentCache*> MemBufferInfos; - /// SLocEntryTable - This is an array of SLocEntry's that we have created. - /// FileID is an index into this vector. This array is sorted by the offset. - std::vector<SrcMgr::SLocEntry> SLocEntryTable; - /// NextOffset - This is the next available offset that a new SLocEntry can - /// start at. It is SLocEntryTable.back().getOffset()+size of back() entry. - unsigned NextOffset; + /// \brief The table of SLocEntries that are local to this module. + /// + /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid + /// instantiation. + std::vector<SrcMgr::SLocEntry> LocalSLocEntryTable; + + /// \brief The table of SLocEntries that are loaded from other modules. + /// + /// Negative FileIDs are indexes into this table. To get from ID to an index, + /// use (-ID - 2). + std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable; - /// \brief If source location entries are being lazily loaded from - /// an external source, this vector indicates whether the Ith source - /// location entry has already been loaded from the external storage. + /// \brief The starting offset of the next local SLocEntry. + /// + /// This is LocalSLocEntryTable.back().Offset + the size of that entry. + unsigned NextLocalOffset; + + /// \brief The starting offset of the latest batch of loaded SLocEntries. + /// + /// This is LoadedSLocEntryTable.back().Offset, except that that entry might + /// not have been loaded, so that value would be unknown. + unsigned CurrentLoadedOffset; + + /// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable + /// have already been loaded from the external source. + /// + /// Same indexing as LoadedSLocEntryTable. std::vector<bool> SLocEntryLoaded; /// \brief An external source for source location entries. @@ -513,6 +532,15 @@ public: OverridenFilesKeepOriginalName = value; } + /// createMainFileIDForMembuffer - Create the FileID for a memory buffer + /// that will represent the FileID for the main source. One example + /// of when this would be used is when the main source is read from STDIN. + FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) { + assert(MainFileID.isInvalid() && "MainFileID already set!"); + MainFileID = createFileIDForMemBuffer(Buffer); + return MainFileID; + } + //===--------------------------------------------------------------------===// // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// @@ -541,34 +569,21 @@ public: /// createFileID - Create a new FileID that represents the specified file /// being #included from the specified IncludePosition. This translates NULL /// into standard input. - /// PreallocateID should be non-zero to specify which pre-allocated, - /// lazily computed source location is being filled in by this operation. FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, - unsigned PreallocatedID = 0, - unsigned Offset = 0) { + int LoadedID = 0, unsigned LoadedOffset = 0) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); assert(IR && "getOrCreateContentCache() cannot return NULL"); - return createFileID(IR, IncludePos, FileCharacter, PreallocatedID, Offset); + return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset); } /// createFileIDForMemBuffer - Create a new FileID that represents the /// 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, - unsigned PreallocatedID = 0, - unsigned Offset = 0) { + int LoadedID = 0, unsigned LoadedOffset = 0) { return createFileID(createMemBufferContentCache(Buffer), SourceLocation(), - SrcMgr::C_User, PreallocatedID, Offset); - } - - /// createMainFileIDForMembuffer - Create the FileID for a memory buffer - /// that will represent the FileID for the main source. One example - /// of when this would be used is when the main source is read from STDIN. - FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) { - assert(MainFileID.isInvalid() && "MainFileID already set!"); - MainFileID = createFileIDForMemBuffer(Buffer); - return MainFileID; + SrcMgr::C_User, LoadedID, LoadedOffset); } /// createMacroArgInstantiationLoc - Return a new SourceLocation that encodes @@ -586,8 +601,8 @@ public: SourceLocation InstantiationLocStart, SourceLocation InstantiationLocEnd, unsigned TokLength, - unsigned PreallocatedID = 0, - unsigned Offset = 0); + int LoadedID = 0, + unsigned LoadedOffset = 0); /// \brief Retrieve the memory buffer associated with the given file. /// @@ -702,7 +717,6 @@ public: /// getLocForStartOfFile - Return the source location corresponding to the /// first byte of the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { - assert(FID.ID < SLocEntryTable.size() && "FileID out of range"); bool Invalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); if (Invalid || !Entry.isFile()) @@ -900,10 +914,12 @@ public: #ifndef NDEBUG // Make sure offset/length describe a chunk inside the given FileID. unsigned NextOffset; - if (FID.ID+1 == SLocEntryTable.size()) - NextOffset = getNextOffset(); + if (FID.ID == -2) + NextOffset = 1U << 31U; + else if (FID.ID+1 == (int)LocalSLocEntryTable.size()) + NextOffset = getNextLocalOffset(); else - NextOffset = getSLocEntry(FID.ID+1).getOffset(); + NextOffset = getSLocEntryByID(FID.ID+1).getOffset(); assert(start < NextOffset); assert(end < NextOffset); #endif @@ -979,15 +995,23 @@ public: /// \brief Determines the order of 2 source locations in the "source location /// address space". - static bool isBeforeInSourceLocationOffset(SourceLocation LHS, - SourceLocation RHS) { + bool isBeforeInSourceLocationOffset(SourceLocation LHS, + SourceLocation RHS) const { return isBeforeInSourceLocationOffset(LHS, RHS.getOffset()); } /// \brief Determines the order of a source location and a source location /// offset in the "source location address space". - static bool isBeforeInSourceLocationOffset(SourceLocation LHS, unsigned RHS) { - return LHS.getOffset() < RHS; + /// + /// Note that we always consider source locations loaded from + bool isBeforeInSourceLocationOffset(SourceLocation LHS, unsigned RHS) const { + unsigned LHSOffset = LHS.getOffset(); + bool LHSLoaded = LHSOffset >= CurrentLoadedOffset; + bool RHSLoaded = RHS >= CurrentLoadedOffset; + if (LHSLoaded == RHSLoaded) + return LHS.getOffset() < RHS; + + return LHSLoaded; } // Iterators over FileInfos. @@ -1003,53 +1027,70 @@ public: /// void PrintStats() const; - unsigned sloc_entry_size() const { return SLocEntryTable.size(); } - - // FIXME: Exposing this is a little gross; what we want is a good way - // to iterate the entries that were not defined in an AST file (or - // any other external source). - unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } - - const SrcMgr::SLocEntry &getSLocEntry(unsigned ID, bool *Invalid = 0) const { - assert(ID < SLocEntryTable.size() && "Invalid id"); - // If we haven't loaded this source-location entry from the external source - // yet, do so now. - if (ExternalSLocEntries && - ID < SLocEntryLoaded.size() && - !SLocEntryLoaded[ID] && - ExternalSLocEntries->ReadSLocEntry(ID) && - Invalid) - *Invalid = true; - - return SLocEntryTable[ID]; + /// \brief Get the number of local SLocEntries we have. + unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); } + + /// \brief Get a local SLocEntry. This is exposed for indexing. + const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index, + bool *Invalid = 0) const { + assert(Index < LocalSLocEntryTable.size() && "Invalid index"); + return LocalSLocEntryTable[Index]; } - + + /// \brief Get the number of loaded SLocEntries we have. + 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 { + assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); + if (!SLocEntryLoaded[Index]) + ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2)); + return LoadedSLocEntryTable[Index]; + } + const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { - return getSLocEntry(FID.ID, Invalid); + return getSLocEntryByID(FID.ID); } - unsigned getNextOffset() const { return NextOffset; } - - /// \brief Preallocate some number of source location entries, which - /// will be loaded as needed from the given external source. - void PreallocateSLocEntries(ExternalSLocEntrySource *Source, - unsigned NumSLocEntries, - unsigned NextOffset); - - /// \brief Clear out any preallocated source location entries that - /// haven't already been loaded. - void ClearPreallocatedSLocEntries(); - + unsigned getNextLocalOffset() const { return NextLocalOffset; } + + void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) { + assert(LoadedSLocEntryTable.empty() && + "Invalidating existing loaded entries"); + ExternalSLocEntries = Source; + } + + /// \brief Allocate a number of loaded SLocEntries, which will be actually + /// loaded on demand from the external source. + /// + /// NumSLocEntries will be allocated, which occupy a total of TotalSize space + /// in the global source view. The lowest ID and the base offset of the + /// entries will be returned. + std::pair<int, unsigned> + AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize); + private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + /// \brief Get the entry with the given unwrapped FileID. + const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const { + assert(ID != -1 && "Using FileID sentinel value"); + if (ID < 0) + return getLoadedSLocEntryByID(ID); + return getLocalSLocEntry(static_cast<unsigned>(ID)); + } + + const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const { + return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2)); + } + /// createInstantiationLoc - Implements the common elements of storing an /// instantiation info struct into the SLocEntry table and producing a source /// location that refers to it. SourceLocation createInstantiationLocImpl(const SrcMgr::InstantiationInfo &II, unsigned TokLength, - unsigned PreallocatedID = 0, - unsigned Offset = 0); + int LoadedID = 0, + unsigned LoadedOffset = 0); /// isOffsetInFileID - Return true if the specified FileID contains the /// specified SourceLocation offset. This is a very hot method. @@ -1058,10 +1099,17 @@ private: // If the entry is after the offset, it can't contain it. if (SLocOffset < Entry.getOffset()) return false; - // If this is the last entry than it does. Otherwise, the entry after it - // has to not include it. - if (FID.ID+1 == SLocEntryTable.size()) return true; + // If this is the very last entry then it does. + if (FID.ID == -2) + return true; + + // If it is the last local entry, then it does if the location is local. + if (static_cast<unsigned>(FID.ID+1) == LocalSLocEntryTable.size()) { + return SLocOffset < NextLocalOffset; + } + // Otherwise, the entry after it has to not include it. This works for both + // local and loaded entries. return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset(); } @@ -1071,8 +1119,7 @@ private: FileID createFileID(const SrcMgr::ContentCache* File, SourceLocation IncludePos, SrcMgr::CharacteristicKind DirCharacter, - unsigned PreallocatedID = 0, - unsigned Offset = 0); + int LoadedID, unsigned LoadedOffset); const SrcMgr::ContentCache * getOrCreateContentCache(const FileEntry *SourceFile); @@ -1083,6 +1130,8 @@ private: createMemBufferContentCache(const llvm::MemoryBuffer *Buf); FileID getFileIDSlow(unsigned SLocOffset) const; + FileID getFileIDLocal(unsigned SLocOffset) const; + FileID getFileIDLoaded(unsigned SLocOffset) const; SourceLocation getInstantiationLocSlowCase(SourceLocation Loc) const; SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const; diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index 3f5d1a35e5..6a74d41b54 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -84,7 +84,7 @@ class LineTableInfo { /// LineEntries - This is a map from FileIDs to a list of line entries (sorted /// by the offset they occur in the file. - std::map<unsigned, std::vector<LineEntry> > LineEntries; + std::map<int, std::vector<LineEntry> > LineEntries; public: LineTableInfo() { } @@ -104,25 +104,25 @@ public: } unsigned getNumFilenames() const { return FilenamesByID.size(); } - void AddLineNote(unsigned FID, unsigned Offset, + void AddLineNote(int FID, unsigned Offset, unsigned LineNo, int FilenameID); - void AddLineNote(unsigned FID, unsigned Offset, + void AddLineNote(int FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind); /// FindNearestLineEntry - Find the line entry nearest to FID that is before /// it. If there is no line entry before Offset in FID, return null. - const LineEntry *FindNearestLineEntry(unsigned FID, unsigned Offset); + const LineEntry *FindNearestLineEntry(int FID, unsigned Offset); // Low-level access - typedef std::map<unsigned, std::vector<LineEntry> >::iterator iterator; + typedef std::map<int, std::vector<LineEntry> >::iterator iterator; iterator begin() { return LineEntries.begin(); } iterator end() { return LineEntries.end(); } /// \brief Add a new line entry that has already been encoded into /// the internal representation of the line table. - void AddEntry(unsigned FID, const std::vector<LineEntry> &Entries); + void AddEntry(int FID, const std::vector<LineEntry> &Entries); }; } // end namespace clang diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 58a60a1f9d..9fb552131f 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -41,6 +41,7 @@ namespace llvm { namespace clang { class ASTContext; +class ASTReader; class CodeCompleteConsumer; class CompilerInvocation; class Decl; @@ -143,6 +144,9 @@ private: // Critical optimization when using clang_getCursor(). ASTLocation LastLoc; + /// \brief The set of diagnostics produced when creating the preamble. + llvm::SmallVector<StoredDiagnostic, 4> PreambleDiagnostics; + /// \brief The set of diagnostics produced when creating this /// translation unit. llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics; @@ -230,14 +234,6 @@ private: /// when any errors are present. unsigned NumWarningsInPreamble; - /// \brief The number of diagnostics that were stored when parsing - /// the precompiled preamble. - /// - /// This value is used to determine how many of the stored - /// diagnostics should be retained when reparsing in the presence of - /// a precompiled preamble. - unsigned NumStoredDiagnosticsInPreamble; - /// \brief A list of the serialization ID numbers for each of the top-level /// declarations parsed within the precompiled preamble. std::vector<serialization::DeclID> TopLevelDeclsInPreamble; @@ -257,6 +253,11 @@ private: const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics); + void TranslateStoredDiagnostics(ASTReader *MMan, llvm::StringRef ModName, + SourceManager &SrcMan, + const llvm::SmallVectorImpl<StoredDiagnostic> &Diags, + llvm::SmallVectorImpl<StoredDiagnostic> &Out); + public: /// \brief A cached code-completion result, which may be introduced in one of /// many different contexts. diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 004c8896e2..b2c877ac40 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -27,13 +27,13 @@ class Timer; namespace clang { class ASTContext; class ASTConsumer; +class ASTReader; class CodeCompleteConsumer; class Diagnostic; class DiagnosticClient; class ExternalASTSource; class FileManager; class FrontendAction; -class ASTReader; class Preprocessor; class Sema; class SourceManager; @@ -88,9 +88,12 @@ class CompilerInstance { /// \brief The semantic analysis object. llvm::OwningPtr<Sema> TheSema; - /// The frontend timer + /// \brief The frontend timer llvm::OwningPtr<llvm::Timer> FrontendTimer; + /// \brief Non-owning reference to the ASTReader, if one exists. + ASTReader *ModuleManager; + /// \brief Holds information about the output file. /// /// If TempFilename is not empty we must rename it to Filename at the end. @@ -388,6 +391,12 @@ public: Sema *takeSema() { return TheSema.take(); } /// } + /// @name Module Management + /// { + + ASTReader *getModuleManager() const { return ModuleManager; } + + /// } /// @name Code Completion /// { diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 11b8bed903..a01bf6235a 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -375,8 +375,14 @@ namespace clang { /// \brief Record code for the set of known namespaces, which are used /// for typo correction. - KNOWN_NAMESPACES = 46 + KNOWN_NAMESPACES = 46, + /// \brief Record code for the source location remapping information. + SOURCE_LOCATION_MAP = 47, + + /// \brief Record code for the source manager line table information, + /// which stores information about #line directives. + SOURCE_MANAGER_LINE_TABLE = 48 }; /// \brief Record types used within a source manager block. @@ -393,10 +399,7 @@ namespace clang { SM_SLOC_BUFFER_BLOB = 3, /// \brief Describes a source location entry (SLocEntry) for a /// macro expansion. - SM_SLOC_EXPANSION_ENTRY = 4, - /// \brief Describes the SourceManager's line table, with - /// information about #line directives. - SM_LINE_TABLE = 5 + SM_SLOC_EXPANSION_ENTRY = 4 }; /// \brief Record types used within a preprocessor block. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 9e210c3db2..a0bc899262 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_FRONTEND_AST_READER_H #include "clang/Serialization/ASTBitCodes.h" +#include "clang/Serialization/ContinuousRangeMap.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/DeclObjC.h" @@ -49,6 +50,7 @@ class AddrLabelExpr; class ASTConsumer; class ASTContext; class ASTIdentifierIterator; +class ASTUnit; // FIXME: Layering violation and egregious hack. class Attr; class Decl; class DeclContext; @@ -64,6 +66,7 @@ class Preprocessor; class Sema; class SwitchCase; class ASTDeserializationListener; +class ASTWriter; class ASTReader; class ASTDeclReader; class ASTStmtReader; @@ -191,6 +194,8 @@ public: friend class ASTIdentifierIterator; friend class ASTIdentifierLookupTrait; friend class TypeLocReader; + friend class ASTWriter; + friend class ASTUnit; // ASTUnit needs to remap source locations. private: /// \brief The receiver of some callbacks invoked by ASTReader. llvm::OwningPtr<ASTReaderListener> Listener; @@ -245,6 +250,12 @@ private: /// \brief The main bitstream cursor for the main block. llvm::BitstreamCursor Stream; + /// \brief The source location where this module was first imported. + SourceLocation ImportLoc; + + /// \brief The first source location in this module. + SourceLocation FirstLoc; + // === Source Locations === /// \brief Cursor used to read source location entries. @@ -253,9 +264,15 @@ private: /// \brief The number of source location entries in this AST file. unsigned LocalNumSLocEntries; + /// \brief The base ID in the source manager's view of this module. + int SLocEntryBaseID; + + /// \brief The base offset in the source manager's view of this module. + unsigned SLocEntryBaseOffset; + /// \brief Offsets for all of the source location entries in the /// AST file. - const uint32_t *SLocOffsets; + const uint32_t *SLocEntryOffsets; /// \brief The number of source location file entries in this AST file. unsigned LocalNumSLocFileEntries; @@ -264,8 +281,8 @@ private: /// AST file. const uint32_t *SLocFileOffsets; - /// \brief The entire size of this module's source location offset range. - unsigned LocalSLocSize; + /// \brief Remapping table for source locations in this module. + ContinuousRangeMap<uint32_t, int, 2> SLocRemap; // === Identifiers === @@ -397,6 +414,9 @@ private: // === Miscellaneous === + /// \brief Diagnostic IDs and their mappings that the user changed. + llvm::SmallVector<uint64_t, 8> PragmaDiagMappings; + /// \brief The AST stat cache installed for this file, if any. /// /// The dynamic type of this stat cache is always ASTStatCache @@ -426,7 +446,10 @@ private: llvm::SmallVector<PerFileData*, 2> Chain; /// \brief SLocEntries that we're going to preload. - llvm::SmallVector<uint64_t, 64> PreloadSLocEntries; + llvm::SmallVector<int, 64> PreloadSLocEntries; + + /// \brief A map of negated SLocEntryIDs to the modules containing them. + ContinuousRangeMap<unsigned, PerFileData*, 64> GlobalSLocEntryMap; /// \brief Types that have already been loaded from the chain. /// @@ -630,9 +653,6 @@ private: //@} - /// \brief Diagnostic IDs and their mappings that the user changed. - llvm::SmallVector<uint64_t, 8> PragmaDiagMappings; - /// \brief The original file name that was used to build the primary AST file, /// which may have been modified for relocatable-pch support. std::string OriginalFileName; @@ -686,9 +706,6 @@ private: /// \brief The number of source location entries in the chain. unsigned TotalNumSLocEntries; - /// \brief The next offset for a SLocEntry after everything in this reader. - unsigned NextSLocOffset; - /// \brief The number of statements (and expressions) de-serialized /// from the chain. unsigned NumStatementsRead; @@ -810,8 +827,8 @@ private: bool CheckPredefinesBuffers(); bool ParseLineTable(PerFileData &F, llvm::SmallVectorImpl<uint64_t> &Record); ASTReadResult ReadSourceManagerBlock(PerFileData &F); - ASTReadResult ReadSLocEntryRecord(unsigned ID); - PerFileData *SLocCursorForID(unsigned ID); + ASTReadResult ReadSLocEntryRecord(int ID); + llvm::BitstreamCursor &SLocCursorForID(int ID); SourceLocation getImportLocation(PerFileData *F); bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record); @@ -960,11 +977,6 @@ public: return TotalNumSLocEntries; } - /// \brief Returns the next SLocEntry offset after the chain. - unsigned getNextSLocOffset() const { - return NextSLocOffset; - } - /// \brief Returns the number of identifiers found in the chain. unsigned getTotalNumIdentifiers() const { return static_cast<unsigned>(IdentifiersLoaded.size()); |