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