]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/cp/repo.c
* configure.ac (cxx_compat_warn): Set if -Wc++-compat is supported.
[thirdparty/gcc.git] / gcc / cp / repo.c
1 /* Code to maintain a C++ template repository.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
4 Contributed by Jason Merrill (jason@cygnus.com)
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23 /* My strategy here is as follows:
24
25 Everything should be emitted in a translation unit where it is used.
26 The results of the automatic process should be easily reproducible with
27 explicit code. */
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "tree.h"
34 #include "cp-tree.h"
35 #include "input.h"
36 #include "obstack.h"
37 #include "toplev.h"
38 #include "diagnostic.h"
39 #include "flags.h"
40
41 static char *extract_string (char **);
42 static const char *get_base_filename (const char *);
43 static void open_repo_file (const char *);
44 static char *afgets (FILE *);
45 static void reopen_repo_file_for_write (void);
46
47 static GTY(()) tree pending_repo;
48 static char *repo_name;
49 static FILE *repo_file;
50
51 static const char *old_args, *old_dir, *old_main;
52
53 static struct obstack temporary_obstack;
54 static bool temporary_obstack_initialized_p;
55
56 /* Parse a reasonable subset of shell quoting syntax. */
57
58 static char *
59 extract_string (char **pp)
60 {
61 char *p = *pp;
62 int backquote = 0;
63 int inside = 0;
64
65 for (;;)
66 {
67 char c = *p;
68 if (c == '\0')
69 break;
70 ++p;
71 if (backquote)
72 {
73 obstack_1grow (&temporary_obstack, c);
74 backquote = 0;
75 }
76 else if (! inside && c == ' ')
77 break;
78 else if (! inside && c == '\\')
79 backquote = 1;
80 else if (c == '\'')
81 inside = !inside;
82 else
83 obstack_1grow (&temporary_obstack, c);
84 }
85
86 obstack_1grow (&temporary_obstack, '\0');
87 *pp = p;
88 return (char *) obstack_finish (&temporary_obstack);
89 }
90
91 static const char *
92 get_base_filename (const char *filename)
93 {
94 char *p = getenv ("COLLECT_GCC_OPTIONS");
95 char *output = NULL;
96 int compiling = 0;
97
98 while (p && *p)
99 {
100 char *q = extract_string (&p);
101
102 if (strcmp (q, "-o") == 0)
103 output = extract_string (&p);
104 else if (strcmp (q, "-c") == 0)
105 compiling = 1;
106 }
107
108 if (compiling && output)
109 return output;
110
111 if (p && ! compiling)
112 {
113 warning (0, "-frepo must be used with -c");
114 flag_use_repository = 0;
115 return NULL;
116 }
117
118 return lbasename (filename);
119 }
120
121 static void
122 open_repo_file (const char *filename)
123 {
124 const char *p;
125 const char *s = get_base_filename (filename);
126
127 if (s == NULL)
128 return;
129
130 p = lbasename (s);
131 p = strrchr (p, '.');
132 if (! p)
133 p = s + strlen (s);
134
135 repo_name = XNEWVEC (char, p - s + 5);
136 memcpy (repo_name, s, p - s);
137 memcpy (repo_name + (p - s), ".rpo", 5);
138
139 repo_file = fopen (repo_name, "r");
140 }
141
142 static char *
143 afgets (FILE *stream)
144 {
145 int c;
146 while ((c = getc (stream)) != EOF && c != '\n')
147 obstack_1grow (&temporary_obstack, c);
148 if (obstack_object_size (&temporary_obstack) == 0)
149 return NULL;
150 obstack_1grow (&temporary_obstack, '\0');
151 return (char *) obstack_finish (&temporary_obstack);
152 }
153
154 void
155 init_repo (void)
156 {
157 char *buf;
158
159 if (! flag_use_repository)
160 return;
161
162 /* When a PCH file is loaded, the entire identifier table is
163 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
164 So, we have to reread the repository file. */
165 lang_post_pch_load = init_repo;
166
167 if (!temporary_obstack_initialized_p)
168 gcc_obstack_init (&temporary_obstack);
169
170 open_repo_file (main_input_filename);
171
172 if (repo_file == 0)
173 return;
174
175 while ((buf = afgets (repo_file)))
176 {
177 switch (buf[0])
178 {
179 case 'A':
180 old_args = ggc_strdup (buf + 2);
181 break;
182 case 'D':
183 old_dir = ggc_strdup (buf + 2);
184 break;
185 case 'M':
186 old_main = ggc_strdup (buf + 2);
187 break;
188 case 'O':
189 /* A symbol that we were able to define the last time this
190 file was compiled. */
191 break;
192 case 'C':
193 /* A symbol that the prelinker has requested that we
194 define. */
195 {
196 tree id = get_identifier (buf + 2);
197 IDENTIFIER_REPO_CHOSEN (id) = 1;
198 }
199 break;
200 default:
201 error ("mysterious repository information in %s", repo_name);
202 }
203 obstack_free (&temporary_obstack, buf);
204 }
205 fclose (repo_file);
206 }
207
208 static void
209 reopen_repo_file_for_write (void)
210 {
211 repo_file = fopen (repo_name, "w");
212
213 if (repo_file == 0)
214 {
215 error ("can't create repository information file %qs", repo_name);
216 flag_use_repository = 0;
217 }
218 }
219
220 /* Emit any pending repos. */
221
222 void
223 finish_repo (void)
224 {
225 tree t;
226 char *dir, *args;
227
228 if (!flag_use_repository)
229 return;
230
231 if (errorcount || sorrycount)
232 goto out;
233
234 reopen_repo_file_for_write ();
235 if (repo_file == 0)
236 goto out;
237
238 fprintf (repo_file, "M %s\n", main_input_filename);
239 dir = getpwd ();
240 fprintf (repo_file, "D %s\n", dir);
241 args = getenv ("COLLECT_GCC_OPTIONS");
242 if (args)
243 {
244 fprintf (repo_file, "A %s", args);
245 /* If -frandom-seed is not among the ARGS, then add the value
246 that we chose. That will ensure that the names of types from
247 anonymous namespaces will get the same mangling when this
248 file is recompiled. */
249 if (!strstr (args, "'-frandom-seed="))
250 fprintf (repo_file, " '-frandom-seed=%s'", flag_random_seed);
251 fprintf (repo_file, "\n");
252 }
253
254 for (t = pending_repo; t; t = TREE_CHAIN (t))
255 {
256 tree val = TREE_VALUE (t);
257 tree name = DECL_ASSEMBLER_NAME (val);
258 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
259 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
260 }
261
262 out:
263 if (repo_file)
264 fclose (repo_file);
265 }
266
267 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
268 definition is available in this translation unit. Returns 0 if
269 this definition should not be emitted in this translation unit
270 because it will be emitted elsewhere. Returns 1 if the repository
271 file indicates that that DECL should be emitted in this translation
272 unit, or 2 if the repository file is not in use. */
273
274 int
275 repo_emit_p (tree decl)
276 {
277 gcc_assert (TREE_PUBLIC (decl));
278 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
279 || TREE_CODE (decl) == VAR_DECL);
280 gcc_assert (!DECL_REALLY_EXTERN (decl));
281
282 /* When not using the repository, emit everything. */
283 if (!flag_use_repository)
284 return 2;
285
286 /* Only template instantiations are managed by the repository. This
287 is an artificial restriction; the code in the prelinker and here
288 will work fine if all entities with vague linkage are managed by
289 the repository. */
290 if (TREE_CODE (decl) == VAR_DECL)
291 {
292 tree type = NULL_TREE;
293 if (DECL_VTABLE_OR_VTT_P (decl))
294 type = DECL_CONTEXT (decl);
295 else if (DECL_TINFO_P (decl))
296 type = TREE_TYPE (DECL_NAME (decl));
297 if (!DECL_TEMPLATE_INSTANTIATION (decl)
298 && (!TYPE_LANG_SPECIFIC (type)
299 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
300 return 2;
301 /* Static data members initialized by constant expressions must
302 be processed where needed so that their definitions are
303 available. */
304 if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
305 && DECL_CLASS_SCOPE_P (decl))
306 return 2;
307 }
308 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
309 return 2;
310
311 /* For constructors and destructors, the repository contains
312 information about the clones -- not the original function --
313 because only the clones are emitted in the object file. */
314 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
315 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
316 {
317 int emit_p = 0;
318 tree clone;
319 /* There is no early exit from this loop because we want to
320 ensure that all of the clones are marked as available in this
321 object file. */
322 FOR_EACH_CLONE (clone, decl)
323 /* The only possible results from the recursive call to
324 repo_emit_p are 0 or 1. */
325 if (repo_emit_p (clone))
326 emit_p = 1;
327 return emit_p;
328 }
329
330 /* Keep track of all available entities. */
331 if (!DECL_REPO_AVAILABLE_P (decl))
332 {
333 DECL_REPO_AVAILABLE_P (decl) = 1;
334 pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
335 }
336
337 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
338 }
339
340 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
341 export from this translation unit. */
342
343 bool
344 repo_export_class_p (tree class_type)
345 {
346 if (!flag_use_repository)
347 return false;
348 if (!CLASSTYPE_VTABLES (class_type))
349 return false;
350 /* If the virtual table has been assigned to this translation unit,
351 export the class. */
352 return (IDENTIFIER_REPO_CHOSEN
353 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
354 }
355
356 #include "gt-cp-repo.h"