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 Free Software Foundation, Inc.
4 Contributed by Jason Merrill (jason@cygnus.com)
6 This file is part of GCC.
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)
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.
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/>. */
22 /* My strategy here is as follows:
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
30 #include "coretypes.h"
37 #include "diagnostic.h"
40 static char *extract_string (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);
46 static GTY(()) tree pending_repo;
47 static char *repo_name;
49 static const char *old_args, *old_dir, *old_main;
51 static struct obstack temporary_obstack;
52 static bool temporary_obstack_initialized_p;
54 /* Parse a reasonable subset of shell quoting syntax. */
57 extract_string (char **pp)
71 obstack_1grow (&temporary_obstack, c);
74 else if (! inside && c == ' ')
76 else if (! inside && c == '\\')
81 obstack_1grow (&temporary_obstack, c);
84 obstack_1grow (&temporary_obstack, '\0');
86 return (char *) obstack_finish (&temporary_obstack);
90 get_base_filename (const char *filename)
92 char *p = getenv ("COLLECT_GCC_OPTIONS");
93 const char *output = NULL;
98 char *q = extract_string (&p);
100 if (strcmp (q, "-o") == 0)
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);
108 output = extract_string (&p);
110 else if (strcmp (q, "-c") == 0)
114 if (compiling && output)
117 if (p && ! compiling)
119 warning (0, "-frepo must be used with -c");
120 flag_use_repository = 0;
124 return lbasename (filename);
128 open_repo_file (const char *filename)
131 const char *s = get_base_filename (filename);
137 p = strrchr (p, '.');
141 repo_name = XNEWVEC (char, p - s + 5);
142 memcpy (repo_name, s, p - s);
143 memcpy (repo_name + (p - s), ".rpo", 5);
145 return fopen (repo_name, "r");
149 afgets (FILE *stream)
152 while ((c = getc (stream)) != EOF && c != '\n')
153 obstack_1grow (&temporary_obstack, c);
154 if (obstack_object_size (&temporary_obstack) == 0)
156 obstack_1grow (&temporary_obstack, '\0');
157 return (char *) obstack_finish (&temporary_obstack);
166 if (! flag_use_repository)
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);
182 while ((buf = afgets (repo_file)))
187 old_args = ggc_strdup (buf + 2);
190 old_dir = ggc_strdup (buf + 2);
193 old_main = ggc_strdup (buf + 2);
196 /* A symbol that we were able to define the last time this
197 file was compiled. */
200 /* A symbol that the prelinker has requested that we
203 tree id = get_identifier (buf + 2);
204 IDENTIFIER_REPO_CHOSEN (id) = 1;
208 error ("mysterious repository information in %s", repo_name);
210 obstack_free (&temporary_obstack, buf);
214 if (old_args && !get_random_seed (true)
215 && (buf = strstr (old_args, "'-frandom-seed=")))
216 set_random_seed (extract_string (&buf) + strlen ("-frandom-seed="));
220 reopen_repo_file_for_write (void)
222 FILE *repo_file = fopen (repo_name, "w");
226 error ("can't create repository information file %qs", repo_name);
227 flag_use_repository = 0;
233 /* Emit any pending repos. */
242 if (!flag_use_repository || flag_compare_debug)
245 if (errorcount || sorrycount)
248 repo_file = reopen_repo_file_for_write ();
252 fprintf (repo_file, "M %s\n", main_input_filename);
254 fprintf (repo_file, "D %s\n", dir);
255 args = getenv ("COLLECT_GCC_OPTIONS");
258 fprintf (repo_file, "A %s", args);
259 /* If -frandom-seed is not among the ARGS, then add the value
260 that we chose. That will ensure that the names of types from
261 anonymous namespaces will get the same mangling when this
262 file is recompiled. */
263 if (!strstr (args, "'-frandom-seed="))
264 fprintf (repo_file, " '-frandom-seed=%s'", get_random_seed (false));
265 fprintf (repo_file, "\n");
268 for (t = pending_repo; t; t = TREE_CHAIN (t))
270 tree val = TREE_VALUE (t);
271 tree name = DECL_ASSEMBLER_NAME (val);
272 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
273 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
281 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
282 definition is available in this translation unit. Returns 0 if
283 this definition should not be emitted in this translation unit
284 because it will be emitted elsewhere. Returns 1 if the repository
285 file indicates that that DECL should be emitted in this translation
286 unit, or 2 if the repository file is not in use. */
289 repo_emit_p (tree decl)
292 gcc_assert (TREE_PUBLIC (decl));
293 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
294 || TREE_CODE (decl) == VAR_DECL);
295 gcc_assert (!DECL_REALLY_EXTERN (decl));
297 /* When not using the repository, emit everything. */
298 if (!flag_use_repository)
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
305 if (TREE_CODE (decl) == VAR_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)))
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
321 if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
322 && DECL_CLASS_SCOPE_P (decl))
325 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
328 if (DECL_EXPLICIT_INSTANTIATION (decl))
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))
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
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))
350 /* Keep track of all available entities. */
351 if (!DECL_REPO_AVAILABLE_P (decl))
353 DECL_REPO_AVAILABLE_P (decl) = 1;
354 pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
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. */
364 repo_export_class_p (const_tree class_type)
366 if (!flag_use_repository)
368 if (!CLASSTYPE_VTABLES (class_type))
370 /* If the virtual table has been assigned to this translation unit,
372 return (IDENTIFIER_REPO_CHOSEN
373 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
376 #include "gt-cp-repo.h"