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