[cfe-commits] r38574 - in /cfe/cfe/trunk: Basic/FileManager.cpp Lex/Lexer.cpp Lex/Preprocessor.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Basic/FileManager.h include/clang/Lex/Lexer.h include/clang/Lex/Preprocessor.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:22:50 PDT 2007


Author: sabre
Date: Wed Jul 11 11:22:50 2007
New Revision: 38574

URL: http://llvm.org/viewvc/llvm-project?rev=38574&view=rev
Log:
implement #pragma GCC dependency

Modified:
    cfe/cfe/trunk/Basic/FileManager.cpp
    cfe/cfe/trunk/Lex/Lexer.cpp
    cfe/cfe/trunk/Lex/Preprocessor.cpp
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Basic/FileManager.h
    cfe/cfe/trunk/include/clang/Lex/Lexer.h
    cfe/cfe/trunk/include/clang/Lex/Preprocessor.h

Modified: cfe/cfe/trunk/Basic/FileManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Basic/FileManager.cpp?rev=38574&r1=38573&r2=38574&view=diff

==============================================================================
--- cfe/cfe/trunk/Basic/FileManager.cpp (original)
+++ cfe/cfe/trunk/Basic/FileManager.cpp Wed Jul 11 11:22:50 2007
@@ -113,11 +113,12 @@
   
   if (UFE)  // Already have an entry with this inode, return it.
     return Ent = UFE;
-  
+
   // Otherwise, we don't have this directory yet, add it.
   FileEntry *FE = new FileEntry();
-  FE->Size      = StatBuf.st_size;
   FE->Name      = Filename;
+  FE->Size      = StatBuf.st_size;
+  FE->ModTime   = StatBuf.st_mtime;
   FE->Dir       = DirInfo;
   FE->UID       = NextFileUID++;
   return Ent = UFE = FE;

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

==============================================================================
--- cfe/cfe/trunk/Lex/Lexer.cpp (original)
+++ cfe/cfe/trunk/Lex/Lexer.cpp Wed Jul 11 11:22:50 2007
@@ -783,7 +783,7 @@
 
 /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
 /// (potentially) macro expand the filename.
-void Lexer::LexIncludeFilename(LexerToken &Result) {
+std::string Lexer::LexIncludeFilename(LexerToken &FilenameTok) {
   assert(ParsingPreprocessorDirective &&
          ParsingFilename == false &&
          "Must be in a preprocessing directive!");
@@ -791,33 +791,49 @@
   // We are now parsing a filename!
   ParsingFilename = true;
   
-  // There should be exactly two tokens here if everything is good: first the
-  // filename, then the EOM.
-  Lex(Result);
+  // Lex the filename.
+  Lex(FilenameTok);
 
   // We should have gotten the filename now.
   ParsingFilename = false;
 
   // No filename?
-  if (Result.getKind() == tok::eom) {
-    PP.Diag(Result, diag::err_pp_expects_filename);
-    return;
+  if (FilenameTok.getKind() == tok::eom) {
+    PP.Diag(FilenameTok, diag::err_pp_expects_filename);
+    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.
-  LexerToken EndTok;
-  PP.Lex(EndTok);
-
-  if (EndTok.getKind() != tok::eom) {
-    PP.Diag(EndTok, diag::ext_pp_extra_tokens_at_eol, "#include");
-    
-    // Lex until the end of the preprocessor directive line.
-    while (EndTok.getKind() != tok::eom)
-      PP.Lex(EndTok);
-    
-    Result.SetKind(tok::eom);
+  // 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] != '>') {
+      PP.Diag(FilenameTok, diag::err_pp_expects_filename);
+      FilenameTok.SetKind(tok::eom);
+      return "";
+    }
+  } else if (Filename[0] == '"') {
+    if (Filename[Filename.size()-1] != '"') {
+      PP.Diag(FilenameTok, diag::err_pp_expects_filename);
+      FilenameTok.SetKind(tok::eom);
+      return "";
+    }
+  } else {
+    PP.Diag(FilenameTok, diag::err_pp_expects_filename);
+    FilenameTok.SetKind(tok::eom);
+    return "";
+  }
+  
+  // Diagnose #include "" as invalid.
+  if (Filename.size() == 2) {
+    PP.Diag(FilenameTok, 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/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Preprocessor.cpp?rev=38574&r1=38573&r2=38574&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:22:50 2007
@@ -938,41 +938,26 @@
                                           bool isImport) {
   ++NumIncluded;
   LexerToken FilenameTok;
-  CurLexer->LexIncludeFilename(FilenameTok);
+  std::string Filename = CurLexer->LexIncludeFilename(FilenameTok);
   
   // If the token kind is EOM, the error has already been diagnosed.
   if (FilenameTok.getKind() == tok::eom)
     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");
 
   // Check that we don't have infinite #include recursion.
   if (IncludeStack.size() == MaxAllowedIncludeStackDepth-1)
     return Diag(FilenameTok, diag::err_pp_include_too_deep);
   
-  // Get the text form of the filename.
-  std::string Filename = getSpelling(FilenameTok);
-  assert(!Filename.empty() && "Can't have tokens with empty spellings!");
-  
-  // Make sure the filename is <x> or "x".
-  bool isAngled;
-  if (Filename[0] == '<') {
-    isAngled = true;
-    if (Filename[Filename.size()-1] != '>')
-      return Diag(FilenameTok, diag::err_pp_expects_filename);
-  } else if (Filename[0] == '"') {
-    isAngled = false;
-    if (Filename[Filename.size()-1] != '"')
-      return Diag(FilenameTok, diag::err_pp_expects_filename);
-  } else {
-    return Diag(FilenameTok, diag::err_pp_expects_filename);
-  }
+  // Find out whether the filename is <x> or "x".
+  bool isAngled = Filename[0] == '<';
   
   // Remove the quotes.
   Filename = std::string(Filename.begin()+1, Filename.end()-1);
   
-  // Diagnose #include "" as invalid.
-  if (Filename.empty())
-    return Diag(FilenameTok, diag::err_pp_empty_filename);
-  
   // Search include directories.
   const DirectoryLookup *CurDir;
   const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir);
@@ -1325,6 +1310,8 @@
   }
 }
 
+/// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know
+/// that the whole directive has been parsed.
 void Preprocessor::HandlePragmaSystemHeader(LexerToken &SysHeaderTok) {
   if (IncludeStack.empty()) {
     Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
@@ -1343,6 +1330,52 @@
                       SystemHeaderPragma, DirectoryLookup::SystemHeaderDir);
 }
 
+/// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
+///
+void Preprocessor::HandlePragmaDependency(LexerToken &DependencyTok) {
+  LexerToken FilenameTok;
+  std::string Filename = 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] == '<';
+  
+  // Remove the quotes.
+  Filename = std::string(Filename.begin()+1, Filename.end()-1);
+  
+  // Search include directories.
+  const DirectoryLookup *CurDir;
+  const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir);
+  if (File == 0)
+    return Diag(FilenameTok, diag::err_pp_file_not_found);
+  
+  Lexer *TheLexer = CurLexer;
+  if (TheLexer == 0) {
+    assert(!IncludeStack.empty() && "No current lexer?");
+    TheLexer = IncludeStack.back().TheLexer;
+  }
+  const FileEntry *CurFile =
+    SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
+
+  // If this file is older than the file it depends on, emit a diagnostic.
+  if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
+    // Lex tokens at the end of the message and include them in the message.
+    std::string Message;
+    Lex(DependencyTok);
+    while (DependencyTok.getKind() != tok::eom) {
+      Message += getSpelling(DependencyTok) + " ";
+      Lex(DependencyTok);
+    }
+    
+    Message.erase(Message.end()-1);
+    Diag(FilenameTok, diag::pp_out_of_date_dependency, Message);
+  }
+}
+
+
 /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
 /// If 'Namespace' is non-null, then it is a token required to exist on the
 /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
@@ -1398,6 +1431,12 @@
     PP.CheckEndOfDirective("#pragma");
   }
 };
+struct PragmaDependencyHandler : public PragmaHandler {
+  PragmaDependencyHandler(const IdentifierTokenInfo *ID) : PragmaHandler(ID) {}
+  virtual void HandlePragma(Preprocessor &PP, LexerToken &DepToken) {
+    PP.HandlePragmaDependency(DepToken);
+  }
+};
 }
 
 
@@ -1408,4 +1447,6 @@
   AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
   AddPragmaHandler("GCC", new PragmaSystemHeaderHandler(
                                           getIdentifierInfo("system_header")));
+  AddPragmaHandler("GCC", new PragmaDependencyHandler(
+                                          getIdentifierInfo("dependency")));
 }

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38574&r1=38573&r2=38574&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:22:50 2007
@@ -92,6 +92,8 @@
      "#pragma system_header ignored in main file")
 DIAG(pp_poisoning_existing_macro, WARNING,
      "poisoning existing macro")
+DIAG(pp_out_of_date_dependency, WARNING,
+     "current file is older than dependency %s")
 
 DIAG(ext_pp_import_directive, EXTENSION,
      "#import is a language extension")

Modified: cfe/cfe/trunk/include/clang/Basic/FileManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/FileManager.h?rev=38574&r1=38573&r2=38574&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/FileManager.h (original)
+++ cfe/cfe/trunk/include/clang/Basic/FileManager.h Wed Jul 11 11:22:50 2007
@@ -38,6 +38,7 @@
 class FileEntry {
   std::string Name;           // Name of the directory.
   off_t Size;                 // File size in bytes.
+  time_t ModTime;             // Modification time of file.
   const DirectoryEntry *Dir;  // Directory file lives in.
   unsigned UID;               // A unique (small) ID for the file.
   FileEntry() {}
@@ -47,6 +48,7 @@
   const std::string &getName() const { return Name; }
   off_t getSize() const { return Size; }
   unsigned getUID() const { return UID; }
+  time_t getModificationTime() const { return ModTime; }
   
   /// getDir - Return the directory the file lives in.
   ///

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=38574&r1=38573&r2=38574&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Lexer.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Lexer.h Wed Jul 11 11:22:50 2007
@@ -288,8 +288,9 @@
   
   /// 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.
-  void LexIncludeFilename(LexerToken &Result);
+  /// lexically legal, emit a diagnostic and return a result EOM token.  Return
+  /// the spelled and checked filename.
+  std::string 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=38574&r1=38573&r2=38574&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:22:50 2007
@@ -433,6 +433,7 @@
   void HandlePragmaOnce(LexerToken &OnceTok);
   void HandlePragmaPoison(LexerToken &PoisonTok);
   void HandlePragmaSystemHeader(LexerToken &SysHeaderTok);
+  void HandlePragmaDependency(LexerToken &DependencyTok);
 };
 
 }  // end namespace clang





More information about the cfe-commits mailing list