diff options
| -rw-r--r-- | clang/Lex/Preprocessor.cpp | 35 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticKinds.def | 2 | ||||
| -rw-r--r-- | clang/include/clang/Lex/Preprocessor.h | 1 |
3 files changed, 36 insertions, 2 deletions
diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp index 83ae6f93b7f..9d868ec4456 100644 --- a/clang/Lex/Preprocessor.cpp +++ b/clang/Lex/Preprocessor.cpp @@ -31,7 +31,7 @@ // // TODO: Implement the include guard optimization. // -// Predefined Macros: _Pragma, __TIMESTAMP__, ... +// Predefined Macros: _Pragma, ... // //===----------------------------------------------------------------------===// @@ -441,7 +441,7 @@ void Preprocessor::RegisterBuiltinMacros() { // GCC Extensions. Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__"); Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__"); - // __TIMESTAMP__ + Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__"); // _Pragma //Pseudo #defines. @@ -613,6 +613,37 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) { Tok.SetKind(tok::numeric_constant); Tok.SetLength(Length); Tok.SetLocation(ScratchBuf->getToken(TmpBuffer, Length, Tok.getLocation())); + } else if (ITI == Ident__TIMESTAMP__) { + // MSVC, ICC, GCC, VisualAge C++ extension. The generated string should be + // of the form "Ddd Mmm dd hh::mm::ss yyyy", which is returned by asctime. + Diag(Tok, diag::ext_pp_timestamp); + + // Get the file that we are lexing out of. If we're currently lexing from + // a macro, dig into the include stack. + const FileEntry *CurFile = 0; + Lexer *TheLexer = CurLexer; + if (TheLexer == 0 && !IncludeStack.empty()) + TheLexer = IncludeStack.back().TheLexer; + + if (TheLexer) + CurFile = SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID()); + + // If this file is older than the file it depends on, emit a diagnostic. + const char *Result; + if (CurFile) { + time_t TT = CurFile->getModificationTime(); + struct tm *TM = localtime(&TT); + Result = asctime(TM); + } else { + Result = "??? ??? ?? ??:??:?? ????\n"; + } + TmpBuffer[0] = '"'; + strcpy(TmpBuffer+1, Result); + unsigned Len = strlen(TmpBuffer); + TmpBuffer[Len-1] = '"'; // Replace the newline with a quote. + Tok.SetKind(tok::string_literal); + Tok.SetLength(Len); + Tok.SetLocation(ScratchBuf->getToken(TmpBuffer, Len, Tok.getLocation())); } else { assert(0 && "Unknown identifier!"); } diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 470c0c27abe..9fe876915ad 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -114,6 +114,8 @@ DIAG(ext_pp_base_file, EXTENSION, "__BASE_FILE__ is a language extension") DIAG(ext_pp_include_level, EXTENSION, "__INCLUDE_LEVEL__ is a language extension") +DIAG(ext_pp_timestamp, EXTENSION, + "__TIMESTAMP__ is a language extension") DIAG(err_pp_invalid_directive, ERROR, "invalid preprocessing directive") diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 9cd6f6a406f..bd7e892c16c 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -97,6 +97,7 @@ class Preprocessor { IdentifierTokenInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__ IdentifierTokenInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__ IdentifierTokenInfo *Ident__BASE_FILE__; // __BASE_FILE__ + IdentifierTokenInfo *Ident__TIMESTAMP__; // __TIMESTAMP__ SourceLocation DATELoc, TIMELoc; public: |

