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