]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/cp/repo.c
* repo.c (pending_repo): Change type to a VEC.
[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 2006, 2007, 2008, 2009, 2010 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 3, 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 COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 /* My strategy here is as follows:
23
24 Everything should be emitted in a translation unit where it is used.
25 The results of the automatic process should be easily reproducible with
26 explicit code. */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33 #include "cp-tree.h"
34 #include "input.h"
35 #include "obstack.h"
36 #include "toplev.h"
37 #include "diagnostic-core.h"
38 #include "flags.h"
39
40 static const char *extract_string (const char **);
41 static const char *get_base_filename (const char *);
42 static FILE *open_repo_file (const char *);
43 static char *afgets (FILE *);
44 static FILE *reopen_repo_file_for_write (void);
45
46 static GTY(()) VEC(tree,gc) *pending_repo;
47 static char *repo_name;
48
49 static const char *old_args, *old_dir, *old_main;
50
51 static struct obstack temporary_obstack;
52 static bool temporary_obstack_initialized_p;
53
54 /* Parse a reasonable subset of shell quoting syntax. */
55
56 static const char *
57 extract_string (const char **pp)
58 {
59 const char *p = *pp;
60 int backquote = 0;
61 int inside = 0;
62
63 for (;;)
64 {
65 char c = *p;
66 if (c == '\0')
67 break;
68 ++p;
69 if (backquote)
70 {
71 obstack_1grow (&temporary_obstack, c);
72 backquote = 0;
73 }
74 else if (! inside && c == ' ')
75 break;
76 else if (! inside && c == '\\')
77 backquote = 1;
78 else if (c == '\'')
79 inside = !inside;
80 else
81 obstack_1grow (&temporary_obstack, c);
82 }
83
84 obstack_1grow (&temporary_obstack, '\0');
85 *pp = p;
86 return (char *) obstack_finish (&temporary_obstack);
87 }
88
89 static const char *
90 get_base_filename (const char *filename)
91 {
92 const char *p = getenv ("COLLECT_GCC_OPTIONS");
93 const char *output = NULL;
94 int compiling = 0;
95
96 while (p && *p)
97 {
98 const char *q = extract_string (&p);
99
100 if (strcmp (q, "-o") == 0)
101 {
102 if (flag_compare_debug)
103 /* Just in case aux_base_name was based on a name with two
104 or more '.'s, add an arbitrary extension that will be
105 stripped by the caller. */
106 output = concat (aux_base_name, ".o", NULL);
107 else
108 output = extract_string (&p);
109 }
110 else if (strcmp (q, "-c") == 0)
111 compiling = 1;
112 }
113
114 if (compiling && output)
115 return output;
116
117 if (p && ! compiling)
118 {
119 warning (0, "-frepo must be used with -c");
120 flag_use_repository = 0;
121 return NULL;
122 }
123
124 return lbasename (filename);
125 }
126
127 static FILE *
128 open_repo_file (const char *filename)
129 {
130 const char *p;
131 const char *s = get_base_filename (filename);
132
133 if (s == NULL)
134 return NULL;
135
136 p = lbasename (s);
137 p = strrchr (p, '.');
138 if (! p)
139 p = s + strlen (s);
140
141 repo_name = XNEWVEC (char, p - s + 5);
142 memcpy (repo_name, s, p - s);
143 memcpy (repo_name + (p - s), ".rpo", 5);
144
145 return fopen (repo_name, "r");
146 }
147
148 static char *
149 afgets (FILE *stream)
150 {
151 int c;
152 while ((c = getc (stream)) != EOF && c != '\n')
153 obstack_1grow (&temporary_obstack, c);
154 if (obstack_object_size (&temporary_obstack) == 0)
155 return NULL;
156 obstack_1grow (&temporary_obstack, '\0');
157 return (char *) obstack_finish (&temporary_obstack);
158 }
159
160 void
161 init_repo (void)
162 {
163 char *buf;
164 const char *p;
165 FILE *repo_file;
166
167 if (! flag_use_repository)
168 return;
169
170 /* When a PCH file is loaded, the entire identifier table is
171 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
172 So, we have to reread the repository file. */
173 lang_post_pch_load = init_repo;
174
175 if (!temporary_obstack_initialized_p)
176 gcc_obstack_init (&temporary_obstack);
177
178 repo_file = open_repo_file (main_input_filename);
179
180 if (repo_file == 0)
181 return;
182
183 while ((buf = afgets (repo_file)))
184 {
185 switch (buf[0])
186 {
187 case 'A':
188 old_args = ggc_strdup (buf + 2);
189 break;
190 case 'D':
191 old_dir = ggc_strdup (buf + 2);
192 break;
193 case 'M':
194 old_main = ggc_strdup (buf + 2);
195 break;
196 case 'O':
197 /* A symbol that we were able to define the last time this
198 file was compiled. */
199 break;
200 case 'C':
201 /* A symbol that the prelinker has requested that we
202 define. */
203 {
204 tree id = get_identifier (buf + 2);
205 IDENTIFIER_REPO_CHOSEN (id) = 1;
206 }
207 break;
208 default:
209 error ("mysterious repository information in %s", repo_name);
210 }
211 obstack_free (&temporary_obstack, buf);
212 }
213 fclose (repo_file);
214
215 if (old_args && !get_random_seed (true)
216 && (p = strstr (old_args, "'-frandom-seed=")))
217 set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
218 }
219
220 static FILE *
221 reopen_repo_file_for_write (void)
222 {
223 FILE *repo_file = fopen (repo_name, "w");
224
225 if (repo_file == 0)
226 {
227 error ("can't create repository information file %qs", repo_name);
228 flag_use_repository = 0;
229 }
230
231 return repo_file;
232 }
233
234 /* Emit any pending repos. */
235
236 void
237 finish_repo (void)
238 {
239 tree val;
240 char *dir, *args;
241 FILE *repo_file;
242 unsigned ix;
243
244 if (!flag_use_repository || flag_compare_debug)
245 return;
246
247 if (seen_error ())
248 return;
249
250 repo_file = reopen_repo_file_for_write ();
251 if (repo_file == 0)
252 goto out;
253
254 fprintf (repo_file, "M %s\n", main_input_filename);
255 dir = getpwd ();
256 fprintf (repo_file, "D %s\n", dir);
257 args = getenv ("COLLECT_GCC_OPTIONS");
258 if (args)
259 {
260 fprintf (repo_file, "A %s", args);
261 /* If -frandom-seed is not among the ARGS, then add the value
262 that we chose. That will ensure that the names of types from
263 anonymous namespaces will get the same mangling when this
264 file is recompiled. */
265 if (!strstr (args, "'-frandom-seed="))
266 fprintf (repo_file, " '-frandom-seed=%s'", get_random_seed (false));
267 fprintf (repo_file, "\n");
268 }
269
270 for (ix = VEC_length (tree, pending_repo) - 1;
271 VEC_iterate (tree, pending_repo, ix, val);
272 ix--);
273 {
274 tree name = DECL_ASSEMBLER_NAME (val);
275 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
276 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
277 }
278
279 out:
280 if (repo_file)
281 fclose (repo_file);
282 }
283
284 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
285 definition is available in this translation unit. Returns 0 if
286 this definition should not be emitted in this translation unit
287 because it will be emitted elsewhere. Returns 1 if the repository
288 file indicates that that DECL should be emitted in this translation
289 unit, or 2 if the repository file is not in use. */
290
291 int
292 repo_emit_p (tree decl)
293 {
294 int ret = 0;
295 gcc_assert (TREE_PUBLIC (decl));
296 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
297 || TREE_CODE (decl) == VAR_DECL);
298 gcc_assert (!DECL_REALLY_EXTERN (decl));
299
300 /* When not using the repository, emit everything. */
301 if (!flag_use_repository)
302 return 2;
303
304 /* Only template instantiations are managed by the repository. This
305 is an artificial restriction; the code in the prelinker and here
306 will work fine if all entities with vague linkage are managed by
307 the repository. */
308 if (TREE_CODE (decl) == VAR_DECL)
309 {
310 tree type = NULL_TREE;
311 if (DECL_VTABLE_OR_VTT_P (decl))
312 type = DECL_CONTEXT (decl);
313 else if (DECL_TINFO_P (decl))
314 type = TREE_TYPE (DECL_NAME (decl));
315 if (!DECL_TEMPLATE_INSTANTIATION (decl)
316 && (!TYPE_LANG_SPECIFIC (type)
317 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
318 return 2;
319 /* Const static data members initialized by constant expressions must
320 be processed where needed so that their definitions are
321 available. Still record them into *.rpo files, so if they
322 weren't actually emitted and collect2 requests them, they can
323 be provided. */
324 if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
325 && DECL_CLASS_SCOPE_P (decl))
326 ret = 2;
327 }
328 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
329 return 2;
330
331 if (DECL_EXPLICIT_INSTANTIATION (decl))
332 return 2;
333
334 /* For constructors and destructors, the repository contains
335 information about the clones -- not the original function --
336 because only the clones are emitted in the object file. */
337 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
338 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
339 {
340 int emit_p = 0;
341 tree clone;
342 /* There is no early exit from this loop because we want to
343 ensure that all of the clones are marked as available in this
344 object file. */
345 FOR_EACH_CLONE (clone, decl)
346 /* The only possible results from the recursive call to
347 repo_emit_p are 0 or 1. */
348 if (repo_emit_p (clone))
349 emit_p = 1;
350 return emit_p;
351 }
352
353 /* Keep track of all available entities. */
354 if (!DECL_REPO_AVAILABLE_P (decl))
355 {
356 DECL_REPO_AVAILABLE_P (decl) = 1;
357 VEC_safe_push (tree, gc, pending_repo, decl);
358 }
359
360 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
361 }
362
363 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
364 export from this translation unit. */
365
366 bool
367 repo_export_class_p (const_tree class_type)
368 {
369 if (!flag_use_repository)
370 return false;
371 if (!CLASSTYPE_VTABLES (class_type))
372 return false;
373 /* If the virtual table has been assigned to this translation unit,
374 export the class. */
375 return (IDENTIFIER_REPO_CHOSEN
376 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
377 }
378
379 #include "gt-cp-repo.h"