diff --git a/clang/Lex/MacroExpander.cpp b/clang/Lex/MacroExpander.cpp index a6d60c3f8f84..e98125dde460 100644 --- a/clang/Lex/MacroExpander.cpp +++ b/clang/Lex/MacroExpander.cpp @@ -26,26 +26,6 @@ MacroExpander::MacroExpander(LexerToken &Tok, Preprocessor &pp) } -/// getInstantiationLoc - Return a SourceLocation that specifies a macro -/// instantiation whose physical location is PhysLoc but the logical location -/// is InstantiationLoc. -SourceLocation MacroExpander:: -getInstantiationLoc(Preprocessor &PP, - SourceLocation PhysLoc, SourceLocation InstantiationLoc) { - // The token's current location indicate where the token was lexed from. We - // need this information to compute the spelling of the token, but any - // diagnostics for the expanded token should appear as if they came from - // InstantiationLoc. Pull this information together into a new SourceLocation - // that captures all of this. - unsigned CharFilePos = PhysLoc.getRawFilePos(); - unsigned CharFileID = PhysLoc.getFileID(); - - unsigned InstantiationFileID = - PP.getSourceManager().createFileIDForMacroExp(InstantiationLoc, CharFileID); - return SourceLocation(InstantiationFileID, CharFilePos); -} - - /// Lex - Lex and return a token from this macro stream. /// void MacroExpander::Lex(LexerToken &Tok) { @@ -56,9 +36,13 @@ void MacroExpander::Lex(LexerToken &Tok) { // Get the next token to return. Tok = Macro.getReplacementToken(CurToken++); - // Update the tokens location to include both its logical and physical - // locations. - Tok.SetLocation(getInstantiationLoc(PP, Tok.getLocation(), InstantiateLoc)); + // The token's current location indicate where the token was lexed from. We + // need this information to compute the spelling of the token, but any + // diagnostics for the expanded token should appear as if they came from + // InstantiationLoc. Pull this information together into a new SourceLocation + // that captures all of this. + Tok.SetLocation(PP.getSourceManager().getInstantiationLoc(Tok.getLocation(), + InstantiateLoc)); // If this is the first token, set the lexical properties of the token to // match the lexical properties of the macro identifier. diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp index e68fbcbfda60..807b151a2855 100644 --- a/clang/Lex/Preprocessor.cpp +++ b/clang/Lex/Preprocessor.cpp @@ -434,6 +434,8 @@ IdentifierTokenInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) { void Preprocessor::RegisterBuiltinMacros() { // FIXME: implement them all, including _Pragma. Ident__LINE__ = RegisterBuiltinMacro("__LINE__"); + Ident__DATE__ = RegisterBuiltinMacro("__DATE__"); + Ident__TIME__ = RegisterBuiltinMacro("__TIME__"); } @@ -498,8 +500,7 @@ void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier, // Update the tokens location to include both its logical and physical // locations. SourceLocation Loc = - MacroExpander::getInstantiationLoc(*this, Identifier.getLocation(), - InstantiateLoc); + SourceMgr.getInstantiationLoc(Identifier.getLocation(), InstantiateLoc); Identifier.SetLocation(Loc); // Since this is not an identifier token, it can't be macro expanded, so @@ -516,6 +517,27 @@ void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier, return Lex(Identifier); } +/// ComputeDATE_TIME - Compute the current time, enter it into the specified +/// scratch buffer, then return DATELoc/TIMELoc locations with the position of +/// the identifier tokens inserted. +static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, + ScratchBuffer *ScratchBuf) { + time_t TT = time(0); + struct tm *TM = localtime(&TT); + + static const char * const Months[] = { + "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" + }; + + char TmpBuffer[100]; + sprintf(TmpBuffer, "\"%s %2d %4d\"", Months[TM->tm_mon], TM->tm_mday, + TM->tm_year+1900); + DATELoc = ScratchBuf->getToken(TmpBuffer, strlen(TmpBuffer)); + + sprintf(TmpBuffer, "\"%02d:%02d:%02d\"", TM->tm_hour, TM->tm_min, TM->tm_sec); + TIMELoc = ScratchBuf->getToken(TmpBuffer, strlen(TmpBuffer)); +} + /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) { @@ -524,6 +546,7 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) { assert(ITI && "Can't be a macro without id info!"); char TmpBuffer[100]; + if (ITI == Ident__LINE__) { // __LINE__ expands to a simple numeric value. sprintf(TmpBuffer, "%u", SourceMgr.getLineNumber(Tok.getLocation())); @@ -533,7 +556,24 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) { Tok.SetLocation(ScratchBuf->getToken(TmpBuffer, Length, Tok.getLocation())); Tok.SetIdentifierInfo(0); Tok.ClearFlag(LexerToken::NeedsCleaning); - return; + } else if (ITI == Ident__DATE__) { + if (!DATELoc.isValid()) + ComputeDATE_TIME(DATELoc, TIMELoc, ScratchBuf); + Tok.SetKind(tok::string_literal); + Tok.SetLength(strlen("\"Mmm dd yyyy\"")); + Tok.SetLocation(SourceMgr.getInstantiationLoc(DATELoc, Tok.getLocation())); + Tok.SetIdentifierInfo(0); + Tok.ClearFlag(LexerToken::NeedsCleaning); + + } else if (ITI == Ident__TIME__) { + if (!TIMELoc.isValid()) + ComputeDATE_TIME(DATELoc, TIMELoc, ScratchBuf); + Tok.SetKind(tok::string_literal); + Tok.SetLength(strlen("\"hh:mm:ss\"")); + Tok.SetLocation(SourceMgr.getInstantiationLoc(TIMELoc, Tok.getLocation())); + Tok.SetIdentifierInfo(0); + Tok.ClearFlag(LexerToken::NeedsCleaning); + } else { assert(0 && "Unknown identifier!"); } diff --git a/clang/include/clang/Lex/MacroExpander.h b/clang/include/clang/Lex/MacroExpander.h index 60ec8cb39f2e..497f53407a19 100644 --- a/clang/include/clang/Lex/MacroExpander.h +++ b/clang/include/clang/Lex/MacroExpander.h @@ -50,13 +50,6 @@ public: MacroInfo &getMacro() const { return Macro; } - /// getInstantiationLoc - Return a SourceLocation that specifies a macro - /// instantiation whose physical location is PhysLoc but the logical location - /// is InstantiationLoc. - static SourceLocation getInstantiationLoc(Preprocessor &PP, - SourceLocation PhysLoc, - SourceLocation InstantiationLoc); - /// Lex - Lex and return a token from this macro stream. void Lex(LexerToken &Tok); }; diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index c65b8287fd61..81f3bc6ecb5b 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -94,6 +94,8 @@ class Preprocessor { /// Identifiers for builtin macros. IdentifierTokenInfo *Ident__LINE__; // __LINE__ + IdentifierTokenInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__ + SourceLocation DATELoc, TIMELoc; public: enum FileChangeReason { EnterFile, ExitFile, SystemHeaderPragma, RenameFile