Commit | Line | Data |
---|---|---|
d71d6fe8 MB |
1 | Continuation of the SOURCE_DATE_EPOCH patch. |
2 | ||
3 | Patch adapted from upstream source repository: | |
4 | ||
5 | https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=dfa5c0d3f3e23e4fdb14857a42de376d9ff8601c | |
6 | ||
7 | From dfa5c0d3f3e23e4fdb14857a42de376d9ff8601c Mon Sep 17 00:00:00 2001 | |
8 | From: doko <doko@138bc75d-0d04-0410-961f-82ee72b054a4> | |
9 | Date: Wed, 1 Jun 2016 16:42:41 +0000 | |
10 | Subject: [PATCH] gcc/c-family/ChangeLog: | |
11 | ||
12 | diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c | |
13 | index 6f0898a38d7..efbc78ef218 100644 | |
14 | --- a/gcc/c-family/c-common.c | |
15 | +++ b/gcc/c-family/c-common.c | |
16 | @@ -12321,8 +12321,9 @@ pointer_to_zero_sized_aggr_p (tree t) | |
17 | /* Read SOURCE_DATE_EPOCH from environment to have a deterministic | |
18 | timestamp to replace embedded current dates to get reproducible | |
19 | results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */ | |
20 | + | |
21 | time_t | |
22 | -get_source_date_epoch () | |
23 | +cb_get_source_date_epoch (cpp_reader *pfile ATTRIBUTE_UNUSED) | |
24 | { | |
25 | char *source_date_epoch; | |
26 | long long epoch; | |
27 | @@ -12334,19 +12335,14 @@ get_source_date_epoch () | |
28 | ||
29 | errno = 0; | |
30 | epoch = strtoll (source_date_epoch, &endptr, 10); | |
31 | - if ((errno == ERANGE && (epoch == LLONG_MAX || epoch == LLONG_MIN)) | |
32 | - || (errno != 0 && epoch == 0)) | |
33 | - fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
34 | - "strtoll: %s\n", xstrerror(errno)); | |
35 | - if (endptr == source_date_epoch) | |
36 | - fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
37 | - "no digits were found: %s\n", endptr); | |
38 | - if (*endptr != '\0') | |
39 | - fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
40 | - "trailing garbage: %s\n", endptr); | |
41 | - if (epoch < 0) | |
42 | - fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
43 | - "value must be nonnegative: %lld \n", epoch); | |
44 | + if (errno != 0 || endptr == source_date_epoch || *endptr != '\0' | |
45 | + || epoch < 0 || epoch > MAX_SOURCE_DATE_EPOCH) | |
46 | + { | |
47 | + error_at (input_location, "environment variable SOURCE_DATE_EPOCH must " | |
48 | + "expand to a non-negative integer less than or equal to %wd", | |
49 | + MAX_SOURCE_DATE_EPOCH); | |
50 | + return (time_t) -1; | |
51 | + } | |
52 | ||
53 | return (time_t) epoch; | |
54 | } | |
55 | diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h | |
56 | index ba0a5d7df50..977ae9df5ea 100644 | |
57 | --- a/gcc/c-family/c-common.h | |
58 | +++ b/gcc/c-family/c-common.h | |
59 | @@ -1063,6 +1063,16 @@ extern vec<tree, va_gc> *make_tree_vector_copy (const vec<tree, va_gc> *); | |
60 | c_register_builtin_type. */ | |
61 | extern GTY(()) tree registered_builtin_types; | |
62 | ||
63 | +/* Read SOURCE_DATE_EPOCH from environment to have a deterministic | |
64 | + timestamp to replace embedded current dates to get reproducible | |
65 | + results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */ | |
66 | +extern time_t cb_get_source_date_epoch (cpp_reader *pfile); | |
67 | + | |
68 | +/* The value (as a unix timestamp) corresponds to date | |
69 | + "Dec 31 9999 23:59:59 UTC", which is the latest date that __DATE__ and | |
70 | + __TIME__ can store. */ | |
71 | +#define MAX_SOURCE_DATE_EPOCH HOST_WIDE_INT_C (253402300799) | |
72 | + | |
73 | /* In c-gimplify.c */ | |
74 | extern void c_genericize (tree); | |
75 | extern int c_gimplify_expr (tree *, gimple_seq *, gimple_seq *); | |
76 | @@ -1438,9 +1448,4 @@ extern tree cilk_for_number_of_iterations (tree); | |
77 | extern bool check_no_cilk (tree, const char *, const char *, | |
78 | location_t loc = UNKNOWN_LOCATION); | |
79 | ||
80 | -/* Read SOURCE_DATE_EPOCH from environment to have a deterministic | |
81 | - timestamp to replace embedded current dates to get reproducible | |
82 | - results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */ | |
83 | -extern time_t get_source_date_epoch (void); | |
84 | - | |
85 | #endif /* ! GCC_C_COMMON_H */ | |
86 | diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c | |
87 | index e68471b9d2b..3f78073f640 100644 | |
88 | --- a/gcc/c-family/c-lex.c | |
89 | +++ b/gcc/c-family/c-lex.c | |
90 | @@ -97,6 +97,7 @@ init_c_lex (void) | |
91 | cb->valid_pch = c_common_valid_pch; | |
92 | cb->read_pch = c_common_read_pch; | |
93 | cb->has_attribute = c_common_has_attribute; | |
94 | + cb->get_source_date_epoch = cb_get_source_date_epoch; | |
95 | ||
96 | /* Set the debug callbacks if we can use them. */ | |
97 | if ((debug_info_level == DINFO_LEVEL_VERBOSE | |
98 | @@ -402,9 +403,6 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags, | |
99 | enum cpp_ttype type; | |
100 | unsigned char add_flags = 0; | |
101 | enum overflow_type overflow = OT_NONE; | |
102 | - time_t source_date_epoch = get_source_date_epoch (); | |
103 | - | |
104 | - cpp_init_source_date_epoch (parse_in, source_date_epoch); | |
105 | ||
106 | timevar_push (TV_CPP); | |
107 | retry: | |
108 | diff --git a/gcc/doc/cppenv.texi b/gcc/doc/cppenv.texi | |
109 | index 3b5317beb53..7b4cf6adc11 100644 | |
110 | --- a/gcc/doc/cppenv.texi | |
111 | +++ b/gcc/doc/cppenv.texi | |
112 | @@ -81,7 +81,6 @@ main input file is omitted. | |
113 | @end ifclear | |
114 | ||
115 | @item SOURCE_DATE_EPOCH | |
116 | - | |
117 | If this variable is set, its value specifies a UNIX timestamp to be | |
118 | used in replacement of the current date and time in the @code{__DATE__} | |
119 | and @code{__TIME__} macros, so that the embedded timestamps become | |
120 | @@ -89,8 +88,9 @@ reproducible. | |
121 | ||
122 | The value of @env{SOURCE_DATE_EPOCH} must be a UNIX timestamp, | |
123 | defined as the number of seconds (excluding leap seconds) since | |
124 | -01 Jan 1970 00:00:00 represented in ASCII, identical to the output of | |
125 | -@samp{@command{date +%s}}. | |
126 | +01 Jan 1970 00:00:00 represented in ASCII; identical to the output of | |
127 | +@samp{@command{date +%s}} on GNU/Linux and other systems that support the | |
128 | +@code{%s} extension in the @code{date} command. | |
129 | ||
130 | The value should be a known timestamp such as the last modification | |
131 | time of the source or package and it should be set by the build | |
132 | diff --git a/gcc/gcc.c b/gcc/gcc.c | |
133 | index d956c36b151..2709f295734 100644 | |
134 | --- a/gcc/gcc.c | |
135 | +++ b/gcc/gcc.c | |
136 | @@ -3328,6 +3328,29 @@ save_switch (const char *opt, size_t n_args, const char *const *args, | |
137 | n_switches++; | |
138 | } | |
139 | ||
140 | +/* Set the SOURCE_DATE_EPOCH environment variable to the current time if it is | |
141 | + not set already. */ | |
142 | + | |
143 | +static void | |
144 | +set_source_date_epoch_envvar () | |
145 | +{ | |
146 | + /* Array size is 21 = ceil(log_10(2^64)) + 1 to hold string representations | |
147 | + of 64 bit integers. */ | |
148 | + char source_date_epoch[21]; | |
149 | + time_t tt; | |
150 | + | |
151 | + errno = 0; | |
152 | + tt = time (NULL); | |
153 | + if (tt < (time_t) 0 || errno != 0) | |
154 | + tt = (time_t) 0; | |
155 | + | |
156 | + snprintf (source_date_epoch, 21, "%llu", (unsigned long long) tt); | |
157 | + /* Using setenv instead of xputenv because we want the variable to remain | |
158 | + after finalizing so that it's still set in the second run when using | |
159 | + -fcompare-debug. */ | |
160 | + setenv ("SOURCE_DATE_EPOCH", source_date_epoch, 0); | |
161 | +} | |
162 | + | |
163 | /* Handle an option DECODED that is unknown to the option-processing | |
164 | machinery. */ | |
165 | ||
166 | @@ -3628,6 +3651,7 @@ driver_handle_option (struct gcc_options *opts, | |
167 | else | |
168 | compare_debug_opt = arg; | |
169 | save_switch (compare_debug_replacement_opt, 0, NULL, validated, true); | |
170 | + set_source_date_epoch_envvar (); | |
171 | return true; | |
172 | ||
173 | case OPT_fdiagnostics_color_: | |
174 | diff --git a/gcc/testsuite/gcc.dg/cpp/source_date_epoch-1.c b/gcc/testsuite/gcc.dg/cpp/source_date_epoch-1.c | |
175 | new file mode 100644 | |
176 | index 00000000000..f6aa1a360ff | |
177 | --- /dev/null | |
178 | +++ b/gcc/testsuite/gcc.dg/cpp/source_date_epoch-1.c | |
179 | @@ -0,0 +1,11 @@ | |
180 | +/* { dg-do run } */ | |
181 | +/* { dg-set-compiler-env-var SOURCE_DATE_EPOCH "630333296" } */ | |
182 | + | |
183 | +int | |
184 | +main(void) | |
185 | +{ | |
186 | + __builtin_printf ("%s %s\n", __DATE__, __TIME__); | |
187 | + return 0; | |
188 | +} | |
189 | + | |
190 | +/* { dg-output "^Dec 22 1989 12:34:56\n$" } */ | |
191 | diff --git a/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c b/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c | |
192 | new file mode 100644 | |
193 | index 00000000000..ae18362ae87 | |
194 | --- /dev/null | |
195 | +++ b/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c | |
196 | @@ -0,0 +1,12 @@ | |
197 | +/* { dg-do compile } */ | |
198 | +/* { dg-set-compiler-env-var SOURCE_DATE_EPOCH "AAA" } */ | |
199 | + | |
200 | +/* Make sure that SOURCE_DATE_EPOCH is only parsed once */ | |
201 | + | |
202 | +int | |
203 | +main(void) | |
204 | +{ | |
205 | + __builtin_printf ("%s %s\n", __DATE__, __TIME__); /* { dg-error "SOURCE_DATE_EPOCH must expand" } */ | |
206 | + __builtin_printf ("%s %s\n", __DATE__, __TIME__); | |
207 | + return 0; | |
208 | +} | |
209 | diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp | |
210 | index 4fa433d9954..7656b2254a1 100644 | |
211 | --- a/gcc/testsuite/lib/gcc-dg.exp | |
212 | +++ b/gcc/testsuite/lib/gcc-dg.exp | |
213 | @@ -324,6 +324,38 @@ proc restore-target-env-var { } { | |
214 | } | |
215 | } | |
216 | ||
217 | +proc dg-set-compiler-env-var { args } { | |
218 | + global set_compiler_env_var | |
219 | + global saved_compiler_env_var | |
220 | + if { [llength $args] != 3 } { | |
221 | + error "dg-set-compiler-env-var: need two arguments" | |
222 | + return | |
223 | + } | |
224 | + set var [lindex $args 1] | |
225 | + set value [lindex $args 2] | |
226 | + if [info exists ::env($var)] { | |
227 | + lappend saved_compiler_env_var [list $var 1 $::env($var)] | |
228 | + } else { | |
229 | + lappend saved_compiler_env_var [list $var 0] | |
230 | + } | |
231 | + setenv $var $value | |
232 | + lappend set_compiler_env_var [list $var $value] | |
233 | +} | |
234 | + | |
235 | +proc restore-compiler-env-var { } { | |
236 | + global saved_compiler_env_var | |
237 | + for { set env_vari [llength $saved_compiler_env_var] } { | |
238 | + [incr env_vari -1] >= 0 } {} { | |
239 | + set env_var [lindex $saved_compiler_env_var $env_vari] | |
240 | + set var [lindex $env_var 0] | |
241 | + if [lindex $env_var 1] { | |
242 | + setenv $var [lindex $env_var 2] | |
243 | + } else { | |
244 | + unsetenv $var | |
245 | + } | |
246 | + } | |
247 | +} | |
248 | + | |
249 | # Utility routines. | |
250 | ||
251 | # | |
252 | @@ -785,6 +817,11 @@ if { [info procs saved-dg-test] == [list] } { | |
253 | if [info exists set_target_env_var] { | |
254 | unset set_target_env_var | |
255 | } | |
256 | + if [info exists set_compiler_env_var] { | |
257 | + restore-compiler-env-var | |
258 | + unset set_compiler_env_var | |
259 | + unset saved_compiler_env_var | |
260 | + } | |
261 | unset_timeout_vars | |
262 | if [info exists compiler_conditional_xfail_data] { | |
263 | unset compiler_conditional_xfail_data | |
264 | diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h | |
265 | index 7a5481219be..867aeebc39f 100644 | |
266 | --- a/libcpp/include/cpplib.h | |
267 | +++ b/libcpp/include/cpplib.h | |
268 | @@ -585,6 +585,9 @@ struct cpp_callbacks | |
269 | ||
270 | /* Callback that can change a user builtin into normal macro. */ | |
271 | bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *); | |
272 | + | |
273 | + /* Callback to parse SOURCE_DATE_EPOCH from environment. */ | |
274 | + time_t (*get_source_date_epoch) (cpp_reader *); | |
275 | }; | |
276 | ||
277 | #ifdef VMS | |
278 | @@ -775,9 +778,6 @@ extern void cpp_init_special_builtins (cpp_reader *); | |
279 | /* Set up built-ins like __FILE__. */ | |
280 | extern void cpp_init_builtins (cpp_reader *, int); | |
281 | ||
282 | -/* Initialize the source_date_epoch value. */ | |
283 | -extern void cpp_init_source_date_epoch (cpp_reader *, time_t); | |
284 | - | |
285 | /* This is called after options have been parsed, and partially | |
286 | processed. */ | |
287 | extern void cpp_post_options (cpp_reader *); | |
288 | diff --git a/libcpp/init.c b/libcpp/init.c | |
289 | index a8d00f4628b..61c9bbbf945 100644 | |
290 | --- a/libcpp/init.c | |
291 | +++ b/libcpp/init.c | |
292 | @@ -254,6 +254,9 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, | |
293 | /* Do not force token locations by default. */ | |
294 | pfile->forced_token_location_p = NULL; | |
295 | ||
296 | + /* Initialize source_date_epoch to -2 (not yet set). */ | |
297 | + pfile->source_date_epoch = (time_t) -2; | |
298 | + | |
299 | /* The expression parser stack. */ | |
300 | _cpp_expand_op_stack (pfile); | |
301 | ||
302 | @@ -530,13 +533,6 @@ cpp_init_builtins (cpp_reader *pfile, int hosted) | |
303 | _cpp_define_builtin (pfile, "__OBJC__ 1"); | |
304 | } | |
305 | ||
306 | -/* Initialize the source_date_epoch value. */ | |
307 | -void | |
308 | -cpp_init_source_date_epoch (cpp_reader *pfile, time_t source_date_epoch) | |
309 | -{ | |
310 | - pfile->source_date_epoch = source_date_epoch; | |
311 | -} | |
312 | - | |
313 | /* Sanity-checks are dependent on command-line options, so it is | |
314 | called as a subroutine of cpp_read_main_file (). */ | |
315 | #if ENABLE_CHECKING | |
316 | diff --git a/libcpp/internal.h b/libcpp/internal.h | |
317 | index 8507eba1747..226ae328e76 100644 | |
318 | --- a/libcpp/internal.h | |
319 | +++ b/libcpp/internal.h | |
320 | @@ -503,7 +503,8 @@ struct cpp_reader | |
321 | const unsigned char *time; | |
322 | ||
323 | /* Externally set timestamp to replace current date and time useful for | |
324 | - reproducibility. */ | |
325 | + reproducibility. It should be initialized to -2 (not yet set) and | |
326 | + set to -1 to disable it or to a non-negative value to enable it. */ | |
327 | time_t source_date_epoch; | |
328 | ||
329 | /* EOF token, and a token forcing paste avoidance. */ | |
330 | diff --git a/libcpp/macro.c b/libcpp/macro.c | |
331 | index 3f3b278e97d..756c7c6e0c6 100644 | |
332 | --- a/libcpp/macro.c | |
333 | +++ b/libcpp/macro.c | |
334 | @@ -351,9 +351,13 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) | |
335 | struct tm *tb = NULL; | |
336 | ||
337 | /* Set a reproducible timestamp for __DATE__ and __TIME__ macro | |
338 | - usage if SOURCE_DATE_EPOCH is defined. */ | |
339 | - if (pfile->source_date_epoch != (time_t) -1) | |
340 | - tb = gmtime (&pfile->source_date_epoch); | |
341 | + if SOURCE_DATE_EPOCH is defined. */ | |
342 | + if (pfile->source_date_epoch == (time_t) -2 | |
343 | + && pfile->cb.get_source_date_epoch != NULL) | |
344 | + pfile->source_date_epoch = pfile->cb.get_source_date_epoch (pfile); | |
345 | + | |
346 | + if (pfile->source_date_epoch >= (time_t) 0) | |
347 | + tb = gmtime (&pfile->source_date_epoch); | |
348 | else | |
349 | { | |
350 | /* (time_t) -1 is a legitimate value for "number of seconds | |
351 | -- | |
352 | 2.11.0 | |
353 |