[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