#include "coretypes.h"
#include "cpplib.h"
#include "tree.h"
+#include "flags.h"
#include "c-common.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
#include "langhooks.h"
+struct c_pch_validity
+{
+ unsigned char debug_info_type;
+};
+
struct c_pch_header
{
unsigned long asm_size;
static const char * get_ident PARAMS((void));
+/* Compute an appropriate 8-byte magic number for the PCH file, so that
+ utilities like file(1) can identify it, and so that GCC can quickly
+ ignore non-PCH files and PCH files that are of a completely different
+ format. */
+
static const char *
get_ident()
{
static char result[IDENT_LENGTH];
- static const char template[IDENT_LENGTH] = "gpch.010";
+ static const char template[IDENT_LENGTH] = "gpch.011";
memcpy (result, template, IDENT_LENGTH);
if (c_language == clk_c)
return result;
}
+/* Prepare to write a PCH file. This is called at the start of
+ compilation. */
+
void
pch_init ()
{
FILE *f;
+ struct c_pch_validity v;
- if (pch_file)
- {
- f = fopen (pch_file, "w+b");
- if (f == NULL)
- fatal_io_error ("can't open %s", pch_file);
- pch_outfile = f;
-
- if (fwrite (get_ident(), IDENT_LENGTH, 1, f) != 1)
- fatal_io_error ("can't write to %s", pch_file);
-
- /* We need to be able to re-read the output. */
- /* The driver always provides a valid -o option. */
- if (asm_file_name == NULL
- || strcmp (asm_file_name, "-") == 0)
- fatal_error ("`%s' is not a valid output file", asm_file_name);
-
- asm_file_startpos = ftell (asm_out_file);
-
- /* Let the debugging format deal with the PCHness. */
- (*debug_hooks->handle_pch) (0);
-
- cpp_save_state (parse_in, f);
- }
+ if (! pch_file)
+ return;
+
+ f = fopen (pch_file, "w+b");
+ if (f == NULL)
+ fatal_io_error ("can't open %s", pch_file);
+ pch_outfile = f;
+
+ v.debug_info_type = write_symbols;
+ if (fwrite (get_ident(), IDENT_LENGTH, 1, f) != 1
+ || fwrite (&v, sizeof (v), 1, f) != 1)
+ fatal_io_error ("can't write to %s", pch_file);
+
+ /* We need to be able to re-read the output. */
+ /* The driver always provides a valid -o option. */
+ if (asm_file_name == NULL
+ || strcmp (asm_file_name, "-") == 0)
+ fatal_error ("`%s' is not a valid output file", asm_file_name);
+
+ asm_file_startpos = ftell (asm_out_file);
+
+ /* Let the debugging format deal with the PCHness. */
+ (*debug_hooks->handle_pch) (0);
+
+ cpp_save_state (parse_in, f);
}
+/* Write the PCH file. This is called at the end of a compilation which
+ will produce a PCH file. */
+
void
c_common_write_pch ()
{
fclose (pch_outfile);
}
+/* Check the PCH file called NAME, open on FD, to see if it can be used
+ in this compilation. */
+
int
c_common_valid_pch (pfile, name, fd)
cpp_reader *pfile;
int result;
char ident[IDENT_LENGTH];
const char *pch_ident;
+ struct c_pch_validity v;
if (! allow_pch)
return 2;
/* Perform a quick test of whether this is a valid
- precompiled header for C. */
+ precompiled header for the current language. */
sizeread = read (fd, ident, IDENT_LENGTH);
if (sizeread == -1)
return 2;
}
+ if (read (fd, &v, sizeof (v)) != sizeof (v))
+ {
+ fatal_io_error ("can't read %s", name);
+ return 2;
+ }
+
+ /* The allowable debug info combinations are that either the PCH file
+ was built with the same as is being used now, or the PCH file was
+ built for some kind of debug info but now none is in use. */
+ if (v.debug_info_type != write_symbols
+ && write_symbols != NO_DEBUG)
+ {
+ if (cpp_get_options (pfile)->warn_invalid_pch)
+ cpp_error (pfile, DL_WARNING,
+ "%s: created with -g%s, but used with -g%s", name,
+ debug_type_names[v.debug_info_type],
+ debug_type_names[write_symbols]);
+ return 2;
+ }
+
/* Check the preprocessor macros are the same as when the PCH was
generated. */
return result == 0;
}
+/* Load in the PCH file NAME, open on FD. It was originally searched for
+ by ORIG_NAME. */
+
void
c_common_read_pch (pfile, name, fd, orig_name)
cpp_reader *pfile;
return 1;
}
+/* Indexed by enum debug_info_type. */
+const char *const debug_type_names[] =
+{
+ "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms"
+};
+
/* Parse a -g... command line switch. ARG is the value after the -g.
It is safe to access 'ARG - 2' to generate the full switch name.
Return the number of strings consumed. */
-g and -ggdb don't explicitly set the debugging format so
-gdwarf -g3 is equivalent to -gdwarf3. */
static int type_explicitly_set_p = 0;
- /* Indexed by enum debug_info_type. */
- static const char *const debug_type_names[] =
- {
- "none", "stabs", "coff", "dwarf-1", "dwarf-2", "xcoff", "vms"
- };
/* The maximum admissible debug level value. */
static const unsigned max_debug_level = 3;