OSDN Git Service

* typeck.c: Change copyright header to refer to version 3 of the GNU General
[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 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   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         output = extract_string (&p);
102       else if (strcmp (q, "-c") == 0)
103         compiling = 1;
104     }
105
106   if (compiling && output)
107     return output;
108
109   if (p && ! compiling)
110     {
111       warning (0, "-frepo must be used with -c");
112       flag_use_repository = 0;
113       return NULL;
114     }
115
116   return lbasename (filename);
117 }
118
119 static FILE *
120 open_repo_file (const char *filename)
121 {
122   const char *p;
123   const char *s = get_base_filename (filename);
124
125   if (s == NULL)
126     return NULL;
127
128   p = lbasename (s);
129   p = strrchr (p, '.');
130   if (! p)
131     p = s + strlen (s);
132
133   repo_name = XNEWVEC (char, p - s + 5);
134   memcpy (repo_name, s, p - s);
135   memcpy (repo_name + (p - s), ".rpo", 5);
136
137   return fopen (repo_name, "r");
138 }
139
140 static char *
141 afgets (FILE *stream)
142 {
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);
150 }
151
152 void
153 init_repo (void)
154 {
155   char *buf;
156   FILE *repo_file;
157
158   if (! flag_use_repository)
159     return;
160
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;
165
166   if (!temporary_obstack_initialized_p)
167     gcc_obstack_init (&temporary_obstack);
168
169   repo_file = open_repo_file (main_input_filename);
170
171   if (repo_file == 0)
172     return;
173
174   while ((buf = afgets (repo_file)))
175     {
176       switch (buf[0])
177         {
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.  */
194           {
195             tree id = get_identifier (buf + 2);
196             IDENTIFIER_REPO_CHOSEN (id) = 1;
197           }
198           break;
199         default:
200           error ("mysterious repository information in %s", repo_name);
201         }
202       obstack_free (&temporary_obstack, buf);
203     }
204   fclose (repo_file);
205
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="));
209 }
210
211 static FILE *
212 reopen_repo_file_for_write (void)
213 {
214   FILE *repo_file = fopen (repo_name, "w");
215
216   if (repo_file == 0)
217     {
218       error ("can't create repository information file %qs", repo_name);
219       flag_use_repository = 0;
220     }
221
222   return repo_file;
223 }
224
225 /* Emit any pending repos.  */
226
227 void
228 finish_repo (void)
229 {
230   tree t;
231   char *dir, *args;
232   FILE *repo_file;
233
234   if (!flag_use_repository)
235     return;
236
237   if (errorcount || sorrycount)
238     return;
239
240   repo_file = reopen_repo_file_for_write ();
241   if (repo_file == 0)
242     goto out;
243
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)
249     {
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");
258     }
259
260   for (t = pending_repo; t; t = TREE_CHAIN (t))
261     {
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));
266     }
267
268  out:
269   if (repo_file)
270     fclose (repo_file);
271 }
272
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.  */
279
280 int
281 repo_emit_p (tree decl)
282 {
283   gcc_assert (TREE_PUBLIC (decl));
284   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
285               || TREE_CODE (decl) == VAR_DECL);
286   gcc_assert (!DECL_REALLY_EXTERN (decl));
287
288   /* When not using the repository, emit everything.  */
289   if (!flag_use_repository)
290     return 2;
291
292   /* Only template instantiations are managed by the repository.  This
293      is an artificial restriction; the code in the prelinker and here
294      will work fine if all entities with vague linkage are managed by
295      the repository.  */
296   if (TREE_CODE (decl) == VAR_DECL)
297     {
298       tree type = NULL_TREE;
299       if (DECL_VTABLE_OR_VTT_P (decl))
300         type = DECL_CONTEXT (decl);
301       else if (DECL_TINFO_P (decl))
302         type = TREE_TYPE (DECL_NAME (decl));
303       if (!DECL_TEMPLATE_INSTANTIATION (decl)
304           && (!TYPE_LANG_SPECIFIC (type)
305               || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
306         return 2;
307       /* Static data members initialized by constant expressions must
308          be processed where needed so that their definitions are
309          available.  */
310       if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
311           && DECL_CLASS_SCOPE_P (decl))
312         return 2;
313     }
314   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
315     return 2;
316
317   /* For constructors and destructors, the repository contains
318      information about the clones -- not the original function --
319      because only the clones are emitted in the object file.  */
320   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
321       || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
322     {
323       int emit_p = 0;
324       tree clone;
325       /* There is no early exit from this loop because we want to
326          ensure that all of the clones are marked as available in this
327          object file.  */
328       FOR_EACH_CLONE (clone, decl)
329         /* The only possible results from the recursive call to
330            repo_emit_p are 0 or 1.  */
331         if (repo_emit_p (clone))
332           emit_p = 1;
333       return emit_p;
334     }
335
336   /* Keep track of all available entities.  */
337   if (!DECL_REPO_AVAILABLE_P (decl))
338     {
339       DECL_REPO_AVAILABLE_P (decl) = 1;
340       pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
341     }
342
343   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
344 }
345
346 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
347    export from this translation unit.  */
348
349 bool
350 repo_export_class_p (tree class_type)
351 {
352   if (!flag_use_repository)
353     return false;
354   if (!CLASSTYPE_VTABLES (class_type))
355     return false;
356   /* If the virtual table has been assigned to this translation unit,
357      export the class.  */
358   return (IDENTIFIER_REPO_CHOSEN
359           (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
360 }
361
362 #include "gt-cp-repo.h"