diff options
-rw-r--r-- | clang/include/clang/Basic/SourceManager.h | 35 | ||||
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 76 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 38 |
3 files changed, 127 insertions, 22 deletions
diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index a58662443d1..d8c17e11da5 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -31,6 +31,7 @@ class SourceManager; class FileManager; class FileEntry; class IdentifierTokenInfo; +class LineTableInfo; /// SrcMgr - Public enums and private classes that are part of the /// SourceManager implementation. @@ -224,7 +225,6 @@ namespace SrcMgr { return E; } }; - } // end SrcMgr namespace. } // end clang namespace @@ -275,6 +275,10 @@ class SourceManager { /// is very common to look up many tokens from the same file. mutable FileID LastFileIDLookup; + /// LineTable - This holds information for #line directives. It is referenced + /// by indices from SLocEntryTable. + LineTableInfo *LineTable; + /// LastLineNo - These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. mutable FileID LastLineNoFileIDQuery; @@ -292,23 +296,13 @@ class SourceManager { explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); public: - SourceManager() : NumLinearScans(0), NumBinaryProbes(0) { + SourceManager() : LineTable(0), NumLinearScans(0), NumBinaryProbes(0) { clearIDTables(); } - ~SourceManager() {} - - void clearIDTables() { - MainFileID = FileID(); - SLocEntryTable.clear(); - LastLineNoFileIDQuery = FileID(); - LastLineNoContentCache = 0; - LastFileIDLookup = FileID(); - - // Use up FileID #0 as an invalid instantiation. - NextOffset = 0; - createInstantiationLoc(SourceLocation(), SourceLocation(), 1); - } - + ~SourceManager(); + + void clearIDTables(); + //===--------------------------------------------------------------------===// // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// @@ -553,6 +547,15 @@ public: } //===--------------------------------------------------------------------===// + // Line Table Manipulation Routines + //===--------------------------------------------------------------------===// + + /// getLineTableFilenameID - Return the uniqued ID for the specified filename. + /// + unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + + + //===--------------------------------------------------------------------===// // Other miscellaneous methods. //===--------------------------------------------------------------------===// diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index fcca97774df..42e6040b746 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -59,9 +59,85 @@ const llvm::MemoryBuffer *ContentCache::getBuffer() const { } //===--------------------------------------------------------------------===// +// Line Table Implementation +//===--------------------------------------------------------------------===// + +namespace clang { +/// LineTableInfo - This class is used to hold and unique data used to +/// represent #line information. +class LineTableInfo { + /// FilenameIDs - This map is used to assign unique IDs to filenames in + /// #line directives. This allows us to unique the filenames that + /// frequently reoccur and reference them with indices. FilenameIDs holds + /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID + /// to string. + llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs; + std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID; +public: + LineTableInfo() { + } + + void clear() { + FilenameIDs.clear(); + FilenamesByID.clear(); + } + + ~LineTableInfo() {} + + unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + +}; +} // namespace clang + + + + +unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) { + // Look up the filename in the string table, returning the pre-existing value + // if it exists. + llvm::StringMapEntry<unsigned> &Entry = + FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U); + if (Entry.getValue() != ~0U) + return Entry.getValue(); + + // Otherwise, assign this the next available ID. + Entry.setValue(FilenamesByID.size()); + FilenamesByID.push_back(&Entry); + return FilenamesByID.size()-1; +} + +/// getLineTableFilenameID - Return the uniqued ID for the specified filename. +/// +unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) { + if (LineTable == 0) + LineTable = new LineTableInfo(); + return LineTable->getLineTableFilenameID(Ptr, Len); +} + + +//===--------------------------------------------------------------------===// // Private 'Create' methods. //===--------------------------------------------------------------------===// +SourceManager::~SourceManager() { + delete LineTable; +} + +void SourceManager::clearIDTables() { + MainFileID = FileID(); + SLocEntryTable.clear(); + LastLineNoFileIDQuery = FileID(); + LastLineNoContentCache = 0; + LastFileIDLookup = FileID(); + + if (LineTable) + LineTable->clear(); + + // Use up FileID #0 as an invalid instantiation. + NextOffset = 0; + createInstantiationLoc(SourceLocation(), SourceLocation(), 1); +} + /// getOrCreateContentCache - Create or return a cached ContentCache for the /// specified file. const ContentCache * diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 5b45ddd35e9..099dfb4aef0 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -621,6 +621,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) { if (LineNo >= LineLimit) Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit; + int FilenameID = -1; Token StrTok; Lex(StrTok); @@ -633,6 +634,18 @@ void Preprocessor::HandleLineDirective(Token &Tok) { DiscardUntilEndOfDirective(); return; } else { + // Parse and validate the string, converting it into a unique ID. + StringLiteralParser Literal(&StrTok, 1, *this); + assert(!Literal.AnyWide && "Didn't allow wide strings in"); + if (Literal.hadError) + return DiscardUntilEndOfDirective(); + if (Literal.Pascal) { + Diag(StrTok, diag::err_pp_linemarker_invalid_filename); + return DiscardUntilEndOfDirective(); + } + FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(), + Literal.GetStringLength()); + // Verify that there is nothing after the string, other than EOM. CheckEndOfDirective("#line"); } @@ -671,6 +684,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, // We must have 3 if there are still flags. if (FlagVal != 3) { PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); + PP.DiscardUntilEndOfDirective(); return true; } @@ -684,6 +698,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, // We must have 4 if there is yet another flag. if (FlagVal != 4) { PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); + PP.DiscardUntilEndOfDirective(); return true; } @@ -694,6 +709,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, // There are no more valid flags here. PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); + PP.DiscardUntilEndOfDirective(); return true; } @@ -717,22 +733,32 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { bool IsFileEntry = false, IsFileExit = false; bool IsSystemHeader = false, IsExternCHeader = false; - + int FilenameID = -1; + // If the StrTok is "eom", then it wasn't present. Otherwise, it must be a // string followed by eom. if (StrTok.is(tok::eom)) ; // ok else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_linemarker_invalid_filename); - DiscardUntilEndOfDirective(); - return; + return DiscardUntilEndOfDirective(); } else { + // Parse and validate the string, converting it into a unique ID. + StringLiteralParser Literal(&StrTok, 1, *this); + assert(!Literal.AnyWide && "Didn't allow wide strings in"); + if (Literal.hadError) + return DiscardUntilEndOfDirective(); + if (Literal.Pascal) { + Diag(StrTok, diag::err_pp_linemarker_invalid_filename); + return DiscardUntilEndOfDirective(); + } + FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(), + Literal.GetStringLength()); + // If a filename was present, read any flags that are present. if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, - IsSystemHeader, IsExternCHeader, *this)) { - DiscardUntilEndOfDirective(); + IsSystemHeader, IsExternCHeader, *this)) return; - } } // FIXME: do something with the #line info. |