PR c++/65054
[official-gcc.git] / gcc / cp / repo.c
blobf417e4b56f12e5fe6a11b0ea4affe05776c4dd59
1 /* Code to maintain a C++ template repository.
2 Copyright (C) 1995-2015 Free Software Foundation, Inc.
3 Contributed by Jason Merrill (jason@cygnus.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* My strategy here is as follows:
23 Everything should be emitted in a translation unit where it is used.
24 The results of the automatic process should be easily reproducible with
25 explicit code. */
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "hash-set.h"
32 #include "machmode.h"
33 #include "vec.h"
34 #include "double-int.h"
35 #include "input.h"
36 #include "alias.h"
37 #include "symtab.h"
38 #include "wide-int.h"
39 #include "inchash.h"
40 #include "tree.h"
41 #include "stringpool.h"
42 #include "cp-tree.h"
43 #include "input.h"
44 #include "obstack.h"
45 #include "toplev.h"
46 #include "diagnostic-core.h"
47 #include "flags.h"
49 static const char *extract_string (const char **);
50 static const char *get_base_filename (const char *);
51 static FILE *open_repo_file (const char *);
52 static char *afgets (FILE *);
53 static FILE *reopen_repo_file_for_write (void);
55 static GTY(()) vec<tree, va_gc> *pending_repo;
56 static char *repo_name;
58 static const char *old_args, *old_dir, *old_main;
60 static struct obstack temporary_obstack;
61 static bool temporary_obstack_initialized_p;
63 /* Parse a reasonable subset of shell quoting syntax. */
65 static const char *
66 extract_string (const char **pp)
68 const char *p = *pp;
69 int backquote = 0;
70 int inside = 0;
72 for (;;)
74 char c = *p;
75 if (c == '\0')
76 break;
77 ++p;
78 if (backquote)
80 obstack_1grow (&temporary_obstack, c);
81 backquote = 0;
83 else if (! inside && c == ' ')
84 break;
85 else if (! inside && c == '\\')
86 backquote = 1;
87 else if (c == '\'')
88 inside = !inside;
89 else
90 obstack_1grow (&temporary_obstack, c);
93 obstack_1grow (&temporary_obstack, '\0');
94 *pp = p;
95 return (char *) obstack_finish (&temporary_obstack);
98 static const char *
99 get_base_filename (const char *filename)
101 const char *p = getenv ("COLLECT_GCC_OPTIONS");
102 const char *output = NULL;
103 int compiling = 0;
105 while (p && *p)
107 const char *q = extract_string (&p);
109 if (strcmp (q, "-o") == 0)
111 if (flag_compare_debug)
112 /* Just in case aux_base_name was based on a name with two
113 or more '.'s, add an arbitrary extension that will be
114 stripped by the caller. */
115 output = concat (aux_base_name, ".o", NULL);
116 else
117 output = extract_string (&p);
119 else if (strcmp (q, "-c") == 0)
120 compiling = 1;
123 if (compiling && output)
124 return output;
126 if (p && ! compiling)
128 warning (0, "-frepo must be used with -c");
129 flag_use_repository = 0;
130 return NULL;
133 return lbasename (filename);
136 static FILE *
137 open_repo_file (const char *filename)
139 const char *p;
140 const char *s = get_base_filename (filename);
142 if (s == NULL)
143 return NULL;
145 p = lbasename (s);
146 p = strrchr (p, '.');
147 if (! p)
148 p = s + strlen (s);
150 repo_name = XNEWVEC (char, p - s + 5);
151 memcpy (repo_name, s, p - s);
152 memcpy (repo_name + (p - s), ".rpo", 5);
154 return fopen (repo_name, "r");
157 static char *
158 afgets (FILE *stream)
160 int c;
161 while ((c = getc (stream)) != EOF && c != '\n')
162 obstack_1grow (&temporary_obstack, c);
163 if (obstack_object_size (&temporary_obstack) == 0)
164 return NULL;
165 obstack_1grow (&temporary_obstack, '\0');
166 return (char *) obstack_finish (&temporary_obstack);
169 void
170 init_repo (void)
172 char *buf;
173 const char *p;
174 FILE *repo_file;
176 if (! flag_use_repository)
177 return;
179 /* When a PCH file is loaded, the entire identifier table is
180 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
181 So, we have to reread the repository file. */
182 lang_post_pch_load = init_repo;
184 if (!temporary_obstack_initialized_p)
185 gcc_obstack_init (&temporary_obstack);
187 repo_file = open_repo_file (main_input_filename);
189 if (repo_file == 0)
190 return;
192 while ((buf = afgets (repo_file)))
194 switch (buf[0])
196 case 'A':
197 old_args = ggc_strdup (buf + 2);
198 break;
199 case 'D':
200 old_dir = ggc_strdup (buf + 2);
201 break;
202 case 'M':
203 old_main = ggc_strdup (buf + 2);
204 break;
205 case 'O':
206 /* A symbol that we were able to define the last time this
207 file was compiled. */
208 break;
209 case 'C':
210 /* A symbol that the prelinker has requested that we
211 define. */
213 tree id = get_identifier (buf + 2);
214 IDENTIFIER_REPO_CHOSEN (id) = 1;
216 break;
217 default:
218 error ("mysterious repository information in %s", repo_name);
220 obstack_free (&temporary_obstack, buf);
222 fclose (repo_file);
224 if (old_args && !get_random_seed (true)
225 && (p = strstr (old_args, "'-frandom-seed=")))
226 set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
229 static FILE *
230 reopen_repo_file_for_write (void)
232 FILE *repo_file = fopen (repo_name, "w");
234 if (repo_file == 0)
236 error ("can%'t create repository information file %qs", repo_name);
237 flag_use_repository = 0;
240 return repo_file;
243 /* Emit any pending repos. */
245 void
246 finish_repo (void)
248 tree val;
249 char *dir, *args;
250 FILE *repo_file;
251 unsigned ix;
253 if (!flag_use_repository || flag_compare_debug)
254 return;
256 if (seen_error ())
257 return;
259 repo_file = reopen_repo_file_for_write ();
260 if (repo_file == 0)
261 goto out;
263 fprintf (repo_file, "M %s\n", main_input_filename);
264 dir = getpwd ();
265 fprintf (repo_file, "D %s\n", dir);
266 args = getenv ("COLLECT_GCC_OPTIONS");
267 if (args)
269 fprintf (repo_file, "A %s", args);
270 /* If -frandom-seed is not among the ARGS, then add the value
271 that we chose. That will ensure that the names of types from
272 anonymous namespaces will get the same mangling when this
273 file is recompiled. */
274 if (!strstr (args, "'-frandom-seed="))
275 fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'",
276 get_random_seed (false));
277 fprintf (repo_file, "\n");
280 FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo, ix, val)
282 tree name = DECL_ASSEMBLER_NAME (val);
283 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
284 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
287 out:
288 if (repo_file)
289 fclose (repo_file);
292 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
293 definition is available in this translation unit. Returns 0 if
294 this definition should not be emitted in this translation unit
295 because it will be emitted elsewhere. Returns 1 if the repository
296 file indicates that that DECL should be emitted in this translation
297 unit, or 2 if the repository file is not in use. */
300 repo_emit_p (tree decl)
302 int ret = 0;
303 gcc_assert (TREE_PUBLIC (decl));
304 gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
305 gcc_assert (!DECL_REALLY_EXTERN (decl)
306 /* A clone might not have its linkage flags updated yet
307 because we call import_export_decl before
308 maybe_clone_body. */
309 || DECL_ABSTRACT_ORIGIN (decl));
311 /* When not using the repository, emit everything. */
312 if (!flag_use_repository)
313 return 2;
315 /* Only template instantiations are managed by the repository. This
316 is an artificial restriction; the code in the prelinker and here
317 will work fine if all entities with vague linkage are managed by
318 the repository. */
319 if (VAR_P (decl))
321 tree type = NULL_TREE;
322 if (DECL_VTABLE_OR_VTT_P (decl))
323 type = DECL_CONTEXT (decl);
324 else if (DECL_TINFO_P (decl))
325 type = TREE_TYPE (DECL_NAME (decl));
326 if (!DECL_TEMPLATE_INSTANTIATION (decl)
327 && (!TYPE_LANG_SPECIFIC (type)
328 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
329 return 2;
330 /* Const static data members initialized by constant expressions must
331 be processed where needed so that their definitions are
332 available. Still record them into *.rpo files, so if they
333 weren't actually emitted and collect2 requests them, they can
334 be provided. */
335 if (decl_maybe_constant_var_p (decl)
336 && DECL_CLASS_SCOPE_P (decl))
337 ret = 2;
339 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
340 return 2;
342 if (DECL_EXPLICIT_INSTANTIATION (decl))
343 return 2;
345 /* For constructors and destructors, the repository contains
346 information about the clones -- not the original function --
347 because only the clones are emitted in the object file. */
348 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
349 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
351 int emit_p = 0;
352 tree clone;
353 /* There is no early exit from this loop because we want to
354 ensure that all of the clones are marked as available in this
355 object file. */
356 FOR_EACH_CLONE (clone, decl)
357 /* The only possible results from the recursive call to
358 repo_emit_p are 0 or 1. */
359 if (repo_emit_p (clone))
360 emit_p = 1;
361 return emit_p;
364 /* Keep track of all available entities. */
365 if (!DECL_REPO_AVAILABLE_P (decl))
367 DECL_REPO_AVAILABLE_P (decl) = 1;
368 vec_safe_push (pending_repo, decl);
371 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
374 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
375 export from this translation unit. */
377 bool
378 repo_export_class_p (const_tree class_type)
380 if (!flag_use_repository)
381 return false;
382 if (!CLASSTYPE_VTABLES (class_type))
383 return false;
384 /* If the virtual table has been assigned to this translation unit,
385 export the class. */
386 return (IDENTIFIER_REPO_CHOSEN
387 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
390 #include "gt-cp-repo.h"