/cp
[official-gcc.git] / gcc / cp / repo.c
blob7b6f7b8ce1bd557e0bd7a6a6329096e918765c1c
1 /* Code to maintain a C++ template repository.
2 Copyright (C) 1995-2013 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 "tree.h"
32 #include "cp-tree.h"
33 #include "input.h"
34 #include "obstack.h"
35 #include "toplev.h"
36 #include "diagnostic-core.h"
37 #include "flags.h"
39 static const char *extract_string (const char **);
40 static const char *get_base_filename (const char *);
41 static FILE *open_repo_file (const char *);
42 static char *afgets (FILE *);
43 static FILE *reopen_repo_file_for_write (void);
45 static GTY(()) vec<tree, va_gc> *pending_repo;
46 static char *repo_name;
48 static const char *old_args, *old_dir, *old_main;
50 static struct obstack temporary_obstack;
51 static bool temporary_obstack_initialized_p;
53 /* Parse a reasonable subset of shell quoting syntax. */
55 static const char *
56 extract_string (const char **pp)
58 const char *p = *pp;
59 int backquote = 0;
60 int inside = 0;
62 for (;;)
64 char c = *p;
65 if (c == '\0')
66 break;
67 ++p;
68 if (backquote)
70 obstack_1grow (&temporary_obstack, c);
71 backquote = 0;
73 else if (! inside && c == ' ')
74 break;
75 else if (! inside && c == '\\')
76 backquote = 1;
77 else if (c == '\'')
78 inside = !inside;
79 else
80 obstack_1grow (&temporary_obstack, c);
83 obstack_1grow (&temporary_obstack, '\0');
84 *pp = p;
85 return (char *) obstack_finish (&temporary_obstack);
88 static const char *
89 get_base_filename (const char *filename)
91 const char *p = getenv ("COLLECT_GCC_OPTIONS");
92 const char *output = NULL;
93 int compiling = 0;
95 while (p && *p)
97 const char *q = extract_string (&p);
99 if (strcmp (q, "-o") == 0)
101 if (flag_compare_debug)
102 /* Just in case aux_base_name was based on a name with two
103 or more '.'s, add an arbitrary extension that will be
104 stripped by the caller. */
105 output = concat (aux_base_name, ".o", NULL);
106 else
107 output = extract_string (&p);
109 else if (strcmp (q, "-c") == 0)
110 compiling = 1;
113 if (compiling && output)
114 return output;
116 if (p && ! compiling)
118 warning (0, "-frepo must be used with -c");
119 flag_use_repository = 0;
120 return NULL;
123 return lbasename (filename);
126 static FILE *
127 open_repo_file (const char *filename)
129 const char *p;
130 const char *s = get_base_filename (filename);
132 if (s == NULL)
133 return NULL;
135 p = lbasename (s);
136 p = strrchr (p, '.');
137 if (! p)
138 p = s + strlen (s);
140 repo_name = XNEWVEC (char, p - s + 5);
141 memcpy (repo_name, s, p - s);
142 memcpy (repo_name + (p - s), ".rpo", 5);
144 return fopen (repo_name, "r");
147 static char *
148 afgets (FILE *stream)
150 int c;
151 while ((c = getc (stream)) != EOF && c != '\n')
152 obstack_1grow (&temporary_obstack, c);
153 if (obstack_object_size (&temporary_obstack) == 0)
154 return NULL;
155 obstack_1grow (&temporary_obstack, '\0');
156 return (char *) obstack_finish (&temporary_obstack);
159 void
160 init_repo (void)
162 char *buf;
163 const char *p;
164 FILE *repo_file;
166 if (! flag_use_repository)
167 return;
169 /* When a PCH file is loaded, the entire identifier table is
170 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
171 So, we have to reread the repository file. */
172 lang_post_pch_load = init_repo;
174 if (!temporary_obstack_initialized_p)
175 gcc_obstack_init (&temporary_obstack);
177 repo_file = open_repo_file (main_input_filename);
179 if (repo_file == 0)
180 return;
182 while ((buf = afgets (repo_file)))
184 switch (buf[0])
186 case 'A':
187 old_args = ggc_strdup (buf + 2);
188 break;
189 case 'D':
190 old_dir = ggc_strdup (buf + 2);
191 break;
192 case 'M':
193 old_main = ggc_strdup (buf + 2);
194 break;
195 case 'O':
196 /* A symbol that we were able to define the last time this
197 file was compiled. */
198 break;
199 case 'C':
200 /* A symbol that the prelinker has requested that we
201 define. */
203 tree id = get_identifier (buf + 2);
204 IDENTIFIER_REPO_CHOSEN (id) = 1;
206 break;
207 default:
208 error ("mysterious repository information in %s", repo_name);
210 obstack_free (&temporary_obstack, buf);
212 fclose (repo_file);
214 if (old_args && !get_random_seed (true)
215 && (p = strstr (old_args, "'-frandom-seed=")))
216 set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
219 static FILE *
220 reopen_repo_file_for_write (void)
222 FILE *repo_file = fopen (repo_name, "w");
224 if (repo_file == 0)
226 error ("can%'t create repository information file %qs", repo_name);
227 flag_use_repository = 0;
230 return repo_file;
233 /* Emit any pending repos. */
235 void
236 finish_repo (void)
238 tree val;
239 char *dir, *args;
240 FILE *repo_file;
241 unsigned ix;
243 if (!flag_use_repository || flag_compare_debug)
244 return;
246 if (seen_error ())
247 return;
249 repo_file = reopen_repo_file_for_write ();
250 if (repo_file == 0)
251 goto out;
253 fprintf (repo_file, "M %s\n", main_input_filename);
254 dir = getpwd ();
255 fprintf (repo_file, "D %s\n", dir);
256 args = getenv ("COLLECT_GCC_OPTIONS");
257 if (args)
259 fprintf (repo_file, "A %s", args);
260 /* If -frandom-seed is not among the ARGS, then add the value
261 that we chose. That will ensure that the names of types from
262 anonymous namespaces will get the same mangling when this
263 file is recompiled. */
264 if (!strstr (args, "'-frandom-seed="))
265 fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'",
266 get_random_seed (false));
267 fprintf (repo_file, "\n");
270 FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo, ix, val)
272 tree name = DECL_ASSEMBLER_NAME (val);
273 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
274 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
277 out:
278 if (repo_file)
279 fclose (repo_file);
282 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
283 definition is available in this translation unit. Returns 0 if
284 this definition should not be emitted in this translation unit
285 because it will be emitted elsewhere. Returns 1 if the repository
286 file indicates that that DECL should be emitted in this translation
287 unit, or 2 if the repository file is not in use. */
290 repo_emit_p (tree decl)
292 int ret = 0;
293 gcc_assert (TREE_PUBLIC (decl));
294 gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
295 gcc_assert (!DECL_REALLY_EXTERN (decl));
297 /* When not using the repository, emit everything. */
298 if (!flag_use_repository)
299 return 2;
301 /* Only template instantiations are managed by the repository. This
302 is an artificial restriction; the code in the prelinker and here
303 will work fine if all entities with vague linkage are managed by
304 the repository. */
305 if (VAR_P (decl))
307 tree type = NULL_TREE;
308 if (DECL_VTABLE_OR_VTT_P (decl))
309 type = DECL_CONTEXT (decl);
310 else if (DECL_TINFO_P (decl))
311 type = TREE_TYPE (DECL_NAME (decl));
312 if (!DECL_TEMPLATE_INSTANTIATION (decl)
313 && (!TYPE_LANG_SPECIFIC (type)
314 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
315 return 2;
316 /* Const static data members initialized by constant expressions must
317 be processed where needed so that their definitions are
318 available. Still record them into *.rpo files, so if they
319 weren't actually emitted and collect2 requests them, they can
320 be provided. */
321 if (decl_maybe_constant_var_p (decl)
322 && DECL_CLASS_SCOPE_P (decl))
323 ret = 2;
325 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
326 return 2;
328 if (DECL_EXPLICIT_INSTANTIATION (decl))
329 return 2;
331 /* For constructors and destructors, the repository contains
332 information about the clones -- not the original function --
333 because only the clones are emitted in the object file. */
334 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
335 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
337 int emit_p = 0;
338 tree clone;
339 /* There is no early exit from this loop because we want to
340 ensure that all of the clones are marked as available in this
341 object file. */
342 FOR_EACH_CLONE (clone, decl)
343 /* The only possible results from the recursive call to
344 repo_emit_p are 0 or 1. */
345 if (repo_emit_p (clone))
346 emit_p = 1;
347 return emit_p;
350 /* Keep track of all available entities. */
351 if (!DECL_REPO_AVAILABLE_P (decl))
353 DECL_REPO_AVAILABLE_P (decl) = 1;
354 vec_safe_push (pending_repo, decl);
357 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
360 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
361 export from this translation unit. */
363 bool
364 repo_export_class_p (const_tree class_type)
366 if (!flag_use_repository)
367 return false;
368 if (!CLASSTYPE_VTABLES (class_type))
369 return false;
370 /* If the virtual table has been assigned to this translation unit,
371 export the class. */
372 return (IDENTIFIER_REPO_CHOSEN
373 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
376 #include "gt-cp-repo.h"