]> granicus.if.org Git - clang/commitdiff
start plumbing together the line table information. So far we just
authorChris Lattner <sabre@nondot.org>
Mon, 26 Jan 2009 07:57:50 +0000 (07:57 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 26 Jan 2009 07:57:50 +0000 (07:57 +0000)
unique the Filenames in #line directives, assigning them UIDs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63010 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/SourceManager.h
lib/Basic/SourceManager.cpp
lib/Lex/PPDirectives.cpp

index a58662443d14bdc9331671fd54f62b23a32635da..d8c17e11da584952575c7554fec1d5f694842916 100644 (file)
@@ -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.
   //===--------------------------------------------------------------------===//
@@ -552,6 +546,15 @@ public:
     return getFileCharacteristic(Loc) != SrcMgr::C_User;
   }
   
+  //===--------------------------------------------------------------------===//
+  // Line Table Manipulation Routines
+  //===--------------------------------------------------------------------===//
+  
+  /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
+  /// 
+  unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
+  
+  
   //===--------------------------------------------------------------------===//
   // Other miscellaneous methods.
   //===--------------------------------------------------------------------===//
index fcca97774df1dbc1bf36a117504018955de688cd..42e6040b7464d84ca57556bc10dfd42f93dcedb8 100644 (file)
@@ -58,10 +58,86 @@ const llvm::MemoryBuffer *ContentCache::getBuffer() const {
   return Buffer;
 }
 
+//===--------------------------------------------------------------------===//
+// 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 *
index 5b45ddd35e9afd2a2d79920534d248d49e936830..099dfb4aef09b934fc3cc47c7b49e5288f2c25bc 100644 (file)
@@ -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.