Import gcc-4.4.1
[dragonfly.git] / contrib / gcc-4.4 / gcc / cp / repo.c
blob4501ba88a9dec6e054a2e6598d8fd070234a09cd
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)
11 any later version.
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
26 explicit code. */
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.h"
38 #include "flags.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. */
56 static char *
57 extract_string (char **pp)
59 char *p = *pp;
60 int backquote = 0;
61 int inside = 0;
63 for (;;)
65 char c = *p;
66 if (c == '\0')
67 break;
68 ++p;
69 if (backquote)
71 obstack_1grow (&temporary_obstack, c);
72 backquote = 0;
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);
84 obstack_1grow (&temporary_obstack, '\0');
85 *pp = p;
86 return (char *) obstack_finish (&temporary_obstack);
89 static const char *
90 get_base_filename (const char *filename)
92 char *p = getenv ("COLLECT_GCC_OPTIONS");
93 char *output = NULL;
94 int compiling = 0;
96 while (p && *p)
98 char *q = extract_string (&p);
100 if (strcmp (q, "-o") == 0)
101 output = extract_string (&p);
102 else if (strcmp (q, "-c") == 0)
103 compiling = 1;
106 if (compiling && output)
107 return output;
109 if (p && ! compiling)
111 warning (0, "-frepo must be used with -c");
112 flag_use_repository = 0;
113 return NULL;
116 return lbasename (filename);
119 static FILE *
120 open_repo_file (const char *filename)
122 const char *p;
123 const char *s = get_base_filename (filename);
125 if (s == NULL)
126 return NULL;
128 p = lbasename (s);
129 p = strrchr (p, '.');
130 if (! p)
131 p = s + strlen (s);
133 repo_name = XNEWVEC (char, p - s + 5);
134 memcpy (repo_name, s, p - s);
135 memcpy (repo_name + (p - s), ".rpo", 5);
137 return fopen (repo_name, "r");
140 static char *
141 afgets (FILE *stream)
143 int c;
144 while ((c = getc (stream)) != EOF && c != '\n')
145 obstack_1grow (&temporary_obstack, c);
146 if (obstack_object_size (&temporary_obstack) == 0)
147 return NULL;
148 obstack_1grow (&temporary_obstack, '\0');
149 return (char *) obstack_finish (&temporary_obstack);
152 void
153 init_repo (void)
155 char *buf;
156 FILE *repo_file;
158 if (! flag_use_repository)
159 return;
161 /* When a PCH file is loaded, the entire identifier table is
162 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
163 So, we have to reread the repository file. */
164 lang_post_pch_load = init_repo;
166 if (!temporary_obstack_initialized_p)
167 gcc_obstack_init (&temporary_obstack);
169 repo_file = open_repo_file (main_input_filename);
171 if (repo_file == 0)
172 return;
174 while ((buf = afgets (repo_file)))
176 switch (buf[0])
178 case 'A':
179 old_args = ggc_strdup (buf + 2);
180 break;
181 case 'D':
182 old_dir = ggc_strdup (buf + 2);
183 break;
184 case 'M':
185 old_main = ggc_strdup (buf + 2);
186 break;
187 case 'O':
188 /* A symbol that we were able to define the last time this
189 file was compiled. */
190 break;
191 case 'C':
192 /* A symbol that the prelinker has requested that we
193 define. */
195 tree id = get_identifier (buf + 2);
196 IDENTIFIER_REPO_CHOSEN (id) = 1;
198 break;
199 default:
200 error ("mysterious repository information in %s", repo_name);
202 obstack_free (&temporary_obstack, buf);
204 fclose (repo_file);
206 if (old_args && !get_random_seed (true)
207 && (buf = strstr (old_args, "'-frandom-seed=")))
208 set_random_seed (extract_string (&buf) + strlen ("-frandom-seed="));
211 static FILE *
212 reopen_repo_file_for_write (void)
214 FILE *repo_file = fopen (repo_name, "w");
216 if (repo_file == 0)
218 error ("can't create repository information file %qs", repo_name);
219 flag_use_repository = 0;
222 return repo_file;
225 /* Emit any pending repos. */
227 void
228 finish_repo (void)
230 tree t;
231 char *dir, *args;
232 FILE *repo_file;
234 if (!flag_use_repository)
235 return;
237 if (errorcount || sorrycount)
238 return;
240 repo_file = reopen_repo_file_for_write ();
241 if (repo_file == 0)
242 goto out;
244 fprintf (repo_file, "M %s\n", main_input_filename);
245 dir = getpwd ();
246 fprintf (repo_file, "D %s\n", dir);
247 args = getenv ("COLLECT_GCC_OPTIONS");
248 if (args)
250 fprintf (repo_file, "A %s", args);
251 /* If -frandom-seed is not among the ARGS, then add the value
252 that we chose. That will ensure that the names of types from
253 anonymous namespaces will get the same mangling when this
254 file is recompiled. */
255 if (!strstr (args, "'-frandom-seed="))
256 fprintf (repo_file, " '-frandom-seed=%s'", get_random_seed (false));
257 fprintf (repo_file, "\n");
260 for (t = pending_repo; t; t = TREE_CHAIN (t))
262 tree val = TREE_VALUE (t);
263 tree name = DECL_ASSEMBLER_NAME (val);
264 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
265 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
268 out:
269 if (repo_file)
270 fclose (repo_file);
273 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
274 definition is available in this translation unit. Returns 0 if
275 this definition should not be emitted in this translation unit
276 because it will be emitted elsewhere. Returns 1 if the repository
277 file indicates that that DECL should be emitted in this translation
278 unit, or 2 if the repository file is not in use. */
281 repo_emit_p (tree decl)
283 int ret = 0;
284 gcc_assert (TREE_PUBLIC (decl));
285 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
286 || TREE_CODE (decl) == VAR_DECL);
287 gcc_assert (!DECL_REALLY_EXTERN (decl));
289 /* When not using the repository, emit everything. */
290 if (!flag_use_repository)
291 return 2;
293 /* Only template instantiations are managed by the repository. This
294 is an artificial restriction; the code in the prelinker and here
295 will work fine if all entities with vague linkage are managed by
296 the repository. */
297 if (TREE_CODE (decl) == VAR_DECL)
299 tree type = NULL_TREE;
300 if (DECL_VTABLE_OR_VTT_P (decl))
301 type = DECL_CONTEXT (decl);
302 else if (DECL_TINFO_P (decl))
303 type = TREE_TYPE (DECL_NAME (decl));
304 if (!DECL_TEMPLATE_INSTANTIATION (decl)
305 && (!TYPE_LANG_SPECIFIC (type)
306 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
307 return 2;
308 /* Const static data members initialized by constant expressions must
309 be processed where needed so that their definitions are
310 available. Still record them into *.rpo files, so if they
311 weren't actually emitted and collect2 requests them, they can
312 be provided. */
313 if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
314 && DECL_CLASS_SCOPE_P (decl))
315 ret = 2;
317 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
318 return 2;
320 if (DECL_EXPLICIT_INSTANTIATION (decl))
321 return 2;
323 /* For constructors and destructors, the repository contains
324 information about the clones -- not the original function --
325 because only the clones are emitted in the object file. */
326 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
327 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
329 int emit_p = 0;
330 tree clone;
331 /* There is no early exit from this loop because we want to
332 ensure that all of the clones are marked as available in this
333 object file. */
334 FOR_EACH_CLONE (clone, decl)
335 /* The only possible results from the recursive call to
336 repo_emit_p are 0 or 1. */
337 if (repo_emit_p (clone))
338 emit_p = 1;
339 return emit_p;
342 /* Keep track of all available entities. */
343 if (!DECL_REPO_AVAILABLE_P (decl))
345 DECL_REPO_AVAILABLE_P (decl) = 1;
346 pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
349 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
352 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
353 export from this translation unit. */
355 bool
356 repo_export_class_p (const_tree class_type)
358 if (!flag_use_repository)
359 return false;
360 if (!CLASSTYPE_VTABLES (class_type))
361 return false;
362 /* If the virtual table has been assigned to this translation unit,
363 export the class. */
364 return (IDENTIFIER_REPO_CHOSEN
365 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
368 #include "gt-cp-repo.h"