Implement the __TIME__ and __DATE__ builtin macros.

llvm-svn: 38597
This commit is contained in:
Chris Lattner 2006-06-30 06:10:41 +00:00
parent 7d6a4f6746
commit c673f905d8
4 changed files with 52 additions and 33 deletions

View File

@ -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. /// Lex - Lex and return a token from this macro stream.
/// ///
void MacroExpander::Lex(LexerToken &Tok) { void MacroExpander::Lex(LexerToken &Tok) {
@ -56,9 +36,13 @@ void MacroExpander::Lex(LexerToken &Tok) {
// Get the next token to return. // Get the next token to return.
Tok = Macro.getReplacementToken(CurToken++); Tok = Macro.getReplacementToken(CurToken++);
// Update the tokens location to include both its logical and physical // The token's current location indicate where the token was lexed from. We
// locations. // need this information to compute the spelling of the token, but any
Tok.SetLocation(getInstantiationLoc(PP, Tok.getLocation(), InstantiateLoc)); // 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 // If this is the first token, set the lexical properties of the token to
// match the lexical properties of the macro identifier. // match the lexical properties of the macro identifier.

View File

@ -434,6 +434,8 @@ IdentifierTokenInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) {
void Preprocessor::RegisterBuiltinMacros() { void Preprocessor::RegisterBuiltinMacros() {
// FIXME: implement them all, including _Pragma. // FIXME: implement them all, including _Pragma.
Ident__LINE__ = RegisterBuiltinMacro("__LINE__"); 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 // Update the tokens location to include both its logical and physical
// locations. // locations.
SourceLocation Loc = SourceLocation Loc =
MacroExpander::getInstantiationLoc(*this, Identifier.getLocation(), SourceMgr.getInstantiationLoc(Identifier.getLocation(), InstantiateLoc);
InstantiateLoc);
Identifier.SetLocation(Loc); Identifier.SetLocation(Loc);
// Since this is not an identifier token, it can't be macro expanded, so // 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); 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 /// 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'. /// as a builtin macro, handle it and return the next token as 'Tok'.
void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) { 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!"); assert(ITI && "Can't be a macro without id info!");
char TmpBuffer[100]; char TmpBuffer[100];
if (ITI == Ident__LINE__) { if (ITI == Ident__LINE__) {
// __LINE__ expands to a simple numeric value. // __LINE__ expands to a simple numeric value.
sprintf(TmpBuffer, "%u", SourceMgr.getLineNumber(Tok.getLocation())); 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.SetLocation(ScratchBuf->getToken(TmpBuffer, Length, Tok.getLocation()));
Tok.SetIdentifierInfo(0); Tok.SetIdentifierInfo(0);
Tok.ClearFlag(LexerToken::NeedsCleaning); 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 { } else {
assert(0 && "Unknown identifier!"); assert(0 && "Unknown identifier!");
} }

View File

@ -50,13 +50,6 @@ public:
MacroInfo &getMacro() const { return Macro; } 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. /// Lex - Lex and return a token from this macro stream.
void Lex(LexerToken &Tok); void Lex(LexerToken &Tok);
}; };

View File

@ -94,6 +94,8 @@ class Preprocessor {
/// Identifiers for builtin macros. /// Identifiers for builtin macros.
IdentifierTokenInfo *Ident__LINE__; // __LINE__ IdentifierTokenInfo *Ident__LINE__; // __LINE__
IdentifierTokenInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
SourceLocation DATELoc, TIMELoc;
public: public:
enum FileChangeReason { enum FileChangeReason {
EnterFile, ExitFile, SystemHeaderPragma, RenameFile EnterFile, ExitFile, SystemHeaderPragma, RenameFile