1/* Precompiled header implementation for the C languages.
2 Copyright (C) 2000-2024 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along 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
36static const struct c_pch_matching
37{
38 int *flag_var;
39 const char *flag_name;
40} pch_matching[] = {
41 { .flag_var: &flag_exceptions, .flag_name: "-fexceptions" },
42};
43
44enum {
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
53struct 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. */
63static FILE *pch_outfile;
64
65static 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
72static const char *
73get_ident (void)
74{
75 static char result[IDENT_LENGTH];
76 static const char templ[] = "gpch.014";
77 static const char c_language_chars[] = "Co+O";
78
79 memcpy (dest: result, src: templ, IDENT_LENGTH);
80 result[4] = c_language_chars[c_language];
81
82 return result;
83}
84
85/* Whether preprocessor state should be saved by pch_init. */
86
87static 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
92void
93pch_init (void)
94{
95 FILE *f;
96 struct c_pch_validity v;
97 void *target_validity;
98 static const char partial_pch[] = "gpcWrite";
99
100 if (!pch_file)
101 return;
102
103 f = fopen (filename: pch_file, modes: "w+b");
104 if (f == NULL)
105 fatal_error (input_location, "cannot create precompiled header %s: %m",
106 pch_file);
107 pch_outfile = f;
108
109 memset (s: &v, c: '\0', n: sizeof (v));
110 v.pch_write_symbols = write_symbols;
111 {
112 size_t i;
113 for (i = 0; i < MATCH_SIZE; i++)
114 {
115 v.match[i] = *pch_matching[i].flag_var;
116 gcc_assert (v.match[i] == *pch_matching[i].flag_var);
117 }
118 }
119 target_validity = targetm.get_pch_validity (&v.target_data_length);
120
121 if (fwrite (ptr: partial_pch, IDENT_LENGTH, n: 1, s: f) != 1
122 || fwrite (ptr: executable_checksum, size: 16, n: 1, s: f) != 1
123 || fwrite (ptr: &v, size: sizeof (v), n: 1, s: f) != 1
124 || fwrite (ptr: target_validity, size: v.target_data_length, n: 1, s: f) != 1)
125 fatal_error (input_location, "cannot write to %s: %m", pch_file);
126
127 /* Let the debugging format deal with the PCHness. */
128 (*debug_hooks->handle_pch) (0);
129
130 if (pch_ready_to_save_cpp_state)
131 pch_cpp_save_state ();
132
133 XDELETE (target_validity);
134}
135
136/* Whether preprocessor state has been saved in a PCH file. */
137
138static 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
144void
145pch_cpp_save_state (void)
146{
147 if (!pch_cpp_state_saved)
148 {
149 if (pch_outfile)
150 {
151 cpp_save_state (parse_in, pch_outfile);
152 pch_cpp_state_saved = true;
153 }
154 else
155 pch_ready_to_save_cpp_state = true;
156 }
157}
158
159/* Write the PCH file. This is called at the end of a compilation which
160 will produce a PCH file. */
161
162void
163c_common_write_pch (void)
164{
165 timevar_push (tv: TV_PCH_SAVE);
166
167 targetm.prepare_pch_save ();
168
169 (*debug_hooks->handle_pch) (1);
170
171 prepare_target_option_nodes_for_pch ();
172
173 cpp_write_pch_deps (parse_in, pch_outfile);
174
175 gt_pch_save (f: pch_outfile);
176
177 timevar_push (tv: TV_PCH_CPP_SAVE);
178 cpp_write_pch_state (parse_in, pch_outfile);
179 timevar_pop (tv: TV_PCH_CPP_SAVE);
180
181 if (fseek (stream: pch_outfile, off: 0, SEEK_SET) != 0
182 || fwrite (ptr: get_ident (), IDENT_LENGTH, n: 1, s: pch_outfile) != 1)
183 fatal_error (input_location, "cannot write %s: %m", pch_file);
184
185 fclose (stream: pch_outfile);
186
187 timevar_pop (tv: TV_PCH_SAVE);
188}
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
195int
196c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
197{
198 int sizeread;
199 int result;
200 char ident[IDENT_LENGTH + 16];
201 const char *pch_ident;
202 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 if (flag_modules)
209 return 2;
210
211 sizeread = read (fd: fd, buf: ident, IDENT_LENGTH + 16);
212 if (sizeread == -1)
213 fatal_error (input_location, "cannot read %s: %m", name);
214 else if (sizeread != IDENT_LENGTH + 16)
215 {
216 cpp_warning (pfile, CPP_W_INVALID_PCH, msgid: "%s: too short to be a PCH file",
217 name);
218 return 2;
219 }
220
221 pch_ident = get_ident();
222 if (memcmp (s1: ident, s2: pch_ident, IDENT_LENGTH) != 0)
223 {
224 if (memcmp (s1: ident, s2: pch_ident, n: 5) == 0)
225 /* It's a PCH, for the right language, but has the wrong version. */
226 cpp_warning (pfile, CPP_W_INVALID_PCH,
227 msgid: "%s: not compatible with this GCC version", name);
228 else if (memcmp (s1: ident, s2: pch_ident, n: 4) == 0)
229 /* It's a PCH for the wrong language. */
230 cpp_warning (pfile, CPP_W_INVALID_PCH, msgid: "%s: not for %s", name,
231 lang_hooks.name);
232 else
233 /* Not any kind of PCH. */
234 cpp_warning (pfile, CPP_W_INVALID_PCH, msgid: "%s: not a PCH file", name);
235 return 2;
236 }
237 if (memcmp (s1: ident + IDENT_LENGTH, s2: executable_checksum, n: 16) != 0)
238 {
239 cpp_warning (pfile, CPP_W_INVALID_PCH,
240 msgid: "%s: created by a different GCC executable", name);
241 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 if (read (fd: fd, buf: &v, nbytes: sizeof (v)) != sizeof (v))
248 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 if (v.pch_write_symbols != write_symbols
254 && write_symbols != NO_DEBUG)
255 {
256 char *created_str = xstrdup (debug_set_names (w_symbols: v.pch_write_symbols));
257 char *used_str = xstrdup (debug_set_names (write_symbols));
258 cpp_warning (pfile, CPP_W_INVALID_PCH,
259 msgid: "%s: created with '%s' debug info, but used with '%s'", name,
260 created_str, used_str);
261 free (ptr: created_str);
262 free (ptr: used_str);
263 return 2;
264 }
265
266 /* Check flags that must match exactly. */
267 {
268 size_t i;
269 for (i = 0; i < MATCH_SIZE; i++)
270 if (*pch_matching[i].flag_var != v.match[i])
271 {
272 cpp_warning (pfile, CPP_W_INVALID_PCH,
273 msgid: "%s: settings for %s do not match", name,
274 pch_matching[i].flag_name);
275 return 2;
276 }
277 }
278
279 /* Check the target-specific validity data. */
280 {
281 void *this_file_data = xmalloc (v.target_data_length);
282 const char *msg;
283
284 if ((size_t) read (fd: fd, buf: this_file_data, nbytes: v.target_data_length)
285 != v.target_data_length)
286 fatal_error (input_location, "cannot read %s: %m", name);
287 msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
288 free (ptr: this_file_data);
289 if (msg != NULL)
290 {
291 cpp_warning (pfile, CPP_W_INVALID_PCH, msgid: "%s: %s", name, msg);
292 return 2;
293 }
294 }
295
296 /* Check the preprocessor macros are the same as when the PCH was
297 generated. */
298
299 result = cpp_valid_state (pfile, name, fd);
300 if (result == -1)
301 return 2;
302 else
303 return result == 0;
304}
305
306/* If non-NULL, this function is called after a precompile header file
307 is loaded. */
308void (*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
313void
314c_common_read_pch (cpp_reader *pfile, const char *name,
315 int fd, const char *orig_name ATTRIBUTE_UNUSED)
316{
317 FILE *f;
318 struct save_macro_data *smd;
319 expanded_location saved_loc;
320 bool saved_trace_includes;
321 int cpp_result;
322
323 timevar_push (tv: TV_PCH_RESTORE);
324
325 f = fdopen (fd, "rb");
326 if (f == NULL)
327 {
328 cpp_errno (pfile, CPP_DL_ERROR, msgid: "calling fdopen");
329 close (fd: fd);
330 goto end;
331 }
332
333 cpp_get_callbacks (parse_in)->valid_pch = NULL;
334
335 /* Save the location and then restore it after reading the PCH. */
336 saved_loc = expand_location (line_table->highest_line);
337 saved_trace_includes = line_table->trace_includes;
338
339 timevar_push (tv: TV_PCH_CPP_RESTORE);
340 cpp_prepare_state (pfile, &smd);
341 timevar_pop (tv: TV_PCH_CPP_RESTORE);
342
343 gt_pch_restore (f);
344 cpp_set_line_map (pfile, line_table);
345 rebuild_location_adhoc_htab (line_table);
346 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 linemap_add (line_table, LC_ENTER, sysp: 0, to_file: saved_loc.file,
352 to_line: saved_loc.line > 1 ? saved_loc.line - 1 : saved_loc.line);
353
354 timevar_push (tv: TV_PCH_CPP_RESTORE);
355 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 linemap_line_start (set: line_table, to_line: saved_loc.line, max_column_hint: 0);
360
361 timevar_pop (tv: TV_PCH_CPP_RESTORE);
362 fclose (stream: f);
363
364 if (cpp_result != 0)
365 goto end;
366
367 /* Give the front end a chance to take action after a PCH file has
368 been loaded. */
369 if (lang_post_pch_load)
370 (*lang_post_pch_load) ();
371
372end:
373 timevar_pop (tv: TV_PCH_RESTORE);
374}
375
376/* Indicate that no more PCH files should be read. */
377
378void
379c_common_no_more_pch (void)
380{
381 if (cpp_get_callbacks (parse_in)->valid_pch)
382 {
383 cpp_get_callbacks (parse_in)->valid_pch = NULL;
384 void *addr = NULL;
385 host_hooks.gt_pch_use_address (addr, 0, -1, 0);
386 }
387}
388
389/* Handle #pragma GCC pch_preprocess, to load in the PCH file. */
390
391void
392c_common_pch_pragma (cpp_reader *pfile, const char *name)
393{
394 int fd;
395
396 if (!cpp_get_options (pfile)->preprocessed)
397 {
398 error ("%<pch_preprocess%> pragma should only be used "
399 "with %<-fpreprocessed%>");
400 inform (input_location, "use %<#include%> instead");
401 return;
402 }
403
404 fd = open (file: name, O_RDONLY | O_BINARY, 0666);
405 if (fd == -1)
406 fatal_error (input_location, "%s: couldn%'t open PCH file: %m", name);
407
408 if (c_common_valid_pch (pfile, name, fd) != 1)
409 {
410 if (!cpp_get_options (pfile)->warn_invalid_pch)
411 inform (input_location, "use %<-Winvalid-pch%> for more information");
412 fatal_error (input_location, "%s: PCH file was invalid", name);
413 }
414
415 c_common_read_pch (pfile, name, fd, orig_name: name);
416
417 close (fd: fd);
418}
419
420

source code of gcc/c-family/c-pch.cc