OSDN Git Service

* decl.c (get_atexit_fn_ptr_type): New function.
[pf3gnuchains/gcc-fork.git] / 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    2006, 2007  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 (char *) 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 = XNEWVEC (char, 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 (char *) 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   if (old_args && !get_random_seed (true)
208       && (buf = strstr (old_args, "'-frandom-seed=")))
209     set_random_seed (extract_string (&buf) + strlen ("-frandom-seed="));
210 }
211
212 static FILE *
213 reopen_repo_file_for_write (void)
214 {
215   FILE *repo_file = fopen (repo_name, "w");
216
217   if (repo_file == 0)
218     {
219       error ("can't create repository information file %qs", repo_name);
220       flag_use_repository = 0;
221     }
222
223   return repo_file;
224 }
225
226 /* Emit any pending repos.  */
227
228 void
229 finish_repo (void)
230 {
231   tree t;
232   char *dir, *args;
233   FILE *repo_file;
234
235   if (!flag_use_repository)
236     return;
237
238   if (errorcount || sorrycount)
239     return;
240
241   repo_file = reopen_repo_file_for_write ();
242   if (repo_file == 0)
243     goto out;
244
245   fprintf (repo_file, "M %s\n", main_input_filename);
246   dir = getpwd ();
247   fprintf (repo_file, "D %s\n", dir);
248   args = getenv ("COLLECT_GCC_OPTIONS");
249   if (args)
250     {
251       fprintf (repo_file, "A %s", args);
252       /* If -frandom-seed is not among the ARGS, then add the value
253          that we chose.  That will ensure that the names of types from
254          anonymous namespaces will get the same mangling when this
255          file is recompiled.  */
256       if (!strstr (args, "'-frandom-seed="))
257         fprintf (repo_file, " '-frandom-seed=%s'", get_random_seed (false));
258       fprintf (repo_file, "\n");
259     }
260
261   for (t = pending_repo; t; t = TREE_CHAIN (t))
262     {
263       tree val = TREE_VALUE (t);
264       tree name = DECL_ASSEMBLER_NAME (val);
265       char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
266       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
267     }
268
269  out:
270   if (repo_file)
271     fclose (repo_file);
272 }
273
274 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
275    definition is available in this translation unit.  Returns 0 if
276    this definition should not be emitted in this translation unit
277    because it will be emitted elsewhere.  Returns 1 if the repository
278    file indicates that that DECL should be emitted in this translation
279    unit, or 2 if the repository file is not in use.  */
280
281 int
282 repo_emit_p (tree decl)
283 {
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));
288
289   /* When not using the repository, emit everything.  */
290   if (!flag_use_repository)
291     return 2;
292
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)
298     {
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       /* Static data members initialized by constant expressions must
309          be processed where needed so that their definitions are
310          available.  */
311       if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
312           && DECL_CLASS_SCOPE_P (decl))
313         return 2;
314     }
315   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
316     return 2;
317
318   /* For constructors and destructors, the repository contains
319      information about the clones -- not the original function --
320      because only the clones are emitted in the object file.  */
321   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
322       || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
323     {
324       int emit_p = 0;
325       tree clone;
326       /* There is no early exit from this loop because we want to
327          ensure that all of the clones are marked as available in this
328          object file.  */
329       FOR_EACH_CLONE (clone, decl)
330         /* The only possible results from the recursive call to
331            repo_emit_p are 0 or 1.  */
332         if (repo_emit_p (clone))
333           emit_p = 1;
334       return emit_p;
335     }
336
337   /* Keep track of all available entities.  */
338   if (!DECL_REPO_AVAILABLE_P (decl))
339     {
340       DECL_REPO_AVAILABLE_P (decl) = 1;
341       pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
342     }
343
344   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
345 }
346
347 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
348    export from this translation unit.  */
349
350 bool
351 repo_export_class_p (tree class_type)
352 {
353   if (!flag_use_repository)
354     return false;
355   if (!CLASSTYPE_VTABLES (class_type))
356     return false;
357   /* If the virtual table has been assigned to this translation unit,
358      export the class.  */
359   return (IDENTIFIER_REPO_CHOSEN
360           (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
361 }
362
363 #include "gt-cp-repo.h"