-
Notifications
You must be signed in to change notification settings - Fork 11k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang][preprocessor] Support __TIMESTAMP__ #98057
Conversation
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".
@llvm/pr-subscribers-flang-parser Author: Peter Klausler (klausler) ChangesSupport 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". Full diff: https://github.com/llvm/llvm-project/pull/98057.diff 4 Files Affected:
diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h
index 42c5b3de2cbe2..3189e012cd495 100644
--- a/flang/include/flang/Parser/provenance.h
+++ b/flang/include/flang/Parser/provenance.h
@@ -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;
diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp
index 8896980bf4bbf..7d3130cd66ed9 100644
--- a/flang/lib/Parser/preprocessor.cpp
+++ b/flang/lib/Parser/preprocessor.cpp
@@ -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>
@@ -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 ¯o, const std::string &value) {
@@ -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)};
diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp
index 6e2e7326e2167..c67ddd22f0968 100644
--- a/flang/lib/Parser/provenance.cpp
+++ b/flang/lib/Parser/provenance.cpp
@@ -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(
@@ -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;
}
diff --git a/flang/test/Preprocessing/timestamp.F90 b/flang/test/Preprocessing/timestamp.F90
new file mode 100644
index 0000000000000..b8f431c3022b8
--- /dev/null
+++ b/flang/test/Preprocessing/timestamp.F90
@@ -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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All builds and tests correctly and looks good.
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".
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".