OSDN Git Service

gcc/ChangeLog:
[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, 2008  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 3, 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 COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 /* My strategy here is as follows:
23
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.  */
27
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"
39
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);
45
46 static GTY(()) tree pending_repo;
47 static char *repo_name;
48
49 static const char *old_args, *old_dir, *old_main;
50
51 static struct obstack temporary_obstack;
52 static bool temporary_obstack_initialized_p;
53
54 /* Parse a reasonable subset of shell quoting syntax.  */
55
56 static char *
57 extract_string (char **pp)
58 {
59   char *p = *pp;
60   int backquote = 0;
61   int inside = 0;
62
63   for (;;)
64     {
65       char c = *p;
66       if (c == '\0')
67         break;
68       ++p;
69       if (backquote)
70         {
71           obstack_1grow (&temporary_obstack, c);
72           backquote = 0;
73         }
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);
82     }
83
84   obstack_1grow (&temporary_obstack, '\0');
85   *pp = p;
86   return (char *) obstack_finish (&temporary_obstack);
87 }
88
89 static const char *
90 get_base_filename (const char *filename)
91 {
92   char *p = getenv ("COLLECT_GCC_OPTIONS");
93   const char *output = NULL;
94   int compiling = 0;
95
96   while (p && *p)
97     {
98       char *q = extract_string (&p);
99
100       if (strcmp (q, "-o") == 0)
101         {
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);
107           else
108             output = extract_string (&p);
109         }
110       else if (strcmp (q, "-c") == 0)
111         compiling = 1;
112     }
113
114   if (compiling && output)
115     return output;
116
117   if (p && ! compiling)
118     {
119       warning (0, "-frepo must be used with -c");
120       flag_use_repository = 0;
121       return NULL;
122     }
123
124   return lbasename (filename);
125 }
126
127 static FILE *
128 open_repo_file (const char *filename)
129 {
130   const char *p;
131   const char *s = get_base_filename (filename);
132
133   if (s == NULL)
134     return NULL;
135
136   p = lbasename (s);
137   p = strrchr (p, '.');
138   if (! p)
139     p = s + strlen (s);
140
141   repo_name = XNEWVEC (char, p - s + 5);
142   memcpy (repo_name, s, p - s);
143   memcpy (repo_name + (p - s), ".rpo", 5);
144
145   return fopen (repo_name, "r");
146 }
147
148 static char *
149 afgets (FILE *stream)
150 {
151   int c;
152   while ((c = getc (stream)) != EOF && c != '\n')
153     obstack_1grow (&temporary_obstack, c);
154   if (obstack_object_size (&temporary_obstack) == 0)
155     return NULL;
156   obstack_1grow (&temporary_obstack, '\0');
157   return (char *) obstack_finish (&temporary_obstack);
158 }
159
160 void
161 init_repo (void)
162 {
163   char *buf;
164   FILE *repo_file;
165
166   if (! flag_use_repository)
167     return;
168
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;
173
174   if (!temporary_obstack_initialized_p)
175     gcc_obstack_init (&temporary_obstack);
176
177   repo_file = open_repo_file (main_input_filename);
178
179   if (repo_file == 0)
180     return;
181
182   while ((buf = afgets (repo_file)))
183     {
184       switch (buf[0])
185         {
186         case 'A':
187           old_args = ggc_strdup (buf + 2);
188           break;
189         case 'D':
190           old_dir = ggc_strdup (buf + 2);
191           break;
192         case 'M':
193           old_main = ggc_strdup (buf + 2);
194           break;
195         case 'O':
196           /* A symbol that we were able to define the last time this
197              file was compiled.  */
198           break;
199         case 'C':
200           /* A symbol that the prelinker has requested that we
201              define.  */
202           {
203             tree id = get_identifier (buf + 2);
204             IDENTIFIER_REPO_CHOSEN (id) = 1;
205           }
206           break;
207         default:
208           error ("mysterious repository information in %s", repo_name);
209         }
210       obstack_free (&temporary_obstack, buf);
211     }
212   fclose (repo_file);
213
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="));
217 }
218
219 static FILE *
220 reopen_repo_file_for_write (void)
221 {
222   FILE *repo_file = fopen (repo_name, "w");
223
224   if (repo_file == 0)
225     {
226       error ("can't create repository information file %qs", repo_name);
227       flag_use_repository = 0;
228     }
229
230   return repo_file;
231 }
232
233 /* Emit any pending repos.  */
234
235 void
236 finish_repo (void)
237 {
238   tree t;
239   char *dir, *args;
240   FILE *repo_file;
241
242   if (!flag_use_repository || flag_compare_debug)
243     return;
244
245   if (errorcount || sorrycount)
246     return;
247
248   repo_file = reopen_repo_file_for_write ();
249   if (repo_file == 0)
250     goto out;
251
252   fprintf (repo_file, "M %s\n", main_input_filename);
253   dir = getpwd ();
254   fprintf (repo_file, "D %s\n", dir);
255   args = getenv ("COLLECT_GCC_OPTIONS");
256   if (args)
257     {
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");
266     }
267
268   for (t = pending_repo; t; t = TREE_CHAIN (t))
269     {
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));
274     }
275
276  out:
277   if (repo_file)
278     fclose (repo_file);
279 }
280
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.  */
287
288 int
289 repo_emit_p (tree decl)
290 {
291   int ret = 0;
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));
296
297   /* When not using the repository, emit everything.  */
298   if (!flag_use_repository)
299     return 2;
300
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
304      the repository.  */
305   if (TREE_CODE (decl) == VAR_DECL)
306     {
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)))
315         return 2;
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
320          be provided.  */
321       if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
322           && DECL_CLASS_SCOPE_P (decl))
323         ret = 2;
324     }
325   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
326     return 2;
327
328   if (DECL_EXPLICIT_INSTANTIATION (decl))
329     return 2;
330
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))
336     {
337       int emit_p = 0;
338       tree clone;
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
341          object file.  */
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))
346           emit_p = 1;
347       return emit_p;
348     }
349
350   /* Keep track of all available entities.  */
351   if (!DECL_REPO_AVAILABLE_P (decl))
352     {
353       DECL_REPO_AVAILABLE_P (decl) = 1;
354       pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
355     }
356
357   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
358 }
359
360 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
361    export from this translation unit.  */
362
363 bool
364 repo_export_class_p (const_tree class_type)
365 {
366   if (!flag_use_repository)
367     return false;
368   if (!CLASSTYPE_VTABLES (class_type))
369     return false;
370   /* If the virtual table has been assigned to this translation unit,
371      export the class.  */
372   return (IDENTIFIER_REPO_CHOSEN
373           (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
374 }
375
376 #include "gt-cp-repo.h"