Skip to content

Commit

Permalink
[flang][preprocessor] Support __TIMESTAMP__ (llvm#98057)
Browse files Browse the repository at this point in the history
Support the predefined macro __TIMESTAMP__ as interpreted by GCC. It
expands to a character literal with the time of last modification of the
top-level source file in asctime(3) format, e.g. "Tue Jul 4 10:18:05
1776".
  • Loading branch information
klausler authored and aaryanshukla committed Jul 14, 2024
1 parent 1670aa5 commit 620294b
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 8 deletions.
4 changes: 2 additions & 2 deletions flang/include/flang/Parser/provenance.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ class AllSources {
const std::string &message, const std::string &prefix,
llvm::raw_ostream::Colors color, bool echoSourceLine = false) const;
const SourceFile *GetSourceFile(
Provenance, std::size_t *offset = nullptr) const;
Provenance, std::size_t *offset = nullptr, bool topLevel = false) const;
const char *GetSource(ProvenanceRange) const;
std::optional<SourcePosition> GetSourcePosition(Provenance) const;
std::optional<ProvenanceRange> GetFirstFileProvenance() const;
std::string GetPath(Provenance) const; // __FILE__
std::string GetPath(Provenance, bool topLevel = false) const; // __FILE__
int GetLineNumber(Provenance) const; // __LINE__
Provenance CompilerInsertionProvenance(char ch);
ProvenanceRange IntersectionWithSourceFiles(ProvenanceRange) const;
Expand Down
15 changes: 15 additions & 0 deletions flang/lib/Parser/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "flang/Common/idioms.h"
#include "flang/Parser/characters.h"
#include "flang/Parser/message.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cinttypes>
Expand Down Expand Up @@ -289,6 +290,7 @@ void Preprocessor::DefineStandardMacros() {
// The values of these predefined macros depend on their invocation sites.
Define("__FILE__"s, "__FILE__"s);
Define("__LINE__"s, "__LINE__"s);
Define("__TIMESTAMP__"s, "__TIMESTAMP__"s);
}

void Preprocessor::Define(const std::string &macro, const std::string &value) {
Expand Down Expand Up @@ -377,6 +379,19 @@ std::optional<TokenSequence> Preprocessor::MacroReplacement(
llvm::raw_string_ostream ss{buf};
ss << allSources_.GetLineNumber(prescanner.GetCurrentProvenance());
repl = ss.str();
} else if (name == "__TIMESTAMP__") {
auto path{allSources_.GetPath(
prescanner.GetCurrentProvenance(), /*topLevel=*/true)};
llvm::sys::fs::file_status status;
repl = "??? ??? ?? ??:??:?? ????";
if (!llvm::sys::fs::status(path, status)) {
auto modTime{llvm::sys::toTimeT(status.getLastModificationTime())};
if (std::string time{std::asctime(std::localtime(&modTime))};
time.size() > 1 && time[time.size() - 1] == '\n') {
time.erase(time.size() - 1); // clip terminal '\n'
repl = "\""s + time + '"';
}
}
}
if (!repl.empty()) {
ProvenanceRange insert{allSources_.AddCompilerInsertion(repl)};
Expand Down
17 changes: 11 additions & 6 deletions flang/lib/Parser/provenance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,19 @@ void AllSources::EmitMessage(llvm::raw_ostream &o,
}

const SourceFile *AllSources::GetSourceFile(
Provenance at, std::size_t *offset) const {
Provenance at, std::size_t *offset, bool topLevel) const {
const Origin &origin{MapToOrigin(at)};
return common::visit(common::visitors{
[&](const Inclusion &inc) {
if (offset) {
*offset = origin.covers.MemberOffset(at);
if (topLevel && !origin.replaces.empty()) {
return GetSourceFile(
origin.replaces.start(), offset, topLevel);
} else {
if (offset) {
*offset = origin.covers.MemberOffset(at);
}
return &inc.source;
}
return &inc.source;
},
[&](const Macro &) {
return GetSourceFile(
Expand Down Expand Up @@ -380,9 +385,9 @@ std::optional<ProvenanceRange> AllSources::GetFirstFileProvenance() const {
return std::nullopt;
}

std::string AllSources::GetPath(Provenance at) const {
std::string AllSources::GetPath(Provenance at, bool topLevel) const {
std::size_t offset{0};
const SourceFile *source{GetSourceFile(at, &offset)};
const SourceFile *source{GetSourceFile(at, &offset, topLevel)};
return source ? *source->GetSourcePosition(offset).path : ""s;
}

Expand Down
12 changes: 12 additions & 0 deletions flang/test/Preprocessing/timestamp.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
!RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
!CHECK: INTEGER, PARAMETER :: tslen = 24_4
!CHECK: LOGICAL, PARAMETER :: tsspaces = .true._4
!CHECK: LOGICAL, PARAMETER :: tscolons = .true._4

integer, parameter :: tsLen = len(__TIMESTAMP__)
character(tsLen), parameter :: ts = __TIMESTAMP__
integer, parameter :: spaces(*) = [4, 8, 11, 20]
integer, parameter :: colons(*) = [14, 17]
logical, parameter :: tsSpaces = all([character(1)::(ts(spaces(j):spaces(j)),j=1,size(spaces))] == ' ')
logical, parameter :: tsColons = all([character(1)::(ts(colons(j):colons(j)),j=1,size(colons))] == ':')
end

0 comments on commit 620294b

Please sign in to comment.