Skip to content
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

Merged
merged 1 commit into from
Jul 11, 2024
Merged

Conversation

klausler
Copy link
Contributor

@klausler klausler commented Jul 8, 2024

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".
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:parser labels Jul 8, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jul 8, 2024

@llvm/pr-subscribers-flang-parser

Author: Peter Klausler (klausler)

Changes

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".


Full diff: https://github.com/llvm/llvm-project/pull/98057.diff

4 Files Affected:

  • (modified) flang/include/flang/Parser/provenance.h (+2-2)
  • (modified) flang/lib/Parser/preprocessor.cpp (+15)
  • (modified) flang/lib/Parser/provenance.cpp (+11-6)
  • (added) flang/test/Preprocessing/timestamp.F90 (+12)
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 &macro, 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

@psteinfeld psteinfeld assigned klausler and unassigned psteinfeld Jul 8, 2024
@psteinfeld psteinfeld self-requested a review July 8, 2024 18:02
Copy link
Contributor

@psteinfeld psteinfeld left a 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.

@klausler klausler merged commit 5024a6e into llvm:main Jul 11, 2024
10 checks passed
@klausler klausler deleted the bug1677 branch July 11, 2024 19:53
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
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".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:parser flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants