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