Import a stripped down version of gcc-4.1.1
[dragonfly.git] / contrib / gcc-4.1 / gcc / cp / repo.c
1 /* Code to maintain a C++ template repository.
2    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
3    Free Software Foundation, Inc.
4    Contributed by Jason Merrill (jason@cygnus.com)
5
6 This file is part of GCC.
7
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 2, or (at your option)
11 any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.  */
22
23 /* My strategy here is as follows:
24
25    Everything should be emitted in a translation unit where it is used.
26    The results of the automatic process should be easily reproducible with
27    explicit code.  */
28
29 #include "config.h"
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "tree.h"
34 #include "cp-tree.h"
35 #include "input.h"
36 #include "obstack.h"
37 #include "toplev.h"
38 #include "diagnostic.h"
39 #include "flags.h"
40
41 static char *extract_string (char **);
42 static const char *get_base_filename (const char *);
43 static void open_repo_file (const char *);
44 static char *afgets (FILE *);
45 static void reopen_repo_file_for_write (void);
46
47 static GTY(()) tree pending_repo;
48 static char *repo_name;
49 static FILE *repo_file;
50
51 static const char *old_args, *old_dir, *old_main;
52
53 static struct obstack temporary_obstack;
54 static bool temporary_obstack_initialized_p;
55
56 /* Parse a reasonable subset of shell quoting syntax.  */
57
58 static char *
59 extract_string (char **pp)
60 {
61   char *p = *pp;
62   int backquote = 0;
63   int inside = 0;
64
65   for (;;)
66     {
67       char c = *p;
68       if (c == '\0')
69         break;
70       ++p;
71       if (backquote)
72         {
73           obstack_1grow (&temporary_obstack, c);
74           backquote = 0;
75         }
76       else if (! inside && c == ' ')
77         break;
78       else if (! inside && c == '\\')
79         backquote = 1;
80       else if (c == '\'')
81         inside = !inside;
82       else
83         obstack_1grow (&temporary_obstack, c);
84     }
85
86   obstack_1grow (&temporary_obstack, '\0');
87   *pp = p;
88   return obstack_finish (&temporary_obstack);
89 }
90
91 static const char *
92 get_base_filename (const char *filename)
93 {
94   char *p = getenv ("COLLECT_GCC_OPTIONS");
95   char *output = NULL;
96   int compiling = 0;
97
98   while (p && *p)
99     {
100       char *q = extract_string (&p);
101
102       if (strcmp (q, "-o") == 0)
103         output = extract_string (&p);
104       else if (strcmp (q, "-c") == 0)
105         compiling = 1;
106     }
107
108   if (compiling && output)
109     return output;
110
111   if (p && ! compiling)
112     {
113       warning (0, "-frepo must be used with -c");
114       flag_use_repository = 0;
115       return NULL;
116     }
117
118   return lbasename (filename);
119 }
120
121 static void
122 open_repo_file (const char *filename)
123 {
124   const char *p;
125   const char *s = get_base_filename (filename);
126
127   if (s == NULL)
128     return;
129
130   p = lbasename (s);
131   p = strrchr (p, '.');
132   if (! p)
133     p = s + strlen (s);
134
135   repo_name = xmalloc (p - s + 5);
136   memcpy (repo_name, s, p - s);
137   memcpy (repo_name + (p - s), ".rpo", 5);
138
139   repo_file = fopen (repo_name, "r");
140 }
141
142 static char *
143 afgets (FILE *stream)
144 {
145   int c;
146   while ((c = getc (stream)) != EOF && c != '\n')
147     obstack_1grow (&temporary_obstack, c);
148   if (obstack_object_size (&temporary_obstack) == 0)
149     return NULL;
150   obstack_1grow (&temporary_obstack, '\0');
151   return obstack_finish (&temporary_obstack);
152 }
153
154 void
155 init_repo (void)
156 {
157   char *buf;
158
159   if (! flag_use_repository)
160     return;
161
162   /* When a PCH file is loaded, the entire identifier table is
163      replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
164      So, we have to reread the repository file.  */
165   lang_post_pch_load = init_repo;
166
167   if (!temporary_obstack_initialized_p)
168     gcc_obstack_init (&temporary_obstack);
169
170   open_repo_file (main_input_filename);
171
172   if (repo_file == 0)
173     return;
174
175   while ((buf = afgets (repo_file)))
176     {
177       switch (buf[0])
178         {
179         case 'A':
180           old_args = ggc_strdup (buf + 2);
181           break;
182         case 'D':
183           old_dir = ggc_strdup (buf + 2);
184           break;
185         case 'M':
186           old_main = ggc_strdup (buf + 2);
187           break;
188         case 'O':
189           /* A symbol that we were able to define the last time this
190              file was compiled.  */
191           break;
192         case 'C':
193           /* A symbol that the prelinker has requested that we
194              define.  */
195           {
196             tree id = get_identifier (buf + 2);
197             IDENTIFIER_REPO_CHOSEN (id) = 1;
198           }
199           break;
200         default:
201           error ("mysterious repository information in %s", repo_name);
202         }
203       obstack_free (&temporary_obstack, buf);
204     }
205   fclose (repo_file);
206 }
207
208 static void
209 reopen_repo_file_for_write (void)
210 {
211   repo_file = fopen (repo_name, "w");
212
213   if (repo_file == 0)
214     {
215       error ("can't create repository information file %qs", repo_name);
216       flag_use_repository = 0;
217     }
218 }
219
220 /* Emit any pending repos.  */
221
222 void
223 finish_repo (void)
224 {
225   tree t;
226   char *dir, *args;
227
228   if (!flag_use_repository)
229     return;
230
231   if (errorcount || sorrycount)
232     goto out;
233
234   reopen_repo_file_for_write ();
235   if (repo_file == 0)
236     goto out;
237
238   fprintf (repo_file, "M %s\n", main_input_filename);
239   dir = getpwd ();
240   fprintf (repo_file, "D %s\n", dir);
241   args = getenv ("COLLECT_GCC_OPTIONS");
242   if (args)
243     {
244       fprintf (repo_file, "A %s", args);
245       /* If -frandom-seed is not among the ARGS, then add the value
246          that we chose.  That will ensure that the names of types from
247          anonymous namespaces will get the same mangling when this
248          file is recompiled.  */
249       if (!strstr (args, "'-frandom-seed="))
250         fprintf (repo_file, " '-frandom-seed=%s'", flag_random_seed);
251       fprintf (repo_file, "\n");
252     }
253
254   for (t = pending_repo; t; t = TREE_CHAIN (t))
255     {
256       tree val = TREE_VALUE (t);
257       tree name = DECL_ASSEMBLER_NAME (val);
258       char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
259       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
260     }
261
262  out:
263   if (repo_file)
264     fclose (repo_file);
265 }
266
267 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
268    definition is available in this translation unit.  Returns 0 if
269    this definition should not be emitted in this translation unit
270    because it will be emitted elsewhere.  Returns 1 if the repository
271    file indicates that that DECL should be emitted in this translation
272    unit, or 2 if the repository file is not in use.  */
273
274 int
275 repo_emit_p (tree decl)
276 {
277   gcc_assert (TREE_PUBLIC (decl));
278   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
279               || TREE_CODE (decl) == VAR_DECL);
280   gcc_assert (!DECL_REALLY_EXTERN (decl));
281
282   /* When not using the repository, emit everything.  */
283   if (!flag_use_repository)
284     return 2;
285
286   /* Only template instantiations are managed by the repository.  This
287      is an artificial restriction; the code in the prelinker and here
288      will work fine if all entities with vague linkage are managed by
289      the repository.  */
290   if (TREE_CODE (decl) == VAR_DECL)
291     {
292       tree type = NULL_TREE;
293       if (DECL_VTABLE_OR_VTT_P (decl))
294         type = DECL_CONTEXT (decl);
295       else if (DECL_TINFO_P (decl))
296         type = TREE_TYPE (DECL_NAME (decl));
297       if (!DECL_TEMPLATE_INSTANTIATION (decl)
298           && (!TYPE_LANG_SPECIFIC (type)
299               || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
300         return 2;
301       /* Static data members initialized by constant expressions must
302          be processed where needed so that their definitions are
303          available.  */
304       if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
305           && DECL_CLASS_SCOPE_P (decl))
306         return 2;
307     }
308   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
309     return 2;
310
311   /* For constructors and destructors, the repository contains
312      information about the clones -- not the original function --
313      because only the clones are emitted in the object file.  */
314   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
315       || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
316     {
317       int emit_p = 0;
318       tree clone;
319       /* There is no early exit from this loop because we want to
320          ensure that all of the clones are marked as available in this
321          object file.  */
322       FOR_EACH_CLONE (clone, decl)
323         /* The only possible results from the recursive call to
324            repo_emit_p are 0 or 1.  */
325         if (repo_emit_p (clone))
326           emit_p = 1;
327       return emit_p;
328     }
329
330   /* Keep track of all available entities.  */
331   if (!DECL_REPO_AVAILABLE_P (decl))
332     {
333       DECL_REPO_AVAILABLE_P (decl) = 1;
334       pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
335     }
336
337   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
338 }
339
340 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
341    export from this translation unit.  */
342
343 bool
344 repo_export_class_p (tree class_type)
345 {
346   if (!flag_use_repository)
347     return false;
348   if (!CLASSTYPE_VTABLES (class_type))
349     return false;
350   /* If the virtual table has been assigned to this translation unit,
351      export the class.  */
352   return (IDENTIFIER_REPO_CHOSEN
353           (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
354 }
355
356 #include "gt-cp-repo.h"