aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-11-06 08:53:31 -0800
committerNathan Sidwell <nathan@acm.org>2020-11-06 08:59:20 -0800
commit4b5f564a5d958295d51a1a7ff825896a89f22b75 (patch)
tree89b054bb02f70619eacc29089f28e45e102c1a27 /libcpp
parent6c3ce63b04b38f84c0357e4648383f0e3ab11cd9 (diff)
downloadgcc-4b5f564a5d958295d51a1a7ff825896a89f22b75.zip
gcc-4b5f564a5d958295d51a1a7ff825896a89f22b75.tar.gz
gcc-4b5f564a5d958295d51a1a7ff825896a89f22b75.tar.bz2
libcpp: Provide date routine
Joseph pointed me at cb_get_source_date_epoch, which allows repeatable builds and solves a FIXME I had on the modules branch. Unfortunately it's used exclusively to generate __DATE__ and __TIME__ values, which fallback to using a time(2) call. It'd be nicer if the preprocessor made whatever time value it determined available to the rest of the compiler. So this patch adds a new cpp_get_date function, which abstracts the call to the get_source_date_epoch hook, or uses time directly. The value is cached. Thus the timestamp I end up putting on CMI files matches __DATE__ and __TIME__ expansions. That seems worthwhile. libcpp/ * include/cpplib.h (enum class CPP_time_kind): New. (cpp_get_date): Declare. * internal.h (struct cpp_reader): Replace source_date_epoch with time_stamp and time_stamp_kind. * init.c (cpp_create_reader): Initialize them. * macro.c (_cpp_builtin_macro_text): Use cpp_get_date. (cpp_get_date): Broken out from _cpp_builtin_macro_text and genericized.
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/include/cpplib.h9
-rw-r--r--libcpp/init.c5
-rw-r--r--libcpp/internal.h7
-rw-r--r--libcpp/macro.c83
4 files changed, 71 insertions, 33 deletions
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 8e39886..c4d7cc5 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -1040,6 +1040,15 @@ inline location_t cpp_macro_definition_location (cpp_hashnode *node)
{
return node->value.macro->line;
}
+/* Return an idempotent time stamp (possibly from SOURCE_DATE_EPOCH). */
+enum class CPP_time_kind
+{
+ FIXED = -1, /* Fixed time via source epoch. */
+ DYNAMIC = -2, /* Dynamic via time(2). */
+ UNKNOWN = -3 /* Wibbly wobbly, timey wimey. */
+};
+extern CPP_time_kind cpp_get_date (cpp_reader *, time_t *);
+
extern void _cpp_backup_tokens (cpp_reader *, unsigned int);
extern const cpp_token *cpp_peek_token (cpp_reader *, int);
diff --git a/libcpp/init.c b/libcpp/init.c
index 6c52f50..dcf1d4b 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -273,8 +273,9 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
/* Do not force token locations by default. */
pfile->forced_token_location = 0;
- /* Initialize source_date_epoch to -2 (not yet set). */
- pfile->source_date_epoch = (time_t) -2;
+ /* Note the timestamp is unset. */
+ pfile->time_stamp = time_t (-1);
+ pfile->time_stamp_kind = 0;
/* The expression parser stack. */
_cpp_expand_op_stack (pfile);
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 4759961..d7780e4 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -512,10 +512,9 @@ struct cpp_reader
const unsigned char *date;
const unsigned char *time;
- /* Externally set timestamp to replace current date and time useful for
- reproducibility. It should be initialized to -2 (not yet set) and
- set to -1 to disable it or to a non-negative value to enable it. */
- time_t source_date_epoch;
+ /* Time stamp, set idempotently lazily. */
+ time_t time_stamp;
+ int time_stamp_kind; /* Or errno. */
/* A token forcing paste avoidance, and one demarking macro arguments. */
cpp_token avoid_paste;
diff --git a/libcpp/macro.c b/libcpp/macro.c
index e304f67..e2cb89e 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -606,29 +606,21 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
at init time, because time() and localtime() are very
slow on some systems. */
time_t tt;
- struct tm *tb = NULL;
+ auto kind = cpp_get_date (pfile, &tt);
- /* Set a reproducible timestamp for __DATE__ and __TIME__ macro
- if SOURCE_DATE_EPOCH is defined. */
- if (pfile->source_date_epoch == (time_t) -2
- && pfile->cb.get_source_date_epoch != NULL)
- pfile->source_date_epoch = pfile->cb.get_source_date_epoch (pfile);
-
- if (pfile->source_date_epoch >= (time_t) 0)
- tb = gmtime (&pfile->source_date_epoch);
- else
+ if (kind == CPP_time_kind::UNKNOWN)
{
- /* (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 (&tt);
+ cpp_errno (pfile, CPP_DL_WARNING,
+ "could not determine date and time");
+
+ pfile->date = UC"\"??? ?? ????\"";
+ pfile->time = UC"\"??:??:??\"";
}
-
- if (tb)
+ else
{
+ struct tm *tb = (kind == CPP_time_kind::FIXED
+ ? gmtime : localtime) (&tt);
+
pfile->date = _cpp_unaligned_alloc (pfile,
sizeof ("\"Oct 11 1347\""));
sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
@@ -640,14 +632,6 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
tb->tm_hour, tb->tm_min, tb->tm_sec);
}
- else
- {
- cpp_errno (pfile, CPP_DL_WARNING,
- "could not determine date and time");
-
- pfile->date = UC"\"??? ?? ????\"";
- pfile->time = UC"\"??:??:??\"";
- }
}
if (node->value.builtin == BT_DATE)
@@ -688,6 +672,51 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
return result;
}
+/* Get an idempotent date. Either the cached value, the value from
+ source epoch, or failing that, the value from time(2). Use this
+ during compilation so that every time stamp is the same. */
+CPP_time_kind
+cpp_get_date (cpp_reader *pfile, time_t *result)
+{
+ if (!pfile->time_stamp_kind)
+ {
+ int kind = 0;
+ if (pfile->cb.get_source_date_epoch)
+ {
+ /* Try reading the fixed epoch. */
+ pfile->time_stamp = pfile->cb.get_source_date_epoch (pfile);
+ if (pfile->time_stamp != time_t (-1))
+ kind = int (CPP_time_kind::FIXED);
+ }
+
+ if (!kind)
+ {
+ /* Pedantically time_t (-1) is a legitimate value for
+ "number of seconds since the Epoch". It is a silly
+ time. */
+ errno = 0;
+ pfile->time_stamp = time (nullptr);
+ /* Annoyingly a library could legally set errno and return a
+ valid time! Bad library! */
+ if (pfile->time_stamp == time_t (-1) && errno)
+ kind = errno;
+ else
+ kind = int (CPP_time_kind::DYNAMIC);
+ }
+
+ pfile->time_stamp_kind = kind;
+ }
+
+ *result = pfile->time_stamp;
+ if (pfile->time_stamp_kind >= 0)
+ {
+ errno = pfile->time_stamp_kind;
+ return CPP_time_kind::UNKNOWN;
+ }
+
+ return CPP_time_kind (pfile->time_stamp_kind);
+}
+
/* Convert builtin macros like __FILE__ to a token and push it on the
context stack. Also handles _Pragma, for which a new token may not
be created. Returns 1 if it generates a new token context, 0 to