Branch data Line data Source code
1 : : /* Precompiled header implementation for the C languages.
2 : : Copyright (C) 2000-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify
7 : : it under the terms of the GNU General Public License as published by
8 : : the Free Software Foundation; either version 3, or (at your option)
9 : : any later version.
10 : :
11 : : GCC is distributed in the hope that it will be useful,
12 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : GNU General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "target.h"
24 : : #include "c-common.h"
25 : : #include "timevar.h"
26 : : #include "flags.h"
27 : : #include "debug.h"
28 : : #include "c-pragma.h"
29 : : #include "langhooks.h"
30 : : #include "hosthooks.h"
31 : :
32 : : /* This is a list of flag variables that must match exactly, and their
33 : : names for the error message. The possible values for *flag_var must
34 : : fit in a 'signed char'. */
35 : :
36 : : static const struct c_pch_matching
37 : : {
38 : : int *flag_var;
39 : : const char *flag_name;
40 : : } pch_matching[] = {
41 : : { &flag_exceptions, "-fexceptions" },
42 : : };
43 : :
44 : : enum {
45 : : MATCH_SIZE = ARRAY_SIZE (pch_matching)
46 : : };
47 : :
48 : : /* Information about flags and suchlike that affect PCH validity.
49 : :
50 : : Before this structure is read, both an initial 8-character identification
51 : : string, and a 16-byte checksum, have been read and validated. */
52 : :
53 : : struct c_pch_validity
54 : : {
55 : : uint32_t pch_write_symbols;
56 : : signed char match[MATCH_SIZE];
57 : : size_t target_data_length;
58 : : };
59 : :
60 : : #define IDENT_LENGTH 8
61 : :
62 : : /* The file we'll be writing the PCH to. */
63 : : static FILE *pch_outfile;
64 : :
65 : : static const char *get_ident (void);
66 : :
67 : : /* Compute an appropriate 8-byte magic number for the PCH file, so that
68 : : utilities like file(1) can identify it, and so that GCC can quickly
69 : : ignore non-PCH files and PCH files that are of a completely different
70 : : format. */
71 : :
72 : : static const char *
73 : 18948 : get_ident (void)
74 : : {
75 : 18948 : static char result[IDENT_LENGTH];
76 : 18948 : static const char templ[] = "gpch.014";
77 : 18948 : static const char c_language_chars[] = "Co+O";
78 : :
79 : 18948 : memcpy (result, templ, IDENT_LENGTH);
80 : 18948 : result[4] = c_language_chars[c_language];
81 : :
82 : 18948 : return result;
83 : : }
84 : :
85 : : /* Whether preprocessor state should be saved by pch_init. */
86 : :
87 : : static bool pch_ready_to_save_cpp_state = false;
88 : :
89 : : /* Prepare to write a PCH file, if one is being written. This is
90 : : called at the start of compilation. */
91 : :
92 : : void
93 : 200703 : pch_init (void)
94 : : {
95 : 200703 : FILE *f;
96 : 200703 : struct c_pch_validity v;
97 : 200703 : void *target_validity;
98 : 200703 : static const char partial_pch[] = "gpcWrite";
99 : :
100 : 200703 : if (!pch_file)
101 : 200236 : return;
102 : :
103 : 467 : f = fopen (pch_file, "w+b");
104 : 467 : if (f == NULL)
105 : 0 : fatal_error (input_location, "cannot create precompiled header %s: %m",
106 : : pch_file);
107 : 467 : pch_outfile = f;
108 : :
109 : 467 : memset (&v, '\0', sizeof (v));
110 : 467 : v.pch_write_symbols = write_symbols;
111 : 467 : {
112 : 467 : size_t i;
113 : 934 : for (i = 0; i < MATCH_SIZE; i++)
114 : : {
115 : 467 : v.match[i] = *pch_matching[i].flag_var;
116 : 467 : gcc_assert (v.match[i] == *pch_matching[i].flag_var);
117 : : }
118 : : }
119 : 467 : target_validity = targetm.get_pch_validity (&v.target_data_length);
120 : :
121 : 467 : if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
122 : 467 : || fwrite (executable_checksum, 16, 1, f) != 1
123 : 467 : || fwrite (&v, sizeof (v), 1, f) != 1
124 : 934 : || fwrite (target_validity, v.target_data_length, 1, f) != 1)
125 : 0 : fatal_error (input_location, "cannot write to %s: %m", pch_file);
126 : :
127 : : /* Let the debugging format deal with the PCHness. */
128 : 467 : (*debug_hooks->handle_pch) (0);
129 : :
130 : 467 : if (pch_ready_to_save_cpp_state)
131 : 0 : pch_cpp_save_state ();
132 : :
133 : 467 : XDELETE (target_validity);
134 : : }
135 : :
136 : : /* Whether preprocessor state has been saved in a PCH file. */
137 : :
138 : : static bool pch_cpp_state_saved = false;
139 : :
140 : : /* Save preprocessor state in a PCH file, after implicitly included
141 : : headers have been read. If the PCH file has not yet been opened,
142 : : record that state should be saved when it is opened. */
143 : :
144 : : void
145 : 736325 : pch_cpp_save_state (void)
146 : : {
147 : 736325 : if (!pch_cpp_state_saved)
148 : : {
149 : 734947 : if (pch_outfile)
150 : : {
151 : 467 : cpp_save_state (parse_in, pch_outfile);
152 : 467 : pch_cpp_state_saved = true;
153 : : }
154 : : else
155 : 734480 : pch_ready_to_save_cpp_state = true;
156 : : }
157 : 736325 : }
158 : :
159 : : /* Write the PCH file. This is called at the end of a compilation which
160 : : will produce a PCH file. */
161 : :
162 : : void
163 : 467 : c_common_write_pch (void)
164 : : {
165 : 467 : timevar_push (TV_PCH_SAVE);
166 : :
167 : 467 : targetm.prepare_pch_save ();
168 : :
169 : 467 : (*debug_hooks->handle_pch) (1);
170 : :
171 : 467 : prepare_target_option_nodes_for_pch ();
172 : :
173 : 467 : cpp_write_pch_deps (parse_in, pch_outfile);
174 : :
175 : 467 : gt_pch_save (pch_outfile);
176 : :
177 : 467 : timevar_push (TV_PCH_CPP_SAVE);
178 : 467 : cpp_write_pch_state (parse_in, pch_outfile);
179 : 467 : timevar_pop (TV_PCH_CPP_SAVE);
180 : :
181 : 467 : if (fseek (pch_outfile, 0, SEEK_SET) != 0
182 : 467 : || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
183 : 0 : fatal_error (input_location, "cannot write %s: %m", pch_file);
184 : :
185 : 467 : fclose (pch_outfile);
186 : :
187 : 467 : timevar_pop (TV_PCH_SAVE);
188 : 467 : }
189 : :
190 : : /* Check the PCH file called NAME, open on FD, to see if it can be
191 : : used in this compilation. Return 1 if valid, 0 if the file can't
192 : : be used now but might be if it's seen later in the compilation, and
193 : : 2 if this file could never be used in the compilation. */
194 : :
195 : : int
196 : 18481 : c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
197 : : {
198 : 18481 : int sizeread;
199 : 18481 : int result;
200 : 18481 : char ident[IDENT_LENGTH + 16];
201 : 18481 : const char *pch_ident;
202 : 18481 : struct c_pch_validity v;
203 : :
204 : : /* Perform a quick test of whether this is a valid
205 : : precompiled header for the current language. */
206 : :
207 : : /* C++ modules and PCH don't play together. */
208 : 18481 : if (flag_modules)
209 : : return 2;
210 : :
211 : 18481 : sizeread = read (fd, ident, IDENT_LENGTH + 16);
212 : 18481 : if (sizeread == -1)
213 : 0 : fatal_error (input_location, "cannot read %s: %m", name);
214 : 18481 : else if (sizeread != IDENT_LENGTH + 16)
215 : : {
216 : 0 : cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: too short to be a PCH file",
217 : : name);
218 : 0 : return 2;
219 : : }
220 : :
221 : 18481 : pch_ident = get_ident();
222 : 18481 : if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
223 : : {
224 : 0 : if (memcmp (ident, pch_ident, 5) == 0)
225 : : /* It's a PCH, for the right language, but has the wrong version. */
226 : 0 : cpp_warning (pfile, CPP_W_INVALID_PCH,
227 : : "%s: not compatible with this GCC version", name);
228 : 0 : else if (memcmp (ident, pch_ident, 4) == 0)
229 : : /* It's a PCH for the wrong language. */
230 : 0 : cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: not for %s", name,
231 : : lang_hooks.name);
232 : : else
233 : : /* Not any kind of PCH. */
234 : 0 : cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: not a PCH file", name);
235 : 0 : return 2;
236 : : }
237 : 18481 : if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0)
238 : : {
239 : 0 : cpp_warning (pfile, CPP_W_INVALID_PCH,
240 : : "%s: created by a different GCC executable", name);
241 : 0 : return 2;
242 : : }
243 : :
244 : : /* At this point, we know it's a PCH file created by this
245 : : executable, so it ought to be long enough that we can read a
246 : : c_pch_validity structure. */
247 : 18481 : if (read (fd, &v, sizeof (v)) != sizeof (v))
248 : 0 : fatal_error (input_location, "cannot read %s: %m", name);
249 : :
250 : : /* The allowable debug info combinations are that either the PCH file
251 : : was built with the same as is being used now, or the PCH file was
252 : : built for some kind of debug info but now none is in use. */
253 : 18481 : if (v.pch_write_symbols != write_symbols
254 : 12 : && write_symbols != NO_DEBUG)
255 : : {
256 : 6 : char *created_str = xstrdup (debug_set_names (v.pch_write_symbols));
257 : 6 : char *used_str = xstrdup (debug_set_names (write_symbols));
258 : 6 : cpp_warning (pfile, CPP_W_INVALID_PCH,
259 : : "%s: created with '%s' debug info, but used with '%s'", name,
260 : : created_str, used_str);
261 : 6 : free (created_str);
262 : 6 : free (used_str);
263 : 6 : return 2;
264 : : }
265 : :
266 : : /* Check flags that must match exactly. */
267 : : {
268 : : size_t i;
269 : 36939 : for (i = 0; i < MATCH_SIZE; i++)
270 : 18475 : if (*pch_matching[i].flag_var != v.match[i])
271 : : {
272 : 11 : cpp_warning (pfile, CPP_W_INVALID_PCH,
273 : : "%s: settings for %s do not match", name,
274 : : pch_matching[i].flag_name);
275 : 11 : return 2;
276 : : }
277 : : }
278 : :
279 : : /* Check the target-specific validity data. */
280 : 18464 : {
281 : 18464 : void *this_file_data = xmalloc (v.target_data_length);
282 : 18464 : const char *msg;
283 : :
284 : 18464 : if ((size_t) read (fd, this_file_data, v.target_data_length)
285 : 18464 : != v.target_data_length)
286 : 0 : fatal_error (input_location, "cannot read %s: %m", name);
287 : 18464 : msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
288 : 18464 : free (this_file_data);
289 : 18464 : if (msg != NULL)
290 : : {
291 : 18117 : cpp_warning (pfile, CPP_W_INVALID_PCH, "%s: %s", name, msg);
292 : 18117 : return 2;
293 : : }
294 : : }
295 : :
296 : : /* Check the preprocessor macros are the same as when the PCH was
297 : : generated. */
298 : :
299 : 347 : result = cpp_valid_state (pfile, name, fd);
300 : 347 : if (result == -1)
301 : : return 2;
302 : : else
303 : 347 : return result == 0;
304 : : }
305 : :
306 : : /* If non-NULL, this function is called after a precompile header file
307 : : is loaded. */
308 : : void (*lang_post_pch_load) (void);
309 : :
310 : : /* Load in the PCH file NAME, open on FD. It was originally searched for
311 : : by ORIG_NAME. */
312 : :
313 : : void
314 : 335 : c_common_read_pch (cpp_reader *pfile, const char *name,
315 : : int fd, const char *orig_name ATTRIBUTE_UNUSED)
316 : : {
317 : 335 : FILE *f;
318 : 335 : struct save_macro_data *smd;
319 : 335 : expanded_location saved_loc;
320 : 335 : bool saved_trace_includes;
321 : 335 : int cpp_result;
322 : :
323 : 335 : timevar_push (TV_PCH_RESTORE);
324 : :
325 : 335 : f = fdopen (fd, "rb");
326 : 335 : if (f == NULL)
327 : : {
328 : 0 : cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
329 : 0 : close (fd);
330 : 0 : goto end;
331 : : }
332 : :
333 : 335 : cpp_get_callbacks (parse_in)->valid_pch = NULL;
334 : :
335 : : /* Save the location and then restore it after reading the PCH. */
336 : 335 : saved_loc = expand_location (line_table->highest_line);
337 : 335 : saved_trace_includes = line_table->trace_includes;
338 : :
339 : 335 : timevar_push (TV_PCH_CPP_RESTORE);
340 : 335 : cpp_prepare_state (pfile, &smd);
341 : 335 : timevar_pop (TV_PCH_CPP_RESTORE);
342 : :
343 : 335 : gt_pch_restore (f);
344 : 335 : cpp_set_line_map (pfile, line_table);
345 : 335 : rebuild_location_adhoc_htab (line_table);
346 : 335 : line_table->trace_includes = saved_trace_includes;
347 : :
348 : : /* Set the current location to the line containing the #include (or the
349 : : #pragma GCC pch_preprocess) for the purpose of assigning locations to any
350 : : macros that are about to be restored. */
351 : 670 : linemap_add (line_table, LC_ENTER, 0, saved_loc.file,
352 : 335 : saved_loc.line > 1 ? saved_loc.line - 1 : saved_loc.line);
353 : :
354 : 335 : timevar_push (TV_PCH_CPP_RESTORE);
355 : 335 : cpp_result = cpp_read_state (pfile, name, f, smd);
356 : :
357 : : /* Set the current location to the line following the #include, where we
358 : : were prior to processing the PCH. */
359 : 335 : linemap_line_start (line_table, saved_loc.line, 0);
360 : :
361 : 335 : timevar_pop (TV_PCH_CPP_RESTORE);
362 : 335 : fclose (f);
363 : :
364 : 335 : if (cpp_result != 0)
365 : 0 : goto end;
366 : :
367 : : /* Give the front end a chance to take action after a PCH file has
368 : : been loaded. */
369 : 335 : if (lang_post_pch_load)
370 : 0 : (*lang_post_pch_load) ();
371 : :
372 : 335 : end:
373 : 335 : timevar_pop (TV_PCH_RESTORE);
374 : 335 : }
375 : :
376 : : /* Indicate that no more PCH files should be read. */
377 : :
378 : : void
379 : 201536 : c_common_no_more_pch (void)
380 : : {
381 : 201536 : if (cpp_get_callbacks (parse_in)->valid_pch)
382 : : {
383 : 200299 : cpp_get_callbacks (parse_in)->valid_pch = NULL;
384 : 200299 : void *addr = NULL;
385 : 200299 : host_hooks.gt_pch_use_address (addr, 0, -1, 0);
386 : : }
387 : 201536 : }
388 : :
389 : : /* Handle #pragma GCC pch_preprocess, to load in the PCH file. */
390 : :
391 : : void
392 : 18 : c_common_pch_pragma (cpp_reader *pfile, const char *name)
393 : : {
394 : 18 : int fd;
395 : :
396 : 18 : if (!cpp_get_options (pfile)->preprocessed)
397 : : {
398 : 0 : error ("%<pch_preprocess%> pragma should only be used "
399 : : "with %<-fpreprocessed%>");
400 : 0 : inform (input_location, "use %<#include%> instead");
401 : 0 : return;
402 : : }
403 : :
404 : 18 : fd = open (name, O_RDONLY | O_BINARY, 0666);
405 : 18 : if (fd == -1)
406 : 0 : fatal_error (input_location, "%s: couldn%'t open PCH file: %m", name);
407 : :
408 : 18 : if (c_common_valid_pch (pfile, name, fd) != 1)
409 : : {
410 : 0 : if (!cpp_get_options (pfile)->warn_invalid_pch)
411 : 0 : inform (input_location, "use %<-Winvalid-pch%> for more information");
412 : 0 : fatal_error (input_location, "%s: PCH file was invalid", name);
413 : : }
414 : :
415 : 18 : c_common_read_pch (pfile, name, fd, name);
416 : :
417 : 18 : close (fd);
418 : : }
419 : :
|