Bug#823937: gcc -E has __DATE__/__TIME__ as Jan 1 1970 00:00:00

2017-05-12 Thread James Clarke
On Tue, May 10, 2016 at 04:32:58PM +0100, James Clarke wrote:
> Package: gcc-5
> Version: 5.3.1-17
> Severity: normal
> Tags: upstream patch
> Control: clone -1 -2
> Control: reassign -2 gcc-6 6.1.1-1
>
> Hi,
> With the SOURCE_DATE_EPOCH patch from upstream, the __DATE__ and
> __TIME__ macros always give Jan 1 1970 00:00:00 when running the
> preprocessor on its own with gcc -E[1]. I believe this is because
> c_lex_with_flags is not called when just preprocessing (no C code needs
> to be lexed), so pfile->source_date_epoch stays initialised to 0, and
> subsequent __DATE__/__TIME__ expansions believe that the timestamp has
> been set to epoch 0. I have attached an alternative implementation of
> gcc-SOURCE_DATE_EPOCH.diff which fixes this, by initialising
> pfile->source_date_epoch inside libcpp when pfile is initially created.
>
> [1] https://paste.debian.net/683081/

Hi,
I notice 5.4.0-1 included a backport of r237001 to fix this, but the
upstream commit introduced a regression fixed in r237408 which *wasn't*
backported to this. Could you please bundle that into the next upload? I
guess it's not especially important now gcc-5 is out of testing, but it
would still be nice to have this fixed.

(The regression introduced is that SOURCE_DATE_EPOCH isn't used when
rnning just the preprocessor [previously it would always act as if it
was 0, but now it always uses the current time] so if you do:

echo __DATE__ | SOURCE_DATE_EPOCH=86400 gcc-5 -E -

you get the current date, not "Jan  2 1970").

Regards,
James



Bug#823937: gcc -E has __DATE__/__TIME__ as Jan 1 1970 00:00:00

2016-05-10 Thread James Clarke
Package: gcc-5
Version: 5.3.1-17
Severity: normal
Tags: upstream patch
Control: clone -1 -2
Control: reassign -2 gcc-6 6.1.1-1

Hi,
With the SOURCE_DATE_EPOCH patch from upstream, the __DATE__ and
__TIME__ macros always give Jan 1 1970 00:00:00 when running the
preprocessor on its own with gcc -E[1]. I believe this is because
c_lex_with_flags is not called when just preprocessing (no C code needs
to be lexed), so pfile->source_date_epoch stays initialised to 0, and
subsequent __DATE__/__TIME__ expansions believe that the timestamp has
been set to epoch 0. I have attached an alternative implementation of
gcc-SOURCE_DATE_EPOCH.diff which fixes this, by initialising
pfile->source_date_epoch inside libcpp when pfile is initially created.

[1] https://paste.debian.net/683081/

-- System Information:
Debian Release: stretch/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'unstable'), (1, 
'experimental-debug'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 4.5.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages gcc-5 depends on:
ii  binutils  2.26-8
ii  cpp-5 5.3.1-17
ii  gcc-5-base5.3.1-17
ii  libc6 2.22-7
ii  libcc1-0  6.1.1-1
ii  libgcc-5-dev  5.3.1-17
ii  libgcc1   1:6.1.1-1
ii  libgmp10  2:6.1.0+dfsg-2
ii  libisl15  0.16.1-1
ii  libmpc3   1.0.3-1
ii  libmpfr4  3.1.4-1
ii  libstdc++66.1.1-1
ii  zlib1g1:1.2.8.dfsg-2+b1

Versions of packages gcc-5 recommends:
ii  libc6-dev  2.22-7

Versions of packages gcc-5 suggests:
pn  gcc-5-doc 
pn  gcc-5-locales 
pn  gcc-5-multilib
pn  libasan2-dbg  
pn  libatomic1-dbg
pn  libcilkrts5-dbg   
pn  libgcc1-dbg   
pn  libgomp1-dbg  
pn  libitm1-dbg   
pn  liblsan0-dbg  
pn  libmpx0-dbg   
pn  libquadmath0-dbg  
pn  libtsan0-dbg  
pn  libubsan0-dbg 

-- no debconf information
--- a/src/libcpp/init.c
+++ b/src/libcpp/init.c
@@ -36,6 +36,7 @@
 
 static void init_library (void);
 static void mark_named_operators (cpp_reader *, int);
+static void cpp_init_source_date_epoch (cpp_reader *);
 static void read_original_filename (cpp_reader *);
 static void read_original_directory (cpp_reader *);
 static void post_options (cpp_reader *);
@@ -264,6 +265,9 @@
 
   _cpp_init_hashtable (pfile, table);
 
+  /* Initialize the source_date_epoch value.  */
+  cpp_init_source_date_epoch (pfile);
+
   return pfile;
 }
 
@@ -530,6 +534,46 @@
 _cpp_define_builtin (pfile, "__OBJC__ 1");
 }
 
+/* Read SOURCE_DATE_EPOCH from environment to have a deterministic
+   timestamp to replace embedded current dates to get reproducible
+   results.  Returns -1 if SOURCE_DATE_EPOCH is not defined.  */
+static time_t
+get_source_date_epoch (cpp_reader *pfile)
+{
+  char *source_date_epoch;
+  long long epoch;
+  char *endptr;
+
+  source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
+  if (!source_date_epoch)
+return (time_t) -1;
+
+  errno = 0;
+  epoch = strtoll (source_date_epoch, , 10);
+  if ((errno == ERANGE && (epoch == LLONG_MAX || epoch == LLONG_MIN))
+  || (errno != 0 && epoch == 0))
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+		 "strtoll: %s\n", xstrerror(errno));
+  if (endptr == source_date_epoch)
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+		 "no digits were found: %s\n", endptr);
+  if (*endptr != '\0')
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+		 "trailing garbage: %s\n", endptr);
+  if (epoch < 0)
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+		 "value must be nonnegative: %lld \n", epoch);
+
+  return (time_t) epoch;
+}
+
+/* Initialize the source_date_epoch value.  */
+static void
+cpp_init_source_date_epoch (cpp_reader *pfile)
+{
+  pfile->source_date_epoch = get_source_date_epoch (pfile);
+}
+
 /* Sanity-checks are dependent on command-line options, so it is
called as a subroutine of cpp_read_main_file ().  */
 #if ENABLE_CHECKING
--- a/src/libcpp/internal.h
+++ b/src/libcpp/internal.h
@@ -502,6 +502,10 @@
   const unsigned char *date;
   const unsigned char *time;
 
+  /* Externally set timestamp to replace current date and time useful for
+ reproducibility.  */
+  time_t source_date_epoch;
+
   /* EOF token, and a token forcing paste avoidance.  */
   cpp_token avoid_paste;
   cpp_token eof;
--- a/src/libcpp/macro.c
+++ b/src/libcpp/macro.c
@@ -350,13 +350,20 @@
 	  time_t tt;
 	  struct tm *tb = NULL;
 
-	  /* (time_t) -1 is a legitimate value for "number of seconds
-	 since the Epoch", so we have to do a little dance to
-	 distinguish that from a genuine error.  */
-	  errno = 0;
-	  tt = time(NULL);
-	  if (tt != (time_t)-1 || errno == 0)
-	tb = localtime ();
+	  /* Set a reproducible timestamp for __DATE__ and