OSDN Git Service

PR c++/10784
[pf3gnuchains/gcc-fork.git] / gcc / c-pch.c
1 /* Precompiled header implementation for the C languages.
2    Copyright (C) 2000, 2002, 2003 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 2, 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 COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "cpplib.h"
25 #include "tree.h"
26 #include "flags.h"
27 #include "c-common.h"
28 #include "output.h"
29 #include "toplev.h"
30 #include "debug.h"
31 #include "c-pragma.h"
32 #include "ggc.h"
33 #include "langhooks.h"
34
35 struct c_pch_validity
36 {
37   unsigned char debug_info_type;
38 };
39
40 struct c_pch_header 
41 {
42   unsigned long asm_size;
43 };
44
45 #define IDENT_LENGTH 8
46
47 static FILE *pch_outfile;
48
49 static long asm_file_startpos;
50
51 static const char *get_ident (void);
52
53 /* Compute an appropriate 8-byte magic number for the PCH file, so that
54    utilities like file(1) can identify it, and so that GCC can quickly
55    ignore non-PCH files and PCH files that are of a completely different
56    format.  */
57
58 static const char *
59 get_ident(void)
60 {
61   static char result[IDENT_LENGTH];
62   static const char template[IDENT_LENGTH] = "gpch.011";
63   
64   memcpy (result, template, IDENT_LENGTH);
65   if (c_language == clk_c)
66     result[4] = flag_objc ? 'o' : 'C';
67   else if (c_language == clk_cplusplus)
68     result[4] = flag_objc ? 'O' : '+';
69   else
70     abort ();
71   return result;
72 }
73
74 /* Prepare to write a PCH file.  This is called at the start of 
75    compilation.  */
76
77 void
78 pch_init (void)
79 {
80   FILE *f;
81   struct c_pch_validity v;
82   
83   if (! pch_file)
84     return;
85   
86   f = fopen (pch_file, "w+b");
87   if (f == NULL)
88     fatal_error ("can't open %s: %m", pch_file);
89   pch_outfile = f;
90   
91   v.debug_info_type = write_symbols;
92   if (fwrite (get_ident(), IDENT_LENGTH, 1, f) != 1
93       || fwrite (&v, sizeof (v), 1, f) != 1)
94     fatal_error ("can't write to %s: %m", pch_file);
95
96   /* We need to be able to re-read the output.  */
97   /* The driver always provides a valid -o option.  */
98   if (asm_file_name == NULL
99       || strcmp (asm_file_name, "-") == 0)
100     fatal_error ("`%s' is not a valid output file", asm_file_name);
101   
102   asm_file_startpos = ftell (asm_out_file);
103   
104   /* Let the debugging format deal with the PCHness.  */
105   (*debug_hooks->handle_pch) (0);
106   
107   cpp_save_state (parse_in, f);
108 }
109
110 /* Write the PCH file.  This is called at the end of a compilation which
111    will produce a PCH file.  */
112
113 void
114 c_common_write_pch (void)
115 {
116   char *buf;
117   long asm_file_end;
118   long written;
119   struct c_pch_header h;
120
121   (*debug_hooks->handle_pch) (1);
122
123   cpp_write_pch_deps (parse_in, pch_outfile);
124
125   asm_file_end = ftell (asm_out_file);
126   h.asm_size = asm_file_end - asm_file_startpos;
127   
128   if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
129     fatal_error ("can't write %s: %m", pch_file);
130   
131   buf = xmalloc (16384);
132   fflush (asm_out_file);
133
134   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
135     fatal_error ("can't seek in %s: %m", asm_file_name);
136
137   for (written = asm_file_startpos; written < asm_file_end; )
138     {
139       long size = asm_file_end - written;
140       if (size > 16384)
141         size = 16384;
142       if (fread (buf, size, 1, asm_out_file) != 1)
143         fatal_error ("can't read %s: %m", asm_file_name);
144       if (fwrite (buf, size, 1, pch_outfile) != 1)
145         fatal_error ("can't write %s: %m", pch_file);
146       written += size;
147     }
148   free (buf);
149
150   gt_pch_save (pch_outfile);
151   cpp_write_pch_state (parse_in, pch_outfile);
152
153   fclose (pch_outfile);
154 }
155
156 /* Check the PCH file called NAME, open on FD, to see if it can be used
157    in this compilation.  */
158
159 int
160 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
161 {
162   int sizeread;
163   int result;
164   char ident[IDENT_LENGTH];
165   const char *pch_ident;
166   struct c_pch_validity v;
167
168   if (! allow_pch)
169     return 2;
170
171   /* Perform a quick test of whether this is a valid
172      precompiled header for the current language.  */
173
174   sizeread = read (fd, ident, IDENT_LENGTH);
175   if (sizeread == -1)
176     fatal_error ("can't read %s: %m", name);
177   else if (sizeread != IDENT_LENGTH)
178     return 2;
179   
180   pch_ident = get_ident();
181   if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
182     {
183       if (cpp_get_options (pfile)->warn_invalid_pch)
184         {
185           if (memcmp (ident, pch_ident, 5) == 0)
186             /* It's a PCH, for the right language, but has the wrong version.
187              */
188             cpp_error (pfile, DL_WARNING, 
189                        "%s: not compatible with this GCC version", name);
190           else if (memcmp (ident, pch_ident, 4) == 0)
191             /* It's a PCH for the wrong language.  */
192             cpp_error (pfile, DL_WARNING, "%s: not for %s", name,
193                        lang_hooks.name);
194           else 
195             /* Not any kind of PCH.  */
196             cpp_error (pfile, DL_WARNING, "%s: not a PCH file", name);
197         }
198       return 2;
199     }
200
201   if (read (fd, &v, sizeof (v)) != sizeof (v))
202     fatal_error ("can't read %s: %m", name);
203
204   /* The allowable debug info combinations are that either the PCH file
205      was built with the same as is being used now, or the PCH file was
206      built for some kind of debug info but now none is in use.  */
207   if (v.debug_info_type != write_symbols
208       && write_symbols != NO_DEBUG)
209     {
210       if (cpp_get_options (pfile)->warn_invalid_pch)
211         cpp_error (pfile, DL_WARNING, 
212                    "%s: created with -g%s, but used with -g%s", name,
213                    debug_type_names[v.debug_info_type],
214                    debug_type_names[write_symbols]);
215       return 2;
216     }
217
218   /* Check the preprocessor macros are the same as when the PCH was
219      generated.  */
220   
221   result = cpp_valid_state (pfile, name, fd);
222   if (result == -1)
223     return 2;
224   else
225     return result == 0;
226 }
227
228 /* Load in the PCH file NAME, open on FD.  It was originally searched for
229    by ORIG_NAME.  */
230
231 void
232 c_common_read_pch (cpp_reader *pfile, const char *name,
233                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
234 {
235   FILE *f;
236   struct c_pch_header h;
237   char *buf;
238   unsigned long written;
239   struct save_macro_data *smd;
240   
241   f = fdopen (fd, "rb");
242   if (f == NULL)
243     {
244       cpp_errno (pfile, DL_ERROR, "calling fdopen");
245       return;
246     }
247
248   allow_pch = 0;
249
250   if (fread (&h, sizeof (h), 1, f) != 1)
251     {
252       cpp_errno (pfile, DL_ERROR, "reading");
253       return;
254     }
255
256   buf = xmalloc (16384);
257   for (written = 0; written < h.asm_size; )
258     {
259       long size = h.asm_size - written;
260       if (size > 16384)
261         size = 16384;
262       if (fread (buf, size, 1, f) != 1
263           || fwrite (buf, size, 1, asm_out_file) != 1)
264         cpp_errno (pfile, DL_ERROR, "reading");
265       written += size;
266     }
267   free (buf);
268
269   cpp_prepare_state (pfile, &smd);
270
271   gt_pch_restore (f);
272
273   if (cpp_read_state (pfile, name, f, smd) != 0)
274     return;
275
276   fclose (f);
277 }