[cfe-commits] r135484 - in /cfe/trunk: include/clang/Basic/ include/clang/Frontend/ include/clang/Serialization/ lib/Basic/ lib/Frontend/ lib/Lex/ lib/Serialization/ test/Index/ test/Index/Inputs/ test/PCH/ tools/libclang/
Douglas Gregor
dgregor at apple.com
Tue Jul 19 09:10:42 PDT 2011
Author: dgregor
Date: Tue Jul 19 11:10:42 2011
New Revision: 135484
URL: http://llvm.org/viewvc/llvm-project?rev=135484&view=rev
Log:
Revamp the SourceManager to separate the representation of parsed
source locations from source locations loaded from an AST/PCH file.
Previously, loading an AST/PCH file involved carefully pre-allocating
space at the beginning of the source manager for the source locations
and FileIDs that correspond to the prefix, and then appending the
source locations/FileIDs used for parsing the remaining translation
unit. This design forced us into loading PCH files early, as a prefix,
whic has become a rather significant limitation.
This patch splits the SourceManager space into two parts: for source
location "addresses", the lower values (growing upward) are used to
describe parsed code, while upper values (growing downward) are used
for source locations loaded from AST/PCH files. Similarly, positive
FileIDs are used to describe parsed code while negative FileIDs are
used to file/macro locations loaded from AST/PCH files. As a result,
we can load PCH/AST files even during parsing, making various
improvemnts in the future possible, e.g., teaching #include <foo.h> to
look for and load <foo.h.gch> if it happens to be already available.
This patch was originally written by Sebastian Redl, then brought
forward to the modern age by Jonathan Turner, and finally
polished/finished by me to be committed.
Added:
cfe/trunk/include/clang/Serialization/ContinuousRangeMap.h
cfe/trunk/test/Index/Inputs/preamble_macro_template.h
cfe/trunk/test/Index/preamble_macro_template.cpp
Modified:
cfe/trunk/include/clang/Basic/Diagnostic.h
cfe/trunk/include/clang/Basic/SourceLocation.h
cfe/trunk/include/clang/Basic/SourceManager.h
cfe/trunk/include/clang/Basic/SourceManagerInternals.h
cfe/trunk/include/clang/Frontend/ASTUnit.h
cfe/trunk/include/clang/Frontend/CompilerInstance.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/include/clang/Serialization/ASTReader.h
cfe/trunk/lib/Basic/Diagnostic.cpp
cfe/trunk/lib/Basic/SourceManager.cpp
cfe/trunk/lib/Frontend/ASTUnit.cpp
cfe/trunk/lib/Frontend/CompilerInstance.cpp
cfe/trunk/lib/Frontend/FrontendAction.cpp
cfe/trunk/lib/Lex/Lexer.cpp
cfe/trunk/lib/Lex/TokenLexer.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/PCH/reinclude.cpp
cfe/trunk/tools/libclang/CIndexInclusionStack.cpp
Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Tue Jul 19 11:10:42 2011
@@ -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 @@
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.
Modified: cfe/trunk/include/clang/Basic/SourceLocation.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceLocation.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceLocation.h (original)
+++ cfe/trunk/include/clang/Basic/SourceLocation.h Tue Jul 19 11:10:42 2011
@@ -35,8 +35,9 @@
/// 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 @@
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 @@
};
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 @@
/// 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;
Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Tue Jul 19 11:10:42 2011
@@ -46,7 +46,7 @@
/// 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 @@
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 @@
};
-/// 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 @@
/// 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 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 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 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 @@
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 @@
/// 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 @@
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 @@
/// 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 @@
#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 @@
/// \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 @@
///
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 @@
// 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 @@
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 @@
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;
Modified: cfe/trunk/include/clang/Basic/SourceManagerInternals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManagerInternals.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManagerInternals.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManagerInternals.h Tue Jul 19 11:10:42 2011
@@ -84,7 +84,7 @@
/// 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 @@
}
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
Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Tue Jul 19 11:10:42 2011
@@ -41,6 +41,7 @@
namespace clang {
class ASTContext;
+class ASTReader;
class CodeCompleteConsumer;
class CompilerInvocation;
class Decl;
@@ -143,6 +144,9 @@
// 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 @@
/// 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 @@
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.
Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
+++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Tue Jul 19 11:10:42 2011
@@ -27,13 +27,13 @@
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 @@
/// \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 @@
Sema *takeSema() { return TheSema.take(); }
/// }
+ /// @name Module Management
+ /// {
+
+ ASTReader *getModuleManager() const { return ModuleManager; }
+
+ /// }
/// @name Code Completion
/// {
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Jul 19 11:10:42 2011
@@ -375,8 +375,14 @@
/// \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 @@
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.
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Jul 19 11:10:42 2011
@@ -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 ASTConsumer;
class ASTContext;
class ASTIdentifierIterator;
+class ASTUnit; // FIXME: Layering violation and egregious hack.
class Attr;
class Decl;
class DeclContext;
@@ -64,6 +66,7 @@
class Sema;
class SwitchCase;
class ASTDeserializationListener;
+class ASTWriter;
class ASTReader;
class ASTDeclReader;
class ASTStmtReader;
@@ -191,6 +194,8 @@
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 @@
/// \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 @@
/// \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 @@
/// 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 @@
// === 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 @@
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 @@
//@}
- /// \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 @@
/// \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 @@
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 @@
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());
@@ -1158,7 +1170,7 @@
}
/// \brief Read the source location entry with index ID.
- virtual bool ReadSLocEntry(unsigned ID);
+ virtual bool ReadSLocEntry(int ID);
Selector DecodeSelector(unsigned Idx);
@@ -1221,8 +1233,15 @@
/// \brief Read a source location from raw form.
SourceLocation ReadSourceLocation(PerFileData &Module, unsigned Raw) {
- (void)Module; // No remapping yet
- return SourceLocation::getFromRawEncoding(Raw);
+ unsigned Flag = Raw & (1U << 31);
+ unsigned Offset = Raw & ~(1U << 31);
+ assert(Module.SLocRemap.find(Offset) != Module.SLocRemap.end() &&
+ "Cannot find offset to remap.");
+ int Remap = Module.SLocRemap.find(Offset)->second;
+ Offset += Remap;
+ assert((Offset & (1U << 31)) == 0 &&
+ "Bad offset in reading source location");
+ return SourceLocation::getFromRawEncoding(Offset | Flag);
}
/// \brief Read a source location.
Added: cfe/trunk/include/clang/Serialization/ContinuousRangeMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ContinuousRangeMap.h?rev=135484&view=auto
==============================================================================
--- cfe/trunk/include/clang/Serialization/ContinuousRangeMap.h (added)
+++ cfe/trunk/include/clang/Serialization/ContinuousRangeMap.h Tue Jul 19 11:10:42 2011
@@ -0,0 +1,90 @@
+//===--- ContinuousRangeMap.h - Map with int range as key -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ContinuousRangeMap class, which is a highly
+// specialized container used by serialization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H
+#define LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H
+
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+#include <utility>
+
+namespace clang {
+
+/// \brief A map from continuous integer ranges to some value, with a very
+/// specialized interface.
+///
+/// CRM maps from integer ranges to values. The ranges are continuous, i.e.
+/// where one ends, the next one begins. So if the map contains the stops I0-3,
+/// the first range is from I0 to I1, the second from I1 to I2, the third from
+/// I2 to I3 and the last from I3 to infinity.
+///
+/// Ranges must be inserted in order. Inserting a new stop I4 into the map will
+/// shrink the fourth range to I3 to I4 and add the new range I4 to inf.
+template <typename Int, typename V, unsigned InitialCapacity>
+class ContinuousRangeMap {
+public:
+ typedef std::pair<const Int, V> value_type;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+
+private:
+ typedef llvm::SmallVector<value_type, InitialCapacity> Representation;
+ Representation Rep;
+
+ struct Compare {
+ bool operator ()(const_reference L, Int R) const {
+ return L.first < R;
+ }
+ bool operator ()(Int L, const_reference R) const {
+ return L < R.first;
+ }
+ };
+
+public:
+ void insert(const value_type &Val) {
+ assert((Rep.empty() || Rep.back().first < Val.first) &&
+ "Must insert keys in order.");
+ Rep.push_back(Val);
+ }
+
+ typedef typename Representation::iterator iterator;
+ typedef typename Representation::const_iterator const_iterator;
+
+ iterator begin() { return Rep.begin(); }
+ iterator end() { return Rep.end(); }
+ const_iterator begin() const { return Rep.begin(); }
+ const_iterator end() const { return Rep.end(); }
+
+ iterator find(Int K) {
+ iterator I = std::upper_bound(Rep.begin(), Rep.end(), K, Compare());
+ // I points to the first entry with a key > K, which is the range that
+ // follows the one containing K.
+ if (I == Rep.begin())
+ return Rep.end();
+ --I;
+ return I;
+ }
+ const_iterator find(Int K) const {
+ return const_cast<ContinuousRangeMap*>(this)->find(K);
+ }
+
+ reference back() { return Rep.back(); }
+ const_reference back() const { return Rep.back(); }
+};
+
+}
+
+#endif
Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Tue Jul 19 11:10:42 2011
@@ -726,6 +726,16 @@
FixIts.push_back(Info.getFixItHint(I));
}
+StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, unsigned ID,
+ llvm::StringRef Message, FullSourceLoc Loc,
+ llvm::ArrayRef<CharSourceRange> Ranges,
+ llvm::ArrayRef<FixItHint> Fixits)
+ : ID(ID), Level(Level), Loc(Loc), Message(Message)
+{
+ this->Ranges.assign(Ranges.begin(), Ranges.end());
+ this->FixIts.assign(FixIts.begin(), FixIts.end());
+}
+
StoredDiagnostic::~StoredDiagnostic() { }
/// IncludeInDiagnosticCounts - This method (whose default implementation
Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Tue Jul 19 11:10:42 2011
@@ -186,7 +186,7 @@
/// AddLineNote - Add a line note to the line table that indicates that there
/// is a #line at the specified FID/Offset location which changes the presumed
/// location to LineNo/FilenameID.
-void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
+void LineTableInfo::AddLineNote(int FID, unsigned Offset,
unsigned LineNo, int FilenameID) {
std::vector<LineEntry> &Entries = LineEntries[FID];
@@ -217,7 +217,7 @@
/// presumed #include stack. If it is 1, this is a file entry, if it is 2 then
/// this is a file exit. FileKind specifies whether this is a system header or
/// extern C system header.
-void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
+void LineTableInfo::AddLineNote(int FID, unsigned Offset,
unsigned LineNo, int FilenameID,
unsigned EntryExit,
SrcMgr::CharacteristicKind FileKind) {
@@ -251,7 +251,7 @@
/// 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 *LineTableInfo::FindNearestLineEntry(unsigned FID,
+const LineEntry *LineTableInfo::FindNearestLineEntry(int FID,
unsigned Offset) {
const std::vector<LineEntry> &Entries = LineEntries[FID];
assert(!Entries.empty() && "No #line entries for this FID after all!");
@@ -270,7 +270,7 @@
/// \brief Add a new line entry that has already been encoded into
/// the internal representation of the line table.
-void LineTableInfo::AddEntry(unsigned FID,
+void LineTableInfo::AddEntry(int FID,
const std::vector<LineEntry> &Entries) {
LineEntries[FID] = Entries;
}
@@ -391,7 +391,9 @@
void SourceManager::clearIDTables() {
MainFileID = FileID();
- SLocEntryTable.clear();
+ LocalSLocEntryTable.clear();
+ LoadedSLocEntryTable.clear();
+ SLocEntryLoaded.clear();
LastLineNoFileIDQuery = FileID();
LastLineNoContentCache = 0;
LastFileIDLookup = FileID();
@@ -400,7 +402,10 @@
LineTable->clear();
// Use up FileID #0 as an invalid instantiation.
- NextOffset = 0;
+ NextLocalOffset = 0;
+ // The highest possible offset is 2^31-1, so CurrentLoadedOffset starts at
+ // 2^31.
+ CurrentLoadedOffset = 1U << 31U;
createInstantiationLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1);
}
@@ -452,33 +457,16 @@
return Entry;
}
-void SourceManager::PreallocateSLocEntries(ExternalSLocEntrySource *Source,
- unsigned NumSLocEntries,
- unsigned NextOffset) {
- ExternalSLocEntries = Source;
- this->NextOffset = NextOffset;
- unsigned CurPrealloc = SLocEntryLoaded.size();
- // If we've ever preallocated, we must not count the dummy entry.
- if (CurPrealloc) --CurPrealloc;
- SLocEntryLoaded.resize(NumSLocEntries + 1);
- SLocEntryLoaded[0] = true;
- SLocEntryTable.resize(SLocEntryTable.size() + NumSLocEntries - CurPrealloc);
-}
-
-void SourceManager::ClearPreallocatedSLocEntries() {
- unsigned I = 0;
- for (unsigned N = SLocEntryLoaded.size(); I != N; ++I)
- if (!SLocEntryLoaded[I])
- break;
-
- // We've already loaded all preallocated source location entries.
- if (I == SLocEntryLoaded.size())
- return;
-
- // Remove everything from location I onward.
- SLocEntryTable.resize(I);
- SLocEntryLoaded.clear();
- ExternalSLocEntries = 0;
+std::pair<int, unsigned>
+SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
+ unsigned TotalSize) {
+ assert(ExternalSLocEntries && "Don't have an external sloc source");
+ LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
+ SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
+ CurrentLoadedOffset -= TotalSize;
+ assert(CurrentLoadedOffset >= NextLocalOffset && "Out of source locations");
+ int ID = LoadedSLocEntryTable.size();
+ return std::make_pair(-ID - 1, CurrentLoadedOffset);
}
/// \brief As part of recovering from missing or changed content, produce a
@@ -501,33 +489,31 @@
FileID SourceManager::createFileID(const ContentCache *File,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
- unsigned PreallocatedID,
- unsigned Offset) {
- if (PreallocatedID) {
- // If we're filling in a preallocated ID, just load in the file
- // entry and return.
- assert(PreallocatedID < SLocEntryLoaded.size() &&
- "Preallocate ID out-of-range");
- assert(!SLocEntryLoaded[PreallocatedID] &&
- "Source location entry already loaded");
- assert(Offset && "Preallocate source location cannot have zero offset");
- SLocEntryTable[PreallocatedID]
- = SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
- SLocEntryLoaded[PreallocatedID] = true;
- FileID FID = FileID::get(PreallocatedID);
- return FID;
- }
-
- SLocEntryTable.push_back(SLocEntry::get(NextOffset,
- FileInfo::get(IncludePos, File,
- FileCharacter)));
+ int LoadedID, unsigned LoadedOffset) {
+ if (LoadedID < 0) {
+ assert(LoadedID != -1 && "Loading sentinel FileID");
+ unsigned Index = unsigned(-LoadedID) - 2;
+ assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
+ assert(!SLocEntryLoaded[Index] && "FileID already loaded");
+ LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset,
+ FileInfo::get(IncludePos, File, FileCharacter));
+ SLocEntryLoaded[Index] = true;
+ return FileID::get(LoadedID);
+ }
+ LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset,
+ FileInfo::get(IncludePos, File,
+ FileCharacter)));
unsigned FileSize = File->getSize();
- assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
- NextOffset += FileSize+1;
+ assert(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
+ NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset &&
+ "Ran out of source locations!");
+ // We do a +1 here because we want a SourceLocation that means "the end of the
+ // file", e.g. for the "no newline at the end of the file" diagnostic.
+ NextLocalOffset += FileSize + 1;
// Set LastFileIDLookup to the newly created file. The next getFileID call is
// almost guaranteed to be from that file.
- FileID FID = FileID::get(SLocEntryTable.size()-1);
+ FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
return LastFileIDLookup = FID;
}
@@ -544,34 +530,34 @@
SourceLocation ILocStart,
SourceLocation ILocEnd,
unsigned TokLength,
- unsigned PreallocatedID,
- unsigned Offset) {
+ int LoadedID,
+ unsigned LoadedOffset) {
InstantiationInfo II =
InstantiationInfo::create(SpellingLoc, ILocStart, ILocEnd);
- return createInstantiationLocImpl(II, TokLength, PreallocatedID, Offset);
+ return createInstantiationLocImpl(II, TokLength, LoadedID, LoadedOffset);
}
SourceLocation
SourceManager::createInstantiationLocImpl(const InstantiationInfo &II,
unsigned TokLength,
- unsigned PreallocatedID,
- unsigned Offset) {
- if (PreallocatedID) {
- // If we're filling in a preallocated ID, just load in the
- // instantiation entry and return.
- assert(PreallocatedID < SLocEntryLoaded.size() &&
- "Preallocate ID out-of-range");
- assert(!SLocEntryLoaded[PreallocatedID] &&
- "Source location entry already loaded");
- assert(Offset && "Preallocate source location cannot have zero offset");
- SLocEntryTable[PreallocatedID] = SLocEntry::get(Offset, II);
- SLocEntryLoaded[PreallocatedID] = true;
- return SourceLocation::getMacroLoc(Offset);
- }
- SLocEntryTable.push_back(SLocEntry::get(NextOffset, II));
- assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!");
- NextOffset += TokLength+1;
- return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
+ int LoadedID,
+ unsigned LoadedOffset) {
+ if (LoadedID < 0) {
+ assert(LoadedID != -1 && "Loading sentinel FileID");
+ unsigned Index = unsigned(-LoadedID) - 2;
+ assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
+ assert(!SLocEntryLoaded[Index] && "FileID already loaded");
+ LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, II);
+ SLocEntryLoaded[Index] = true;
+ return SourceLocation::getMacroLoc(LoadedOffset);
+ }
+ LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, II));
+ assert(NextLocalOffset + TokLength + 1 > NextLocalOffset &&
+ NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset &&
+ "Ran out of source locations!");
+ // See createFileID for that +1.
+ NextLocalOffset += TokLength + 1;
+ return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
}
const llvm::MemoryBuffer *
@@ -604,7 +590,7 @@
llvm::StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
bool MyInvalid = false;
- const SLocEntry &SLoc = getSLocEntry(FID.ID, &MyInvalid);
+ const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
if (!SLoc.isFile() || MyInvalid) {
if (Invalid)
*Invalid = true;
@@ -627,15 +613,29 @@
// SourceLocation manipulation methods.
//===----------------------------------------------------------------------===//
-/// getFileIDSlow - Return the FileID for a SourceLocation. This is a very hot
-/// method that is used for all SourceManager queries that start with a
-/// SourceLocation object. It is responsible for finding the entry in
-/// SLocEntryTable which contains the specified location.
+/// \brief Return the FileID for a SourceLocation.
///
+/// This is the cache-miss path of getFileID. Not as hot as that function, but
+/// still very important. It is responsible for finding the entry in the
+/// SLocEntry tables that contains the specified location.
FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
if (!SLocOffset)
return FileID::get(0);
+ // Now it is time to search for the correct file. See where the SLocOffset
+ // sits in the global view and consult local or loaded buffers for it.
+ if (SLocOffset < NextLocalOffset)
+ return getFileIDLocal(SLocOffset);
+ return getFileIDLoaded(SLocOffset);
+}
+
+/// \brief Return the FileID for a SourceLocation with a low offset.
+///
+/// This function knows that the SourceLocation is in a local buffer, not a
+/// loaded one.
+FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
+ assert(SLocOffset < NextLocalOffset && "Bad function choice");
+
// After the first and second level caches, I see two common sorts of
// behavior: 1) a lot of searched FileID's are "near" the cached file location
// or are "near" the cached instantiation location. 2) others are just
@@ -649,12 +649,13 @@
// most newly created FileID.
std::vector<SrcMgr::SLocEntry>::const_iterator I;
- if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
+ if (LastFileIDLookup.ID < 0 ||
+ LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
// Neither loc prunes our search.
- I = SLocEntryTable.end();
+ I = LocalSLocEntryTable.end();
} else {
// Perhaps it is near the file point.
- I = SLocEntryTable.begin()+LastFileIDLookup.ID;
+ I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID;
}
// Find the FileID that contains this. "I" is an iterator that points to a
@@ -662,21 +663,8 @@
unsigned NumProbes = 0;
while (1) {
--I;
- if (ExternalSLocEntries) {
- bool Invalid = false;
- getSLocEntry(FileID::get(I - SLocEntryTable.begin()), &Invalid);
- if (Invalid)
- return FileID::get(0);
- }
-
if (I->getOffset() <= SLocOffset) {
-#if 0
- printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
- I-SLocEntryTable.begin(),
- I->isInstantiation() ? "inst" : "file",
- LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
-#endif
- FileID Res = FileID::get(I-SLocEntryTable.begin());
+ FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin()));
// If this isn't an instantiation, remember it. We have good locality
// across FileID lookups.
@@ -691,7 +679,7 @@
// Convert "I" back into an index. We know that it is an entry whose index is
// larger than the offset we are looking for.
- unsigned GreaterIndex = I-SLocEntryTable.begin();
+ unsigned GreaterIndex = I - LocalSLocEntryTable.begin();
// LessIndex - This is the lower bound of the range that we're searching.
// We know that the offset corresponding to the FileID is is less than
// SLocOffset.
@@ -700,8 +688,7 @@
while (1) {
bool Invalid = false;
unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
- unsigned MidOffset = getSLocEntry(FileID::get(MiddleIndex), &Invalid)
- .getOffset();
+ unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset();
if (Invalid)
return FileID::get(0);
@@ -715,18 +702,14 @@
}
// If the middle index contains the value, succeed and return.
+ // FIXME: This could be made faster by using a function that's aware of
+ // being in the local area.
if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
-#if 0
- printf("bin %d -> %d [%s] %d %d\n", SLocOffset,
- I-SLocEntryTable.begin(),
- I->isInstantiation() ? "inst" : "file",
- LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
-#endif
FileID Res = FileID::get(MiddleIndex);
// If this isn't an instantiation, remember it. We have good locality
// across FileID lookups.
- if (!I->isInstantiation())
+ if (!LocalSLocEntryTable[MiddleIndex].isInstantiation())
LastFileIDLookup = Res;
NumBinaryProbes += NumProbes;
return Res;
@@ -737,6 +720,68 @@
}
}
+/// \brief Return the FileID for a SourceLocation with a high offset.
+///
+/// This function knows that the SourceLocation is in a loaded buffer, not a
+/// local one.
+FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
+ assert(SLocOffset >= CurrentLoadedOffset && "Bad function choice");
+
+ // Essentially the same as the local case, but the loaded array is sorted
+ // in the other direction.
+
+ // First do a linear scan from the last lookup position, if possible.
+ unsigned I;
+ int LastID = LastFileIDLookup.ID;
+ if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset)
+ I = 0;
+ else
+ I = (-LastID - 2) + 1;
+
+ unsigned NumProbes;
+ for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) {
+ // Make sure the entry is loaded!
+ const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I);
+ if (E.getOffset() <= SLocOffset) {
+ FileID Res = FileID::get(-int(I) - 2);
+
+ if (!E.isInstantiation())
+ LastFileIDLookup = Res;
+ NumLinearScans += NumProbes + 1;
+ return Res;
+ }
+ }
+
+ // Linear scan failed. Do the binary search. Note the reverse sorting of the
+ // table: GreaterIndex is the one where the offset is greater, which is
+ // actually a lower index!
+ unsigned GreaterIndex = I;
+ unsigned LessIndex = LoadedSLocEntryTable.size();
+ NumProbes = 0;
+ while (1) {
+ ++NumProbes;
+ unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
+ const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex);
+
+ ++NumProbes;
+
+ if (E.getOffset() > SLocOffset) {
+ GreaterIndex = MiddleIndex;
+ continue;
+ }
+
+ if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) {
+ FileID Res = FileID::get(-int(MiddleIndex) - 2);
+ if (!E.isInstantiation())
+ LastFileIDLookup = Res;
+ NumBinaryProbes += NumProbes;
+ return Res;
+ }
+
+ LessIndex = MiddleIndex;
+ }
+}
+
SourceLocation SourceManager::
getInstantiationLocSlowCase(SourceLocation Loc) const {
do {
@@ -1259,7 +1304,7 @@
/// \brief Get the source location for the given file:line:col triplet.
///
/// If the source file is included multiple times, the source location will
-/// be based upon the first inclusion.
+/// be based upon an arbitrary inclusion.
SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
unsigned Line, unsigned Col) {
assert(SourceFile && "Null source file!");
@@ -1308,10 +1353,10 @@
if (FirstFID.isInvalid()) {
// The location we're looking for isn't in the main file; look
- // through all of the source locations.
- for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
+ // through all of the local source locations.
+ for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
bool Invalid = false;
- const SLocEntry &SLoc = getSLocEntry(I, &Invalid);
+ const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid);
if (Invalid)
return SourceLocation();
@@ -1322,6 +1367,18 @@
break;
}
}
+ // If that still didn't help, try the modules.
+ if (FirstFID.isInvalid()) {
+ for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getLoadedSLocEntry(I);
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache() &&
+ SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
+ FirstFID = FileID::get(-int(I) - 2);
+ break;
+ }
+ }
+ }
}
// If we haven't found what we want yet, try again, but this time stat()
@@ -1333,8 +1390,10 @@
(SourceFileInode ||
(SourceFileInode = getActualFileInode(SourceFile)))) {
bool Invalid = false;
- for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
- const SLocEntry &SLoc = getSLocEntry(I, &Invalid);
+ for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
+ FileID IFileID;
+ IFileID.ID = I;
+ const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid);
if (Invalid)
return SourceLocation();
@@ -1368,7 +1427,7 @@
return SourceLocation();
// If this is the first use of line information for this buffer, compute the
- /// SourceLineCache for it on demand.
+ // SourceLineCache for it on demand.
if (Content->SourceLineCache == 0) {
bool MyInvalid = false;
ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
@@ -1447,39 +1506,25 @@
// Okay, we missed in the cache, start updating the cache for this query.
IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first);
- // "Traverse" the include/instantiation stacks of both locations and try to
- // find a common "ancestor". FileIDs build a tree-like structure that
- // reflects the #include hierarchy, and this algorithm needs to find the
- // nearest common ancestor between the two locations. For example, if you
- // have a.c that includes b.h and c.h, and are comparing a location in b.h to
- // a location in c.h, we need to find that their nearest common ancestor is
- // a.c, and compare the locations of the two #includes to find their relative
- // ordering.
- //
- // SourceManager assigns FileIDs in order of parsing. This means that an
- // includee always has a larger FileID than an includer. While you might
- // think that we could just compare the FileID's here, that doesn't work to
- // compare a point at the end of a.c with a point within c.h. Though c.h has
- // a larger FileID, we have to compare the include point of c.h to the
- // location in a.c.
- //
- // Despite not being able to directly compare FileID's, we can tell that a
- // larger FileID is necessarily more deeply nested than a lower one and use
- // this information to walk up the tree to the nearest common ancestor.
+ // We need to find the common ancestor. The only way of doing this is to
+ // build the complete include chain for one and then walking up the chain
+ // of the other looking for a match.
+ // We use a map from FileID to Offset to store the chain. Easier than writing
+ // a custom set hash info that only depends on the first part of a pair.
+ typedef llvm::DenseMap<FileID, unsigned> LocSet;
+ LocSet LChain;
do {
- // If LOffs is larger than ROffs, then LOffs must be more deeply nested than
- // ROffs, walk up the #include chain.
- if (LOffs.first.ID > ROffs.first.ID) {
- if (MoveUpIncludeHierarchy(LOffs, *this))
- break; // We reached the top.
-
- } else {
- // Otherwise, ROffs is larger than LOffs, so ROffs must be more deeply
- // nested than LOffs, walk up the #include chain.
- if (MoveUpIncludeHierarchy(ROffs, *this))
- break; // We reached the top.
- }
- } while (LOffs.first != ROffs.first);
+ LChain.insert(LOffs);
+ // We catch the case where LOffs is in a file included by ROffs and
+ // quit early. The other way round unfortunately remains suboptimal.
+ } while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this));
+ LocSet::iterator I;
+ while((I = LChain.find(ROffs.first)) == LChain.end()) {
+ if (MoveUpIncludeHierarchy(ROffs, *this))
+ break; // Met at topmost file.
+ }
+ if (I != LChain.end())
+ LOffs = *I;
// If we exited because we found a nearest common ancestor, compare the
// locations within the common file and cache them.
@@ -1488,26 +1533,21 @@
return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
}
- // There is no common ancestor, most probably because one location is in the
- // predefines buffer or an AST file.
- // FIXME: We should rearrange the external interface so this simply never
- // happens; it can't conceptually happen. Also see PR5662.
- IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching.
-
- // Zip both entries up to the top level record.
- while (!MoveUpIncludeHierarchy(LOffs, *this)) /*empty*/;
- while (!MoveUpIncludeHierarchy(ROffs, *this)) /*empty*/;
-
- // If exactly one location is a memory buffer, assume it precedes the other.
-
- // Strip off macro instantation locations, going up to the top-level File
- // SLocEntry.
- bool LIsMB = getFileEntryForID(LOffs.first) == 0;
- bool RIsMB = getFileEntryForID(ROffs.first) == 0;
- if (LIsMB != RIsMB)
- return LIsMB;
-
- // Otherwise, just assume FileIDs were created in order.
+ // This can happen if a location is in a built-ins buffer.
+ // But see PR5662.
+ // Clear the lookup cache, it depends on a common location.
+ IsBeforeInTUCache.setQueryFIDs(FileID(), FileID());
+ bool LIsBuiltins = strcmp("<built-in>",
+ getBuffer(LOffs.first)->getBufferIdentifier()) == 0;
+ bool RIsBuiltins = strcmp("<built-in>",
+ getBuffer(ROffs.first)->getBufferIdentifier()) == 0;
+ // built-in is before non-built-in
+ if (LIsBuiltins != RIsBuiltins)
+ return LIsBuiltins;
+ assert(LIsBuiltins && RIsBuiltins &&
+ "Non-built-in locations must be rooted in the main file");
+ // Both are in built-in buffers, but from different files. We just claim that
+ // lower IDs come first.
return LOffs.first < ROffs.first;
}
@@ -1517,11 +1557,15 @@
llvm::errs() << "\n*** Source Manager Stats:\n";
llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
<< " mem buffers mapped.\n";
- llvm::errs() << SLocEntryTable.size() << " SLocEntry's allocated ("
- << SLocEntryTable.capacity()*sizeof(SrcMgr::SLocEntry)
+ llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntry's allocated ("
+ << LocalSLocEntryTable.capacity()*sizeof(SrcMgr::SLocEntry)
<< " bytes of capacity), "
- << NextOffset << "B of Sloc address space used.\n";
-
+ << NextLocalOffset << "B of Sloc address space used.\n";
+ llvm::errs() << LoadedSLocEntryTable.size()
+ << " loaded SLocEntries allocated, "
+ << (1U << 31U) - CurrentLoadedOffset
+ << "B of Sloc address space used.\n";
+
unsigned NumLineNumsComputed = 0;
unsigned NumFileBytesMapped = 0;
for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Tue Jul 19 11:10:42 2011
@@ -976,7 +976,14 @@
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
Clang->getFrontendOpts().Inputs[0].first))
goto error;
-
+
+ if (OverrideMainBuffer) {
+ std::string ModName = "$" + PreambleFile;
+ TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
+ getSourceManager(), PreambleDiagnostics,
+ StoredDiagnostics);
+ }
+
Act->Execute();
// Steal the created target, context, and preprocessor.
@@ -1170,7 +1177,7 @@
std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
= ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer);
- // If ComputePreamble() Take ownership of the
+ // If ComputePreamble() Take ownership of the preamble buffer.
llvm::OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer;
if (CreatedPreambleBuffer)
OwnedPreambleBuffer.reset(NewPreamble.first);
@@ -1271,10 +1278,6 @@
ProcessWarningOptions(getDiagnostics(),
PreambleInvocation->getDiagnosticOpts());
getDiagnostics().setNumWarnings(NumWarningsInPreamble);
- if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
- StoredDiagnostics.erase(
- StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
- StoredDiagnostics.end());
// Create a version of the main file buffer that is padded to
// buffer size we reserved when creating the preamble.
@@ -1291,6 +1294,7 @@
// We can't reuse the previously-computed preamble. Build a new one.
Preamble.clear();
+ PreambleDiagnostics.clear();
llvm::sys::Path(PreambleFile).eraseFromDisk();
PreambleRebuildCounter = 1;
} else if (!AllowRebuild) {
@@ -1446,9 +1450,18 @@
return 0;
}
+ // Transfer any diagnostics generated when parsing the preamble into the set
+ // of preamble diagnostics.
+ PreambleDiagnostics.clear();
+ PreambleDiagnostics.insert(PreambleDiagnostics.end(),
+ StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
+ StoredDiagnostics.end());
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
+ StoredDiagnostics.end());
+
// Keep track of the preamble we precompiled.
PreambleFile = FrontendOpts.OutputFile;
- NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
NumWarningsInPreamble = getDiagnostics().getNumWarnings();
// Keep track of all of the files that the source manager knows about,
@@ -1776,6 +1789,7 @@
llvm::IntrusiveRefCntPtr<CompilerInvocation> CI;
{
+
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
StoredDiagnostics);
@@ -1826,7 +1840,6 @@
AST->CompleteTranslationUnit = CompleteTranslationUnit;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
- AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI;
AST->NestedMacroExpansions = NestedMacroExpansions;
@@ -2272,17 +2285,6 @@
PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
PreprocessorOpts.DisablePCHValidation = true;
- // The stored diagnostics have the old source manager. Copy them
- // to our output set of stored diagnostics, updating the source
- // manager to the one we were given.
- for (unsigned I = NumStoredDiagnosticsFromDriver,
- N = this->StoredDiagnostics.size();
- I < N; ++I) {
- StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
- FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
- StoredDiagnostics[I].setLocation(Loc);
- }
-
OwnedBuffers.push_back(OverrideMainBuffer);
} else {
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
@@ -2296,6 +2298,12 @@
Act.reset(new SyntaxOnlyAction);
if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
Clang->getFrontendOpts().Inputs[0].first)) {
+ if (OverrideMainBuffer) {
+ std::string ModName = "$" + PreambleFile;
+ TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
+ getSourceManager(), PreambleDiagnostics,
+ StoredDiagnostics);
+ }
Act->Execute();
Act->EndSourceFile();
}
@@ -2333,3 +2341,71 @@
return false;
}
+
+typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
+
+static void TranslateSLoc(SourceLocation &L, SLocRemap &Remap) {
+ unsigned Raw = L.getRawEncoding();
+ const unsigned MacroBit = 1U << 31;
+ L = SourceLocation::getFromRawEncoding((Raw & MacroBit) |
+ ((Raw & ~MacroBit) + Remap.find(Raw & ~MacroBit)->second));
+}
+
+void ASTUnit::TranslateStoredDiagnostics(
+ ASTReader *MMan,
+ llvm::StringRef ModName,
+ SourceManager &SrcMgr,
+ const llvm::SmallVectorImpl<StoredDiagnostic> &Diags,
+ llvm::SmallVectorImpl<StoredDiagnostic> &Out) {
+ // The stored diagnostic has the old source manager in it; update
+ // the locations to refer into the new source manager. We also need to remap
+ // all the locations to the new view. This includes the diag location, any
+ // associated source ranges, and the source ranges of associated fix-its.
+ // FIXME: There should be a cleaner way to do this.
+
+ llvm::SmallVector<StoredDiagnostic, 4> Result;
+ Result.reserve(Diags.size());
+ assert(MMan && "Don't have a module manager");
+ ASTReader::PerFileData *Mod = MMan->Modules.lookup(ModName);
+ assert(Mod && "Don't have preamble module");
+ SLocRemap &Remap = Mod->SLocRemap;
+ for (unsigned I = 0, N = Diags.size(); I != N; ++I) {
+ // Rebuild the StoredDiagnostic.
+ const StoredDiagnostic &SD = Diags[I];
+ SourceLocation L = SD.getLocation();
+ TranslateSLoc(L, Remap);
+ FullSourceLoc Loc(L, SrcMgr);
+
+ llvm::SmallVector<CharSourceRange, 4> Ranges;
+ Ranges.reserve(SD.range_size());
+ for (StoredDiagnostic::range_iterator I = SD.range_begin(),
+ E = SD.range_end();
+ I != E; ++I) {
+ SourceLocation BL = I->getBegin();
+ TranslateSLoc(BL, Remap);
+ SourceLocation EL = I->getEnd();
+ TranslateSLoc(EL, Remap);
+ Ranges.push_back(CharSourceRange(SourceRange(BL, EL), I->isTokenRange()));
+ }
+
+ llvm::SmallVector<FixItHint, 2> FixIts;
+ FixIts.reserve(SD.fixit_size());
+ for (StoredDiagnostic::fixit_iterator I = SD.fixit_begin(),
+ E = SD.fixit_end();
+ I != E; ++I) {
+ FixIts.push_back(FixItHint());
+ FixItHint &FH = FixIts.back();
+ FH.CodeToInsert = I->CodeToInsert;
+ SourceLocation BL = I->RemoveRange.getBegin();
+ TranslateSLoc(BL, Remap);
+ SourceLocation EL = I->RemoveRange.getEnd();
+ TranslateSLoc(EL, Remap);
+ FH.RemoveRange = CharSourceRange(SourceRange(BL, EL),
+ I->RemoveRange.isTokenRange());
+ }
+
+ Result.push_back(StoredDiagnostic(SD.getLevel(), SD.getID(),
+ SD.getMessage(), Loc, Ranges, FixIts));
+ }
+ Result.swap(Out);
+}
Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Tue Jul 19 11:10:42 2011
@@ -42,7 +42,7 @@
using namespace clang;
CompilerInstance::CompilerInstance()
- : Invocation(new CompilerInvocation()) {
+ : Invocation(new CompilerInvocation()), ModuleManager(0) {
}
CompilerInstance::~CompilerInstance() {
@@ -275,6 +275,7 @@
getPreprocessor(), getASTContext(),
DeserializationListener,
Preamble));
+ ModuleManager = static_cast<ASTReader*>(Source.get());
getASTContext().setExternalSource(Source);
}
Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendAction.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendAction.cpp Tue Jul 19 11:10:42 2011
@@ -224,9 +224,8 @@
} else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
// Use PCH.
assert(hasPCHSupport() && "This action does not have PCH support!");
- ASTDeserializationListener *DeserialListener
- = CI.getInvocation().getFrontendOpts().ChainedPCH ?
- Consumer->GetASTDeserializationListener() : 0;
+ ASTDeserializationListener *DeserialListener =
+ Consumer->GetASTDeserializationListener();
if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls)
DeserialListener = new DeserializedDeclsDumper(DeserialListener);
if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty())
Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Tue Jul 19 11:10:42 2011
@@ -702,8 +702,8 @@
/// \brief Returns true if the given MacroID location points at the first
/// token of the macro expansion.
bool Lexer::isAtStartOfMacroExpansion(SourceLocation loc,
- const SourceManager &SM,
- const LangOptions &LangOpts) {
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc");
std::pair<FileID, unsigned> infoLoc = SM.getDecomposedLoc(loc);
@@ -735,7 +735,7 @@
FileID FID = SM.getFileID(loc);
SourceLocation afterLoc = loc.getFileLocWithOffset(tokLen+1);
- if (!SM.isBeforeInSourceLocationOffset(afterLoc, SM.getNextOffset()))
+ if (!SM.isBeforeInSourceLocationOffset(afterLoc, SM.getNextLocalOffset()))
return true; // We got past the last FileID, this points to the last token.
// FIXME: If the token comes from the macro token paste operator ('##')
Modified: cfe/trunk/lib/Lex/TokenLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenLexer.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/TokenLexer.cpp (original)
+++ cfe/trunk/lib/Lex/TokenLexer.cpp Tue Jul 19 11:10:42 2011
@@ -43,7 +43,7 @@
MacroExpansionStart = SourceLocation();
SourceManager &SM = PP.getSourceManager();
- MacroStartSLocOffset = SM.getNextOffset();
+ MacroStartSLocOffset = SM.getNextLocalOffset();
if (NumTokens > 0) {
assert(Tokens[0].getLocation().isValid());
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Jul 19 11:10:42 2011
@@ -49,6 +49,7 @@
#include <iterator>
#include <cstdio>
#include <sys/stat.h>
+#include <iostream>
using namespace clang;
using namespace clang::serialization;
@@ -1010,6 +1011,9 @@
std::vector<LineEntry> Entries;
while (Idx < Record.size()) {
int FID = Record[Idx++];
+ assert(FID >= 0 && "Serialized line entries for non-local file.");
+ // Remap FileID from 1-based old view.
+ FID += F.SLocEntryBaseID - 1;
// Extract the line entries
unsigned NumEntries = Record[Idx++];
@@ -1188,11 +1192,6 @@
default: // Default behavior: ignore.
break;
- case SM_LINE_TABLE:
- if (ParseLineTable(F, Record))
- return Failure;
- break;
-
case SM_SLOC_FILE_ENTRY:
case SM_SLOC_BUFFER_ENTRY:
case SM_SLOC_EXPANSION_ENTRY:
@@ -1235,38 +1234,20 @@
return currPCHPath.str();
}
-/// \brief Get a cursor that's correctly positioned for reading the source
-/// location entry with the given ID.
-ASTReader::PerFileData *ASTReader::SLocCursorForID(unsigned ID) {
- assert(ID != 0 && ID <= TotalNumSLocEntries &&
- "SLocCursorForID should only be called for real IDs.");
-
- ID -= 1;
- PerFileData *F = 0;
- for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
- F = Chain[N - I - 1];
- if (ID < F->LocalNumSLocEntries)
- break;
- ID -= F->LocalNumSLocEntries;
- }
- assert(F && F->LocalNumSLocEntries > ID && "Chain corrupted");
-
- F->SLocEntryCursor.JumpToBit(F->SLocOffsets[ID]);
- return F;
-}
-
/// \brief Read in the source location entry with the given ID.
-ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) {
+ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
if (ID == 0)
return Success;
- if (ID > TotalNumSLocEntries) {
+ if (unsigned(-ID) - 2 >= TotalNumSLocEntries || ID > 0) {
Error("source location entry ID out-of-range for AST file");
return Failure;
}
- PerFileData *F = SLocCursorForID(ID);
+ PerFileData *F = GlobalSLocEntryMap.find(-ID)->second;
+ F->SLocEntryCursor.JumpToBit(F->SLocEntryOffsets[ID - F->SLocEntryBaseID]);
llvm::BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;
+ unsigned BaseOffset = F->SLocEntryBaseOffset;
++NumSLocEntriesRead;
unsigned Code = SLocEntryCursor.ReadCode();
@@ -1326,9 +1307,14 @@
return Failure;
}
- FileID FID = SourceMgr.createFileID(File, ReadSourceLocation(*F, Record[1]),
+ SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
+ if (IncludeLoc.isInvalid() && F->Type != MainFile) {
+ // This is the module's main file.
+ IncludeLoc = getImportLocation(F);
+ }
+ FileID FID = SourceMgr.createFileID(File, IncludeLoc,
(SrcMgr::CharacteristicKind)Record[2],
- ID, Record[0]);
+ ID, BaseOffset + Record[0]);
if (Record[3])
const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
.setHasLineDirectives();
@@ -1352,7 +1338,8 @@
llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1),
Name);
- FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
+ FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID,
+ BaseOffset + Offset);
if (strcmp(Name, "<built-in>") == 0) {
PCHPredefinesBlock Block = {
@@ -1372,7 +1359,7 @@
ReadSourceLocation(*F, Record[3]),
Record[4],
ID,
- Record[0]);
+ BaseOffset + Record[0]);
break;
}
}
@@ -1380,6 +1367,23 @@
return Success;
}
+/// \brief Find the location where the module F is imported.
+SourceLocation ASTReader::getImportLocation(PerFileData *F) {
+ if (F->ImportLoc.isValid())
+ return F->ImportLoc;
+ // Otherwise we have a PCH. It's considered to be "imported" at the first
+ // location of its includer.
+ if (F->Loaders.empty() || !F->Loaders[0]) {
+ // Main file is the importer. We assume that it is the first entry in the
+ // entry table. We can't ask the manager, because at the time of PCH loading
+ // the main file entry doesn't exist yet.
+ // The very first entry is the invalid instantiation loc, which takes up
+ // offsets 0 and 1.
+ return SourceLocation::getFromRawEncoding(2U);
+ }
+ return F->Loaders[0]->FirstLoc;
+}
+
/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
/// specified cursor. Read the abbreviations that are at the top of the block
/// and then leave the cursor pointing into the block.
@@ -2191,10 +2195,53 @@
Listener->ReadCounter(Record[0]);
break;
- case SOURCE_LOCATION_OFFSETS:
- F.SLocOffsets = (const uint32_t *)BlobStart;
+ case SOURCE_LOCATION_OFFSETS: {
+ F.SLocEntryOffsets = (const uint32_t *)BlobStart;
F.LocalNumSLocEntries = Record[0];
- F.LocalSLocSize = Record[1];
+ llvm::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
+ SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries, Record[1]);
+ // Make our entry in the range map. BaseID is negative and growing, so
+ // we invert it. Because we invert it, though, we need the other end of
+ // the range.
+ unsigned RangeStart =
+ unsigned(-F.SLocEntryBaseID) - F.LocalNumSLocEntries + 1;
+ GlobalSLocEntryMap.insert(std::make_pair(RangeStart, &F));
+ F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);
+
+ // Initialize the remapping table.
+ // Invalid stays invalid.
+ F.SLocRemap.insert(std::make_pair(0U, 0));
+ // This module. Base was 2 when being compiled.
+ F.SLocRemap.insert(std::make_pair(2U,
+ static_cast<int>(F.SLocEntryBaseOffset - 2)));
+ break;
+ }
+
+ case SOURCE_LOCATION_MAP: {
+ // Additional remapping information.
+ const unsigned char *Data = (const unsigned char*)BlobStart;
+ const unsigned char *DataEnd = Data + BlobLen;
+ while(Data < DataEnd) {
+ uint32_t Offset = io::ReadUnalignedLE32(Data);
+ uint16_t Len = io::ReadUnalignedLE16(Data);
+ llvm::StringRef Name = llvm::StringRef((const char*)Data, Len);
+ PerFileData *OM = Modules.lookup(Name);
+ if (!OM) {
+ Error("SourceLocation remap refers to unknown module");
+ return Failure;
+ }
+ // My Offset is mapped to OM->SLocEntryBaseOffset.
+ F.SLocRemap.insert(std::make_pair(Offset,
+ static_cast<int>(OM->SLocEntryBaseOffset - Offset)));
+ Data += Len;
+ }
+ break;
+ }
+
+
+ case SOURCE_MANAGER_LINE_TABLE:
+ if (ParseLineTable(F, Record))
+ return Failure;
break;
case FILE_SOURCE_LOCATION_OFFSETS:
@@ -2202,13 +2249,14 @@
F.LocalNumSLocFileEntries = Record[0];
break;
- case SOURCE_LOCATION_PRELOADS:
- if (PreloadSLocEntries.empty())
- PreloadSLocEntries.swap(Record);
- else
- PreloadSLocEntries.insert(PreloadSLocEntries.end(),
- Record.begin(), Record.end());
+ case SOURCE_LOCATION_PRELOADS: {
+ // Need to transform from the local view (1-based IDs) to the global view,
+ // which is based off F.SLocEntryBaseID.
+ PreloadSLocEntries.reserve(PreloadSLocEntries.size() + Record.size());
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ PreloadSLocEntries.push_back(int(Record[I] - 1) + F.SLocEntryBaseID);
break;
+ }
case STAT_CACHE: {
if (!DisableStatCache) {
@@ -2326,11 +2374,12 @@
Error("invalid DIAG_USER_MAPPINGS block in AST file");
return Failure;
}
- if (PragmaDiagMappings.empty())
- PragmaDiagMappings.swap(Record);
+
+ if (F.PragmaDiagMappings.empty())
+ F.PragmaDiagMappings.swap(Record);
else
- PragmaDiagMappings.insert(PragmaDiagMappings.end(),
- Record.begin(), Record.end());
+ F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(),
+ Record.begin(), Record.end());
break;
case CUDA_SPECIAL_DECL_REFS:
@@ -2478,7 +2527,6 @@
TotalNumSelectors = 0;
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
TotalNumSLocEntries += Chain[I]->LocalNumSLocEntries;
- NextSLocOffset += Chain[I]->LocalSLocSize;
TotalNumIdentifiers += Chain[I]->LocalNumIdentifiers;
TotalNumTypes += Chain[I]->LocalNumTypes;
TotalNumDecls += Chain[I]->LocalNumDecls;
@@ -2487,7 +2535,6 @@
TotalNumMacroDefs += Chain[I]->LocalNumMacroDefinitions;
TotalNumSelectors += Chain[I]->LocalNumSelectors;
}
- SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, NextSLocOffset);
IdentifiersLoaded.resize(TotalNumIdentifiers);
TypesLoaded.resize(TotalNumTypes);
DeclsLoaded.resize(TotalNumDecls);
@@ -2507,7 +2554,7 @@
for (unsigned I = 0, N = PreloadSLocEntries.size(); I != N; ++I) {
ASTReadResult Result = ReadSLocEntryRecord(PreloadSLocEntries[I]);
if (Result != Success)
- return Result;
+ return Failure;
}
// Check the predefines buffers.
@@ -2572,7 +2619,11 @@
if (Loc.isValid())
OriginalFileID = SourceMgr.getDecomposedLoc(Loc).first;
}
-
+ else {
+ OriginalFileID = FileID::get(Chain[0]->SLocEntryBaseID
+ + OriginalFileID.getOpaqueValue() - 1);
+ }
+
if (!OriginalFileID.isInvalid())
SourceMgr.SetPreambleFileID(OriginalFileID);
}
@@ -2590,6 +2641,8 @@
else
FirstInSource = &F;
F.Loaders.push_back(Prev);
+ // A non-module AST file's module name is $filename.
+ Modules["$" + FileName.str()] = &F;
// Set the AST file name.
F.FileName = FileName;
@@ -2668,9 +2721,8 @@
// AST block, skipping subblocks, to see if there are other
// AST blocks elsewhere.
- // Clear out any preallocated source location entries, so that
- // the source manager does not try to resolve them later.
- SourceMgr.ClearPreallocatedSLocEntries();
+ // FIXME: We can't clear loaded slocentries anymore.
+ //SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache.
if (F.StatCache)
@@ -3062,21 +3114,25 @@
}
void ASTReader::ReadPragmaDiagnosticMappings(Diagnostic &Diag) {
- unsigned Idx = 0;
- while (Idx < PragmaDiagMappings.size()) {
- SourceLocation
- Loc = SourceLocation::getFromRawEncoding(PragmaDiagMappings[Idx++]);
- while (1) {
- assert(Idx < PragmaDiagMappings.size() &&
- "Invalid data, didn't find '-1' marking end of diag/map pairs");
- if (Idx >= PragmaDiagMappings.size())
- break; // Something is messed up but at least avoid infinite loop in
- // release build.
- unsigned DiagID = PragmaDiagMappings[Idx++];
- if (DiagID == (unsigned)-1)
- break; // no more diag/map pairs for this location.
- diag::Mapping Map = (diag::Mapping)PragmaDiagMappings[Idx++];
- Diag.setDiagnosticMapping(DiagID, Map, Loc);
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[I];
+ unsigned Idx = 0;
+ while (Idx < F.PragmaDiagMappings.size()) {
+ SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);
+ while (1) {
+ assert(Idx < F.PragmaDiagMappings.size() &&
+ "Invalid data, didn't find '-1' marking end of diag/map pairs");
+ if (Idx >= F.PragmaDiagMappings.size()) {
+ break; // Something is messed up but at least avoid infinite loop in
+ // release build.
+ }
+ unsigned DiagID = F.PragmaDiagMappings[Idx++];
+ if (DiagID == (unsigned)-1) {
+ break; // no more diag/map pairs for this location.
+ }
+ diag::Mapping Map = (diag::Mapping)F.PragmaDiagMappings[Idx++];
+ Diag.setDiagnosticMapping(DiagID, Map, Loc);
+ }
}
}
}
@@ -4571,7 +4627,7 @@
return IdentifiersLoaded[ID];
}
-bool ASTReader::ReadSLocEntry(unsigned ID) {
+bool ASTReader::ReadSLocEntry(int ID) {
return ReadSLocEntryRecord(ID) != Success;
}
@@ -5175,9 +5231,10 @@
: Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
- Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation),
+ Consumer(0), FirstInSource(0), RelocatablePCH(false), isysroot(isysroot),
+ DisableValidation(DisableValidation),
DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
- NumSLocEntriesRead(0), TotalNumSLocEntries(0), NextSLocOffset(0),
+ NumSLocEntriesRead(0), TotalNumSLocEntries(0),
NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0),
@@ -5185,24 +5242,25 @@
NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
NumCurrentElementsDeserializing(0)
{
- RelocatablePCH = false;
+ SourceMgr.setExternalSLocEntrySource(this);
}
ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
Diagnostic &Diags, const char *isysroot,
bool DisableValidation, bool DisableStatCache)
: DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
- Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
- isysroot(isysroot), DisableValidation(DisableValidation),
- DisableStatCache(DisableStatCache), NumStatHits(0), NumStatMisses(0),
- NumSLocEntriesRead(0), TotalNumSLocEntries(0),
- NextSLocOffset(0), NumStatementsRead(0), TotalNumStatements(0),
- NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0),
- NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),
+ Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), FirstInSource(0),
+ RelocatablePCH(false), isysroot(isysroot),
+ DisableValidation(DisableValidation), DisableStatCache(DisableStatCache),
+ NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0),
+ TotalNumSLocEntries(0), NumStatementsRead(0),
+ TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0),
+ NumSelectorsRead(0), NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),
TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0),
TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0),
- TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) {
- RelocatablePCH = false;
+ TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0)
+{
+ SourceMgr.setExternalSLocEntrySource(this);
}
ASTReader::~ASTReader() {
@@ -5231,13 +5289,13 @@
}
ASTReader::PerFileData::PerFileData(ASTFileType Ty)
- : Type(Ty), SizeInBits(0), LocalNumSLocEntries(0), SLocOffsets(0),
- SLocFileOffsets(0), LocalSLocSize(0),
- LocalNumIdentifiers(0), IdentifierOffsets(0), IdentifierTableData(0),
+ : Type(Ty), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0),
+ SLocEntryBaseOffset(0), SLocEntryOffsets(0),
+ SLocFileOffsets(0), LocalNumIdentifiers(0),
+ IdentifierOffsets(0), IdentifierTableData(0),
IdentifierLookupTable(0), LocalNumMacroDefinitions(0),
- MacroDefinitionOffsets(0),
- LocalNumHeaderFileInfos(0), HeaderFileInfoTableData(0),
- HeaderFileInfoTable(0),
+ MacroDefinitionOffsets(0), LocalNumHeaderFileInfos(0),
+ HeaderFileInfoTableData(0), HeaderFileInfoTable(0),
LocalNumSelectors(0), SelectorOffsets(0),
SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
DeclOffsets(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Jul 19 11:10:42 2011
@@ -45,8 +45,10 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
+#include <algorithm>
#include <cstdio>
#include <string.h>
+#include <utility>
using namespace clang;
using namespace clang::serialization;
@@ -790,7 +792,6 @@
RECORD(SM_SLOC_BUFFER_ENTRY);
RECORD(SM_SLOC_BUFFER_BLOB);
RECORD(SM_SLOC_EXPANSION_ENTRY);
- RECORD(SM_LINE_TABLE);
// Preprocessor Block.
BLOCK(PREPROCESSOR_BLOCK);
@@ -1416,43 +1417,6 @@
unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream);
unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream);
- // Write the line table.
- if (SourceMgr.hasLineTable()) {
- LineTableInfo &LineTable = SourceMgr.getLineTable();
-
- // Emit the file names
- Record.push_back(LineTable.getNumFilenames());
- for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
- // Emit the file name
- const char *Filename = LineTable.getFilename(I);
- Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
- unsigned FilenameLen = Filename? strlen(Filename) : 0;
- Record.push_back(FilenameLen);
- if (FilenameLen)
- Record.insert(Record.end(), Filename, Filename + FilenameLen);
- }
-
- // Emit the line entries
- for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
- L != LEnd; ++L) {
- // Emit the file ID
- Record.push_back(L->first);
-
- // Emit the line entries
- Record.push_back(L->second.size());
- for (std::vector<LineEntry>::iterator LE = L->second.begin(),
- LEEnd = L->second.end();
- LE != LEEnd; ++LE) {
- Record.push_back(LE->FileOffset);
- Record.push_back(LE->LineNo);
- Record.push_back(LE->FilenameID);
- Record.push_back((unsigned)LE->FileKind);
- Record.push_back(LE->IncludeOffset);
- }
- }
- Stream.EmitRecord(SM_LINE_TABLE, Record);
- }
-
// Write out the source location entry table. We skip the first
// entry, which is always the same dummy entry.
std::vector<uint32_t> SLocEntryOffsets;
@@ -1460,12 +1424,11 @@
// We will go through them in ASTReader::validateFileEntries().
std::vector<uint32_t> SLocFileEntryOffsets;
RecordData PreloadSLocs;
- unsigned BaseSLocID = Chain ? Chain->getTotalNumSLocs() : 0;
- SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1 - BaseSLocID);
- for (unsigned I = BaseSLocID + 1, N = SourceMgr.sloc_entry_size();
+ SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1);
+ for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size();
I != N; ++I) {
// Get this source location entry.
- const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
+ const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);
// Record the offset of this source-location entry.
SLocEntryOffsets.push_back(Stream.GetCurrentBitNo());
@@ -1483,7 +1446,8 @@
Record.clear();
Record.push_back(Code);
- Record.push_back(SLoc->getOffset());
+ // Starting offset of this entry within this module, so skip the dummy.
+ Record.push_back(SLoc->getOffset() - 2);
if (SLoc->isFile()) {
const SrcMgr::FileInfo &File = SLoc->getFile();
Record.push_back(File.getIncludeLoc().getRawEncoding());
@@ -1535,8 +1499,9 @@
llvm::StringRef(Buffer->getBufferStart(),
Buffer->getBufferSize() + 1));
- if (strcmp(Name, "<built-in>") == 0)
- PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size());
+ if (strcmp(Name, "<built-in>") == 0) {
+ PreloadSLocs.push_back(SLocEntryOffsets.size());
+ }
}
} else {
// The source location entry is a macro expansion.
@@ -1546,9 +1511,9 @@
Record.push_back(Inst.getInstantiationLocEnd().getRawEncoding());
// Compute the token length for this macro expansion.
- unsigned NextOffset = SourceMgr.getNextOffset();
+ unsigned NextOffset = SourceMgr.getNextLocalOffset();
if (I + 1 != N)
- NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();
+ NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset();
Record.push_back(NextOffset - SLoc->getOffset() - 1);
Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record);
}
@@ -1565,17 +1530,54 @@
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
Record.clear();
Record.push_back(SOURCE_LOCATION_OFFSETS);
Record.push_back(SLocEntryOffsets.size());
- unsigned BaseOffset = Chain ? Chain->getNextSLocOffset() : 0;
- Record.push_back(SourceMgr.getNextOffset() - BaseOffset);
+ Record.push_back(SourceMgr.getNextLocalOffset() - 1); // skip dummy
Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, data(SLocEntryOffsets));
+ // If we have module dependencies, write the mapping from source locations to
+ // their containing modules, so that the reader can build the remapping.
+ if (Chain) {
+ // The map consists solely of a blob with the following format:
+ // *(offset:i32 len:i16 name:len*i8)
+ // Sorted by offset.
+ typedef std::pair<uint32_t, llvm::StringRef> ModuleOffset;
+ llvm::SmallVector<ModuleOffset, 16> Modules;
+ Modules.reserve(Chain->Modules.size());
+ for (llvm::StringMap<ASTReader::PerFileData*>::const_iterator
+ I = Chain->Modules.begin(), E = Chain->Modules.end();
+ I != E; ++I) {
+ Modules.push_back(ModuleOffset(I->getValue()->SLocEntryBaseOffset,
+ I->getKey()));
+ }
+ std::sort(Modules.begin(), Modules.end());
+
+ Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_MAP));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned SLocMapAbbrev = Stream.EmitAbbrev(Abbrev);
+ llvm::SmallString<2048> Buffer;
+ {
+ llvm::raw_svector_ostream Out(Buffer);
+ for (llvm::SmallVector<ModuleOffset, 16>::iterator I = Modules.begin(),
+ E = Modules.end();
+ I != E; ++I) {
+ io::Emit32(Out, I->first);
+ io::Emit16(Out, I->second.size());
+ Out.write(I->second.data(), I->second.size());
+ }
+ }
+ Record.clear();
+ Record.push_back(SOURCE_LOCATION_MAP);
+ Stream.EmitRecordWithBlob(SLocMapAbbrev, Record,
+ Buffer.data(), Buffer.size());
+ }
+
Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(FILE_SOURCE_LOCATION_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
@@ -1591,6 +1593,49 @@
// Write the source location entry preloads array, telling the AST
// reader which source locations entries it should load eagerly.
Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs);
+
+ // Write the line table. It depends on remapping working, so it must come
+ // after the source location offsets.
+ if (SourceMgr.hasLineTable()) {
+ LineTableInfo &LineTable = SourceMgr.getLineTable();
+
+ Record.clear();
+ // Emit the file names
+ Record.push_back(LineTable.getNumFilenames());
+ for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) {
+ // Emit the file name
+ const char *Filename = LineTable.getFilename(I);
+ Filename = adjustFilenameForRelocatablePCH(Filename, isysroot);
+ unsigned FilenameLen = Filename? strlen(Filename) : 0;
+ Record.push_back(FilenameLen);
+ if (FilenameLen)
+ Record.insert(Record.end(), Filename, Filename + FilenameLen);
+ }
+
+ // Emit the line entries
+ for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end();
+ L != LEnd; ++L) {
+ // Only emit entries for local files.
+ if (L->first < 0)
+ continue;
+
+ // Emit the file ID
+ Record.push_back(L->first);
+
+ // Emit the line entries
+ Record.push_back(L->second.size());
+ for (std::vector<LineEntry>::iterator LE = L->second.begin(),
+ LEEnd = L->second.end();
+ LE != LEEnd; ++LE) {
+ Record.push_back(LE->FileOffset);
+ Record.push_back(LE->LineNo);
+ Record.push_back(LE->FilenameID);
+ Record.push_back((unsigned)LE->FileKind);
+ Record.push_back(LE->IncludeOffset);
+ }
+ }
+ Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record);
+ }
}
//===----------------------------------------------------------------------===//
@@ -3926,6 +3971,7 @@
FirstMacroID == NextMacroID &&
FirstCXXBaseSpecifiersID == NextCXXBaseSpecifiersID &&
"Setting chain after writing has started.");
+
Chain = Reader;
FirstDeclID += Chain->getTotalNumDecls();
Added: cfe/trunk/test/Index/Inputs/preamble_macro_template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/preamble_macro_template.h?rev=135484&view=auto
==============================================================================
--- cfe/trunk/test/Index/Inputs/preamble_macro_template.h (added)
+++ cfe/trunk/test/Index/Inputs/preamble_macro_template.h Tue Jul 19 11:10:42 2011
@@ -0,0 +1,6 @@
+#define STATIC_CAST static_cast
+
+template<typename T>
+void foo(T *p) {
+ (void)STATIC_CAST<T*>(0);
+}
Added: cfe/trunk/test/Index/preamble_macro_template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/preamble_macro_template.cpp?rev=135484&view=auto
==============================================================================
--- cfe/trunk/test/Index/preamble_macro_template.cpp (added)
+++ cfe/trunk/test/Index/preamble_macro_template.cpp Tue Jul 19 11:10:42 2011
@@ -0,0 +1,15 @@
+template void foo(int *);
+
+int main() { }
+
+// RUN: c-index-test -write-pch %t.pch -x c++-header %S/Inputs/preamble_macro_template.h
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s | FileCheck %s
+// CHECK: preamble_macro_template.h:4:6: FunctionDecl=foo:4:6 (Definition) [Specialization of foo:4:6] Extent=[4:1 - 6:2]
+// CHECK: preamble_macro_template.h:4:13: ParmDecl=p:4:13 (Definition) Extent=[4:10 - 4:14]
+// CHECK: preamble_macro_template.h:4:16: UnexposedStmt= Extent=[4:16 - 6:2]
+// CHECK: preamble_macro_template.h:5:3: UnexposedExpr= Extent=[5:3 - 5:27]
+// CHECK: preamble_macro_template.h:1:21: UnexposedExpr= Extent=[1:21 - 5:27]
+// CHECK: preamble_macro_template.h:5:25: UnexposedExpr= Extent=[5:25 - 5:26]
+// CHECK: preamble_macro_template.h:5:25: UnexposedExpr= Extent=[5:25 - 5:26]
+// CHECK: preamble_macro_template.cpp:3:5: FunctionDecl=main:3:5 (Definition) Extent=[3:1 - 3:15]
+// CHECK: preamble_macro_template.cpp:3:12: UnexposedStmt= Extent=[3:12 - 3:15]
Modified: cfe/trunk/test/PCH/reinclude.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/reinclude.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/test/PCH/reinclude.cpp (original)
+++ cfe/trunk/test/PCH/reinclude.cpp Tue Jul 19 11:10:42 2011
@@ -4,7 +4,7 @@
// RUN: %clang_cc1 -x c++-header %S/reinclude1.h -emit-pch -o %t1
// RUN: %clang_cc1 -x c++-header %S/reinclude2.h -include-pch %t1 -emit-pch -o %t2
// RUN: %clang_cc1 %s -include-pch %t2 -fsyntax-only -verify
-// RUN: %clang_cc1 -x c++-header %S/reinclude2.h -include-pch %t1 -emit-pch -o %t2 -chained-pch
+// RUN: %clang_cc1 -x c++-header %S/reinclude2.h -include-pch %t1 -emit-pch -o %t2
// RUN: %clang_cc1 %s -include-pch %t2 -fsyntax-only -verify
int q2 = A::y;
Modified: cfe/trunk/tools/libclang/CIndexInclusionStack.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexInclusionStack.cpp?rev=135484&r1=135483&r2=135484&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexInclusionStack.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexInclusionStack.cpp Tue Jul 19 11:10:42 2011
@@ -30,18 +30,21 @@
ASTContext &Ctx = CXXUnit->getASTContext();
llvm::SmallVector<CXSourceLocation, 10> InclusionStack;
- unsigned i = SM.sloc_loaded_entry_size();
- unsigned n = SM.sloc_entry_size();
+ unsigned n = SM.local_sloc_entry_size();
// In the case where all the SLocEntries are in an external source, traverse
// those SLocEntries as well. This is the case where we are looking
// at the inclusion stack of an AST/PCH file.
- if (i >= n)
- i = 0;
-
- for ( ; i < n ; ++i) {
+ const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const;
+ if (n == 1) {
+ Getter = &SourceManager::getLoadedSLocEntry;
+ n = SM.loaded_sloc_entry_size();
+ } else
+ Getter = &SourceManager::getLocalSLocEntry;
+
+ for (unsigned i = 0 ; i < n ; ++i) {
bool Invalid = false;
- const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i, &Invalid);
+ const SrcMgr::SLocEntry &SL = (SM.*Getter)(i, &Invalid);
if (!SL.isFile() || Invalid)
continue;
More information about the cfe-commits
mailing list