[cfe-commits] r39092 - in /cfe/cfe/trunk: Lex/Lexer.cpp Lex/Pragma.cpp Lex/Preprocessor.cpp include/clang/Lex/Lexer.h include/clang/Lex/Preprocessor.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:27:28 PDT 2007


Author: sabre
Date: Wed Jul 11 11:27:27 2007
New Revision: 39092

URL: http://llvm.org/viewvc/llvm-project?rev=39092&view=rev
Log:
Refactor the paths used for checking and getting the spelling of #include
filenames (and also '#pragma GCC dependency' of course).  Now, assuming
no cleaning is needed, we can go all the way from lexing the filename to
doing filename lookups with no mallocs.  This speeds up user PP time from
0.077 to 0.075s for Cocoa.h (2.6%).

Modified:
    cfe/cfe/trunk/Lex/Lexer.cpp
    cfe/cfe/trunk/Lex/Pragma.cpp
    cfe/cfe/trunk/Lex/Preprocessor.cpp
    cfe/cfe/trunk/include/clang/Lex/Lexer.h
    cfe/cfe/trunk/include/clang/Lex/Preprocessor.h

Modified: cfe/cfe/trunk/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Lexer.cpp?rev=39092&r1=39091&r2=39092&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Lexer.cpp (original)
+++ cfe/cfe/trunk/Lex/Lexer.cpp Wed Jul 11 11:27:27 2007
@@ -884,7 +884,7 @@
 
 /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
 /// (potentially) macro expand the filename.
-std::string Lexer::LexIncludeFilename(LexerToken &FilenameTok) {
+void Lexer::LexIncludeFilename(LexerToken &FilenameTok) {
   assert(ParsingPreprocessorDirective &&
          ParsingFilename == false &&
          "Must be in a preprocessing directive!");
@@ -895,46 +895,12 @@
   // Lex the filename.
   Lex(FilenameTok);
 
-  // We should have gotten the filename now.
+  // We should have obtained the filename now.
   ParsingFilename = false;
-
-  // No filename?
-  if (FilenameTok.getKind() == tok::eom) {
-    Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
-    return "";
-  }
   
-  // Get the text form of the filename.
-  std::string Filename = PP.getSpelling(FilenameTok);
-  assert(!Filename.empty() && "Can't have tokens with empty spellings!");
-  
-  // Make sure the filename is <x> or "x".
-  if (Filename[0] == '<') {
-    if (Filename[Filename.size()-1] != '>') {
-      Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
-      FilenameTok.setKind(tok::eom);
-      return "";
-    }
-  } else if (Filename[0] == '"') {
-    if (Filename[Filename.size()-1] != '"') {
-      Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
-      FilenameTok.setKind(tok::eom);
-      return "";
-    }
-  } else {
+  // No filename?
+  if (FilenameTok.getKind() == tok::eom)
     Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
-    FilenameTok.setKind(tok::eom);
-    return "";
-  }
-  
-  // Diagnose #include "" as invalid.
-  if (Filename.size() == 2) {
-    Diag(FilenameTok.getLocation(), diag::err_pp_empty_filename);
-    FilenameTok.setKind(tok::eom);
-    return "";
-  }
-        
-  return Filename;
 }
 
 /// ReadToEndOfLine - Read the rest of the current preprocessor line as an

Modified: cfe/cfe/trunk/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Pragma.cpp?rev=39092&r1=39091&r2=39092&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Pragma.cpp (original)
+++ cfe/cfe/trunk/Lex/Pragma.cpp Wed Jul 11 11:27:27 2007
@@ -18,6 +18,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallVector.h"
 using namespace llvm;
 using namespace clang;
 
@@ -246,20 +247,27 @@
 ///
 void Preprocessor::HandlePragmaDependency(LexerToken &DependencyTok) {
   LexerToken FilenameTok;
-  std::string Filename = CurLexer->LexIncludeFilename(FilenameTok);
+  CurLexer->LexIncludeFilename(FilenameTok);
 
   // If the token kind is EOM, the error has already been diagnosed.
   if (FilenameTok.getKind() == tok::eom)
     return;
   
-  // Find out whether the filename is <x> or "x".
-  bool isAngled = Filename[0] == '<';
+  // Reserve a buffer to get the spelling.
+  SmallVector<char, 128> FilenameBuffer;
+  FilenameBuffer.resize(FilenameTok.getLength());
+  
+  const char *FilenameStart = &FilenameBuffer[0], *FilenameEnd;
+  bool isAngled = GetIncludeFilenameSpelling(FilenameTok,
+                                             FilenameStart, FilenameEnd);
+  // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+  // error.
+  if (FilenameStart == 0)
+    return;
   
   // Search include directories for this file.
   const DirectoryLookup *CurDir;
-
-  // Remove the quotes.
-  const FileEntry *File = LookupFile(&Filename[1], &Filename[Filename.size()-1],
+  const FileEntry *File = LookupFile(FilenameStart, FilenameEnd,
                                      isAngled, 0, CurDir);
   if (File == 0)
     return Diag(FilenameTok, diag::err_pp_file_not_found);

Modified: cfe/cfe/trunk/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Preprocessor.cpp?rev=39092&r1=39091&r2=39092&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:27:27 2007
@@ -1474,6 +1474,55 @@
 // Preprocessor Include Directive Handling.
 //===----------------------------------------------------------------------===//
 
+/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+/// checked and spelled filename, e.g. as an operand of #include. This returns
+/// true if the input filename was in <>'s or false if it were in ""'s.  The
+/// caller is expected to provide a buffer that is large enough to hold the
+/// spelling of the filename, but is also expected to handle the case when
+/// this method decides to use a different buffer.
+bool Preprocessor::GetIncludeFilenameSpelling(const LexerToken &FilenameTok,
+                                              const char *&BufStart,
+                                              const char *&BufEnd) {
+  // Get the text form of the filename.
+  unsigned Len = getSpelling(FilenameTok, BufStart);
+  BufEnd = BufStart+Len;
+  assert(BufStart != BufEnd && "Can't have tokens with empty spellings!");
+  
+  // Make sure the filename is <x> or "x".
+  bool isAngled;
+  if (BufStart[0] == '<') {
+    if (BufEnd[-1] != '>') {
+      Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+      BufStart = 0;
+      return true;
+    }
+    isAngled = true;
+  } else if (BufStart[0] == '"') {
+    if (BufEnd[-1] != '"') {
+      Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+      BufStart = 0;
+      return true;
+    }
+    isAngled = false;
+  } else {
+    Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+    BufStart = 0;
+    return true;
+  }
+  
+  // Diagnose #include "" as invalid.
+  if (BufEnd-BufStart <= 2) {
+    Diag(FilenameTok.getLocation(), diag::err_pp_empty_filename);
+    BufStart = 0;
+    return "";
+  }
+  
+  // Skip the brackets.
+  ++BufStart;
+  --BufEnd;
+  return isAngled;
+}
+
 /// HandleIncludeDirective - The "#include" tokens have just been read, read the
 /// file to be included from the lexer, then include it!  This is a common
 /// routine with functionality shared between #include, #include_next and
@@ -1483,12 +1532,24 @@
                                           bool isImport) {
 
   LexerToken FilenameTok;
-  std::string Filename = CurLexer->LexIncludeFilename(FilenameTok);
+  CurLexer->LexIncludeFilename(FilenameTok);
   
   // If the token kind is EOM, the error has already been diagnosed.
   if (FilenameTok.getKind() == tok::eom)
     return;
   
+  // Reserve a buffer to get the spelling.
+  SmallVector<char, 128> FilenameBuffer;
+  FilenameBuffer.resize(FilenameTok.getLength());
+  
+  const char *FilenameStart = &FilenameBuffer[0], *FilenameEnd;
+  bool isAngled = GetIncludeFilenameSpelling(FilenameTok,
+                                             FilenameStart, FilenameEnd);
+  // If GetIncludeFilenameSpelling set the start ptr to null, there was an
+  // error.
+  if (FilenameStart == 0)
+    return;
+  
   // Verify that there is nothing after the filename, other than EOM.  Use the
   // preprocessor to lex this in case lexing the filename entered a macro.
   CheckEndOfDirective("#include");
@@ -1497,13 +1558,9 @@
   if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1)
     return Diag(FilenameTok, diag::err_pp_include_too_deep);
   
-  // Find out whether the filename is <x> or "x".
-  bool isAngled = Filename[0] == '<';
-  
   // Search include directories.
   const DirectoryLookup *CurDir;
-  // Remove the quotes from the filename.
-  const FileEntry *File = LookupFile(&Filename[1], &Filename[Filename.size()-1],
+  const FileEntry *File = LookupFile(FilenameStart, FilenameEnd,
                                      isAngled, LookupFrom, CurDir);
   if (File == 0)
     return Diag(FilenameTok, diag::err_pp_file_not_found);

Modified: cfe/cfe/trunk/include/clang/Lex/Lexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/Lexer.h?rev=39092&r1=39091&r2=39092&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Lexer.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Lexer.h Wed Jul 11 11:27:27 2007
@@ -341,9 +341,8 @@
   
   /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
   /// (potentially) macro expand the filename.  If the sequence parsed is not
-  /// lexically legal, emit a diagnostic and return a result EOM token.  Return
-  /// the spelled and checked filename.
-  std::string LexIncludeFilename(LexerToken &Result);
+  /// lexically legal, emit a diagnostic and return a result EOM token.
+  void LexIncludeFilename(LexerToken &Result);
 };
 
 

Modified: cfe/cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=39092&r1=39091&r2=39092&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:27:27 2007
@@ -403,6 +403,15 @@
   /// start lexing tokens from it instead of the current buffer.
   void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
   
+  /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
+  /// checked and spelled filename, e.g. as an operand of #include. This returns
+  /// true if the input filename was in <>'s or false if it were in ""'s.  The
+  /// caller is expected to provide a buffer that is large enough to hold the
+  /// spelling of the filename, but is also expected to handle the case when
+  /// this method decides to use a different buffer.
+  bool GetIncludeFilenameSpelling(const LexerToken &FNTok,
+                                  const char *&BufStart, const char *&BufEnd);
+  
   /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
   /// return null on failure.  isAngled indicates whether the file reference is
   /// for system #include's or not (i.e. using <> instead of "").





More information about the cfe-commits mailing list