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)
5 This file is part of GCC.
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)
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.
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/>. */
21 /* My strategy here is as follows:
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
29 #include "coretypes.h"
34 #include "double-int.h"
41 #include "stringpool.h"
46 #include "diagnostic-core.h"
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);
55 static GTY(()) vec
<tree
, va_gc
> *pending_repo
;
56 static char *repo_name
;
58 static const char *old_args
, *old_dir
, *old_main
;
60 static struct obstack temporary_obstack
;
61 static bool temporary_obstack_initialized_p
;
63 /* Parse a reasonable subset of shell quoting syntax. */
66 extract_string (const char **pp
)
80 obstack_1grow (&temporary_obstack
, c
);
83 else if (! inside
&& c
== ' ')
85 else if (! inside
&& c
== '\\')
90 obstack_1grow (&temporary_obstack
, c
);
93 obstack_1grow (&temporary_obstack
, '\0');
95 return (char *) obstack_finish (&temporary_obstack
);
99 get_base_filename (const char *filename
)
101 const char *p
= getenv ("COLLECT_GCC_OPTIONS");
102 const char *output
= NULL
;
107 const char *q
= extract_string (&p
);
109 if (strcmp (q
, "-o") == 0)
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
);
117 output
= extract_string (&p
);
119 else if (strcmp (q
, "-c") == 0)
123 if (compiling
&& output
)
126 if (p
&& ! compiling
)
128 warning (0, "-frepo must be used with -c");
129 flag_use_repository
= 0;
133 return lbasename (filename
);
137 open_repo_file (const char *filename
)
140 const char *s
= get_base_filename (filename
);
146 p
= strrchr (p
, '.');
150 repo_name
= XNEWVEC (char, p
- s
+ 5);
151 memcpy (repo_name
, s
, p
- s
);
152 memcpy (repo_name
+ (p
- s
), ".rpo", 5);
154 return fopen (repo_name
, "r");
158 afgets (FILE *stream
)
161 while ((c
= getc (stream
)) != EOF
&& c
!= '\n')
162 obstack_1grow (&temporary_obstack
, c
);
163 if (obstack_object_size (&temporary_obstack
) == 0)
165 obstack_1grow (&temporary_obstack
, '\0');
166 return (char *) obstack_finish (&temporary_obstack
);
176 if (! flag_use_repository
)
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
;
184 if (!temporary_obstack_initialized_p
)
185 gcc_obstack_init (&temporary_obstack
);
187 repo_file
= open_repo_file (main_input_filename
);
192 while ((buf
= afgets (repo_file
)))
197 old_args
= ggc_strdup (buf
+ 2);
200 old_dir
= ggc_strdup (buf
+ 2);
203 old_main
= ggc_strdup (buf
+ 2);
206 /* A symbol that we were able to define the last time this
207 file was compiled. */
210 /* A symbol that the prelinker has requested that we
213 tree id
= get_identifier (buf
+ 2);
214 IDENTIFIER_REPO_CHOSEN (id
) = 1;
218 error ("mysterious repository information in %s", repo_name
);
220 obstack_free (&temporary_obstack
, buf
);
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="));
230 reopen_repo_file_for_write (void)
232 FILE *repo_file
= fopen (repo_name
, "w");
236 error ("can%'t create repository information file %qs", repo_name
);
237 flag_use_repository
= 0;
243 /* Emit any pending repos. */
253 if (!flag_use_repository
|| flag_compare_debug
)
259 repo_file
= reopen_repo_file_for_write ();
263 fprintf (repo_file
, "M %s\n", main_input_filename
);
265 fprintf (repo_file
, "D %s\n", dir
);
266 args
= getenv ("COLLECT_GCC_OPTIONS");
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");
280 FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo
, ix
, val
)
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
));
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. */
300 repo_emit_p (tree decl
)
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
309 || DECL_ABSTRACT_ORIGIN (decl
));
311 /* When not using the repository, emit everything. */
312 if (!flag_use_repository
)
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
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
)))
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
335 if (decl_maybe_constant_var_p (decl
)
336 && DECL_CLASS_SCOPE_P (decl
))
339 else if (!DECL_TEMPLATE_INSTANTIATION (decl
))
342 if (DECL_EXPLICIT_INSTANTIATION (decl
))
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
))
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
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
))
364 /* Keep track of all available entities. */
365 if (!DECL_REPO_AVAILABLE_P (decl
))
367 DECL_REPO_AVAILABLE_P (decl
) = 1;
368 vec_safe_push (pending_repo
, decl
);
371 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl
)) ? 1 : ret
;
374 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
375 export from this translation unit. */
378 repo_export_class_p (const_tree class_type
)
380 if (!flag_use_repository
)
382 if (!CLASSTYPE_VTABLES (class_type
))
384 /* If the virtual table has been assigned to this translation unit,
386 return (IDENTIFIER_REPO_CHOSEN
387 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type
))));
390 #include "gt-cp-repo.h"