diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 76 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 38 |
2 files changed, 108 insertions, 6 deletions
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. |