gcc41 removal: Part 1 of 2: makefiles
[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 FILE *open_repo_file (const char *);
44 static char *afgets (FILE *);
45 static FILE *reopen_repo_file_for_write (void);
46
47 static GTY(()) tree pending_repo;
48 static char *repo_name;
49
50 static const char *old_args, *old_dir, *old_main;
51
52 static struct obstack temporary_obstack;
53 static bool temporary_obstack_initialized_p;
54
55 /* Parse a reasonable subset of shell quoting syntax.  */
56
57 static char *
58 extract_string (char **pp)
59 {
60   char *p = *pp;
61   int backquote = 0;
62   int inside = 0;
63
64   for (;;)
65     {
66       char c = *p;
67       if (c == '\0')
68         break;
69       ++p;
70       if (backquote)
71         {
72           obstack_1grow (&temporary_obstack, c);
73           backquote = 0;
74         }
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);
83     }
84
85   obstack_1grow (&temporary_obstack, '\0');
86   *pp = p;
87   return obstack_finish (&temporary_obstack);
88 }
89
90 static const char *
91 get_base_filename (const char *filename)
92 {
93   char *p = getenv ("COLLECT_GCC_OPTIONS");
94   char *output = NULL;
95   int compiling = 0;
96
97   while (p && *p)
98     {
99       char *q = extract_string (&p);
100
101       if (strcmp (q, "-o") == 0)
102         output = extract_string (&p);
103       else if (strcmp (q, "-c") == 0)
104         compiling = 1;
105     }
106
107   if (compiling && output)
108     return output;
109
110   if (p && ! compiling)
111     {
112       warning (0, "-frepo must be used with -c");
113       flag_use_repository = 0;
114       return NULL;
115     }
116
117   return lbasename (filename);
118 }
119
120 static FILE *
121 open_repo_file (const char *filename)
122 {
123   const char *p;
124   const char *s = get_base_filename (filename);
125
126   if (s == NULL)
127     return NULL;
128
129   p = lbasename (s);
130   p = strrchr (p, '.');
131   if (! p)
132     p = s + strlen (s);
133
134   repo_name = xmalloc (p - s + 5);
135   memcpy (repo_name, s, p - s);
136   memcpy (repo_name + (p - s), ".rpo", 5);
137
138   return fopen (repo_name, "r");
139 }
140
141 static char *
142 afgets (FILE *stream)
143 {
144   int c;
145   while ((c = getc (stream)) != EOF && c != '\n')
146     obstack_1grow (&temporary_obstack, c);
147   if (obstack_object_size (&temporary_obstack) == 0)
148     return NULL;
149   obstack_1grow (&temporary_obstack, '\0');
150   return obstack_finish (&temporary_obstack);
151 }
152
153 void
154 init_repo (void)
155 {
156   char *buf;
157   FILE *repo_file;
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   repo_file = 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 FILE *
209 reopen_repo_file_for_write (void)
210 {
211   FILE *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   return repo_file;
220 }
221
222 /* Emit any pending repos.  */
223
224 void
225 finish_repo (void)
226 {
227   tree t;
228   char *dir, *args;
229   FILE *repo_file;
230
231   if (!flag_use_repository)
232     return;
233
234   if (errorcount || sorrycount)
235     return;
236
237   repo_file = reopen_repo_file_for_write ();
238   if (repo_file == 0)
239     goto out;
240
241   fprintf (repo_file, "M %s\n", main_input_filename);
242   dir = getpwd ();
243   fprintf (repo_file, "D %s\n", dir);
244   args = getenv ("COLLECT_GCC_OPTIONS");
245   if (args)
246     {
247       fprintf (repo_file, "A %s", args);
248       /* If -frandom-seed is not among the ARGS, then add the value
249          that we chose.  That will ensure that the names of types from
250          anonymous namespaces will get the same mangling when this
251          file is recompiled.  */
252       if (!strstr (args, "'-frandom-seed="))
253         fprintf (repo_file, " '-frandom-seed=%s'", flag_random_seed);
254       fprintf (repo_file, "\n");
255     }
256
257   for (t = pending_repo; t; t = TREE_CHAIN (t))
258     {
259       tree val = TREE_VALUE (t);
260       tree name = DECL_ASSEMBLER_NAME (val);
261       char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
262       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
263     }
264
265  out:
266   if (repo_file)
267     fclose (repo_file);
268 }
269
270 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
271    definition is available in this translation unit.  Returns 0 if
272    this definition should not be emitted in this translation unit
273    because it will be emitted elsewhere.  Returns 1 if the repository
274    file indicates that that DECL should be emitted in this translation
275    unit, or 2 if the repository file is not in use.  */
276
277 int
278 repo_emit_p (tree decl)
279 {
280   gcc_assert (TREE_PUBLIC (decl));
281   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
282               || TREE_CODE (decl) == VAR_DECL);
283   gcc_assert (!DECL_REALLY_EXTERN (decl));
284
285   /* When not using the repository, emit everything.  */
286   if (!flag_use_repository)
287     return 2;
288
289   /* Only template instantiations are managed by the repository.  This
290      is an artificial restriction; the code in the prelinker and here
291      will work fine if all entities with vague linkage are managed by
292      the repository.  */
293   if (TREE_CODE (decl) == VAR_DECL)
294     {
295       tree type = NULL_TREE;
296       if (DECL_VTABLE_OR_VTT_P (decl))
297         type = DECL_CONTEXT (decl);
298       else if (DECL_TINFO_P (decl))
299         type = TREE_TYPE (DECL_NAME (decl));
300       if (!DECL_TEMPLATE_INSTANTIATION (decl)
301           && (!TYPE_LANG_SPECIFIC (type)
302               || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
303         return 2;
304       /* Static data members initialized by constant expressions must
305          be processed where needed so that their definitions are
306          available.  */
307       if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
308           && DECL_CLASS_SCOPE_P (decl))
309         return 2;
310     }
311   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
312     return 2;
313
314   /* For constructors and destructors, the repository contains
315      information about the clones -- not the original function --
316      because only the clones are emitted in the object file.  */
317   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
318       || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
319     {
320       int emit_p = 0;
321       tree clone;
322       /* There is no early exit from this loop because we want to
323          ensure that all of the clones are marked as available in this
324          object file.  */
325       FOR_EACH_CLONE (clone, decl)
326         /* The only possible results from the recursive call to
327            repo_emit_p are 0 or 1.  */
328         if (repo_emit_p (clone))
329           emit_p = 1;
330       return emit_p;
331     }
332
333   /* Keep track of all available entities.  */
334   if (!DECL_REPO_AVAILABLE_P (decl))
335     {
336       DECL_REPO_AVAILABLE_P (decl) = 1;
337       pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
338     }
339
340   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
341 }
342
343 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
344    export from this translation unit.  */
345
346 bool
347 repo_export_class_p (tree class_type)
348 {
349   if (!flag_use_repository)
350     return false;
351   if (!CLASSTYPE_VTABLES (class_type))
352     return false;
353   /* If the virtual table has been assigned to this translation unit,
354      export the class.  */
355   return (IDENTIFIER_REPO_CHOSEN
356           (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
357 }
358
359 #include "gt-cp-repo.h"