gcc/
[official-gcc.git] / gcc / cp / repo.c
blob62c35f90ddc1c5ea62b1ab7250da54475de598d8
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 "alias.h"
32 #include "symtab.h"
33 #include "tree.h"
34 #include "stringpool.h"
35 #include "cp-tree.h"
36 #include "obstack.h"
37 #include "toplev.h"
38 #include "diagnostic-core.h"
39 #include "flags.h"
41 static const char *extract_string (const char **);
42 static const char *get_base_filename (const char *);
43 static FILE *open_repo_file (const char *);
44 static char *afgets (FILE *);
45 static FILE *reopen_repo_file_for_write (void);
47 static GTY(()) vec<tree, va_gc> *pending_repo;
48 static char *repo_name;
50 static const char *old_args, *old_dir, *old_main;
52 static struct obstack temporary_obstack;
53 static bool temporary_obstack_initialized_p;
55 /* Parse a reasonable subset of shell quoting syntax. */
57 static const char *
58 extract_string (const char **pp)
60 const char *p = *pp;
61 int backquote = 0;
62 int inside = 0;
64 for (;;)
66 char c = *p;
67 if (c == '\0')
68 break;
69 ++p;
70 if (backquote)
72 obstack_1grow (&temporary_obstack, c);
73 backquote = 0;
75 else if (! inside && c == ' ')
76 break;
77 else if (! inside && c == '\\')
78 backquote = 1;
79 else if (c == '\'')
80 inside = !inside;
81 else
82 obstack_1grow (&temporary_obstack, c);
85 obstack_1grow (&temporary_obstack, '\0');
86 *pp = p;
87 return (char *) obstack_finish (&temporary_obstack);
90 static const char *
91 get_base_filename (const char *filename)
93 const char *p = getenv ("COLLECT_GCC_OPTIONS");
94 const char *output = NULL;
95 int compiling = 0;
97 while (p && *p)
99 const char *q = extract_string (&p);
101 if (strcmp (q, "-o") == 0)
103 if (flag_compare_debug)
104 /* Just in case aux_base_name was based on a name with two
105 or more '.'s, add an arbitrary extension that will be
106 stripped by the caller. */
107 output = concat (aux_base_name, ".o", NULL);
108 else
109 output = extract_string (&p);
111 else if (strcmp (q, "-c") == 0)
112 compiling = 1;
115 if (compiling && output)
116 return output;
118 if (p && ! compiling)
120 warning (0, "-frepo must be used with -c");
121 flag_use_repository = 0;
122 return NULL;
125 return lbasename (filename);
128 static FILE *
129 open_repo_file (const char *filename)
131 const char *p;
132 const char *s = get_base_filename (filename);
134 if (s == NULL)
135 return NULL;
137 p = lbasename (s);
138 p = strrchr (p, '.');
139 if (! p)
140 p = s + strlen (s);
142 repo_name = XNEWVEC (char, p - s + 5);
143 memcpy (repo_name, s, p - s);
144 memcpy (repo_name + (p - s), ".rpo", 5);
146 return fopen (repo_name, "r");
149 static char *
150 afgets (FILE *stream)
152 int c;
153 while ((c = getc (stream)) != EOF && c != '\n')
154 obstack_1grow (&temporary_obstack, c);
155 if (obstack_object_size (&temporary_obstack) == 0)
156 return NULL;
157 obstack_1grow (&temporary_obstack, '\0');
158 return (char *) obstack_finish (&temporary_obstack);
161 void
162 init_repo (void)
164 char *buf;
165 const char *p;
166 FILE *repo_file;
168 if (! flag_use_repository)
169 return;
171 /* When a PCH file is loaded, the entire identifier table is
172 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
173 So, we have to reread the repository file. */
174 lang_post_pch_load = init_repo;
176 if (!temporary_obstack_initialized_p)
177 gcc_obstack_init (&temporary_obstack);
179 repo_file = open_repo_file (main_input_filename);
181 if (repo_file == 0)
182 return;
184 while ((buf = afgets (repo_file)))
186 switch (buf[0])
188 case 'A':
189 old_args = ggc_strdup (buf + 2);
190 break;
191 case 'D':
192 old_dir = ggc_strdup (buf + 2);
193 break;
194 case 'M':
195 old_main = ggc_strdup (buf + 2);
196 break;
197 case 'O':
198 /* A symbol that we were able to define the last time this
199 file was compiled. */
200 break;
201 case 'C':
202 /* A symbol that the prelinker has requested that we
203 define. */
205 tree id = get_identifier (buf + 2);
206 IDENTIFIER_REPO_CHOSEN (id) = 1;
208 break;
209 default:
210 error ("mysterious repository information in %s", repo_name);
212 obstack_free (&temporary_obstack, buf);
214 fclose (repo_file);
216 if (old_args && !get_random_seed (true)
217 && (p = strstr (old_args, "'-frandom-seed=")))
218 set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
221 static FILE *
222 reopen_repo_file_for_write (void)
224 FILE *repo_file = fopen (repo_name, "w");
226 if (repo_file == 0)
228 error ("can%'t create repository information file %qs", repo_name);
229 flag_use_repository = 0;
232 return repo_file;
235 /* Emit any pending repos. */
237 void
238 finish_repo (void)
240 tree val;
241 char *dir, *args;
242 FILE *repo_file;
243 unsigned ix;
245 if (!flag_use_repository || flag_compare_debug)
246 return;
248 if (seen_error ())
249 return;
251 repo_file = reopen_repo_file_for_write ();
252 if (repo_file == 0)
253 goto out;
255 fprintf (repo_file, "M %s\n", main_input_filename);
256 dir = getpwd ();
257 fprintf (repo_file, "D %s\n", dir);
258 args = getenv ("COLLECT_GCC_OPTIONS");
259 if (args)
261 fprintf (repo_file, "A %s", args);
262 /* If -frandom-seed is not among the ARGS, then add the value
263 that we chose. That will ensure that the names of types from
264 anonymous namespaces will get the same mangling when this
265 file is recompiled. */
266 if (!strstr (args, "'-frandom-seed="))
267 fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'",
268 get_random_seed (false));
269 fprintf (repo_file, "\n");
272 FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo, ix, val)
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));
279 out:
280 if (repo_file)
281 fclose (repo_file);
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. */
292 repo_emit_p (tree decl)
294 int ret = 0;
295 gcc_assert (TREE_PUBLIC (decl));
296 gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
297 gcc_assert (!DECL_REALLY_EXTERN (decl)
298 /* A clone might not have its linkage flags updated yet
299 because we call import_export_decl before
300 maybe_clone_body. */
301 || DECL_ABSTRACT_ORIGIN (decl));
303 /* When not using the repository, emit everything. */
304 if (!flag_use_repository)
305 return 2;
307 /* Only template instantiations are managed by the repository. This
308 is an artificial restriction; the code in the prelinker and here
309 will work fine if all entities with vague linkage are managed by
310 the repository. */
311 if (VAR_P (decl))
313 tree type = NULL_TREE;
314 if (DECL_VTABLE_OR_VTT_P (decl))
315 type = DECL_CONTEXT (decl);
316 else if (DECL_TINFO_P (decl))
317 type = TREE_TYPE (DECL_NAME (decl));
318 if (!DECL_TEMPLATE_INSTANTIATION (decl)
319 && (!TYPE_LANG_SPECIFIC (type)
320 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
321 return 2;
322 /* Const static data members initialized by constant expressions must
323 be processed where needed so that their definitions are
324 available. Still record them into *.rpo files, so if they
325 weren't actually emitted and collect2 requests them, they can
326 be provided. */
327 if (decl_maybe_constant_var_p (decl)
328 && DECL_CLASS_SCOPE_P (decl))
329 ret = 2;
331 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
332 return 2;
334 if (DECL_EXPLICIT_INSTANTIATION (decl))
335 return 2;
337 /* For constructors and destructors, the repository contains
338 information about the clones -- not the original function --
339 because only the clones are emitted in the object file. */
340 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
341 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
343 int emit_p = 0;
344 tree clone;
345 /* There is no early exit from this loop because we want to
346 ensure that all of the clones are marked as available in this
347 object file. */
348 FOR_EACH_CLONE (clone, decl)
349 /* The only possible results from the recursive call to
350 repo_emit_p are 0 or 1. */
351 if (repo_emit_p (clone))
352 emit_p = 1;
353 return emit_p;
356 /* Keep track of all available entities. */
357 if (!DECL_REPO_AVAILABLE_P (decl))
359 DECL_REPO_AVAILABLE_P (decl) = 1;
360 vec_safe_push (pending_repo, decl);
363 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
366 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
367 export from this translation unit. */
369 bool
370 repo_export_class_p (const_tree class_type)
372 if (!flag_use_repository)
373 return false;
374 if (!CLASSTYPE_VTABLES (class_type))
375 return false;
376 /* If the virtual table has been assigned to this translation unit,
377 export the class. */
378 return (IDENTIFIER_REPO_CHOSEN
379 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
382 #include "gt-cp-repo.h"