]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cp/repo.c
Wrap option names in gcc internal messages with %< and %>.
[thirdparty/gcc.git] / gcc / cp / repo.c
CommitLineData
bb09dca5 1/* Code to maintain a C++ template repository.
fbd26352 2 Copyright (C) 1995-2019 Free Software Foundation, Inc.
bb09dca5 3 Contributed by Jason Merrill (jason@cygnus.com)
4
6f0d25a6 5This file is part of GCC.
bb09dca5 6
6f0d25a6 7GCC is free software; you can redistribute it and/or modify
bb09dca5 8it under the terms of the GNU General Public License as published by
aa139c3f 9the Free Software Foundation; either version 3, or (at your option)
bb09dca5 10any later version.
11
6f0d25a6 12GCC is distributed in the hope that it will be useful,
bb09dca5 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
aa139c3f 18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
bb09dca5 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
11682839 25 explicit code. */
bb09dca5 26
11682839 27#include "config.h"
b3ef7553 28#include "system.h"
805e22b2 29#include "coretypes.h"
bb09dca5 30#include "cp-tree.h"
4cba6f60 31#include "stringpool.h"
2a4e40b0 32#include "toplev.h"
bb09dca5 33
3f24af9b 34static const char *extract_string (const char **);
26ac6687 35static const char *get_base_filename (const char *);
8b35a404 36static FILE *open_repo_file (const char *);
26ac6687 37static char *afgets (FILE *);
8b35a404 38static FILE *reopen_repo_file_for_write (void);
bb09dca5 39
f1f41a6c 40static GTY(()) vec<tree, va_gc> *pending_repo;
3f7d79e4 41static char *repo_name;
bb09dca5 42
17dd1766 43static const char *old_args, *old_dir, *old_main;
6686e84d 44
d7c47c0e 45static struct obstack temporary_obstack;
caa6fdce 46static bool temporary_obstack_initialized_p;
dc76caae 47
6686e84d 48/* Parse a reasonable subset of shell quoting syntax. */
49
3f24af9b 50static const char *
51extract_string (const char **pp)
6686e84d 52{
3f24af9b 53 const char *p = *pp;
6686e84d 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)
4840a255 64 {
65 obstack_1grow (&temporary_obstack, c);
66 backquote = 0;
67 }
6686e84d 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;
4e41d774 80 return (char *) obstack_finish (&temporary_obstack);
6686e84d 81}
82
9140e457 83static const char *
26ac6687 84get_base_filename (const char *filename)
11682839 85{
3f24af9b 86 const char *p = getenv ("COLLECT_GCC_OPTIONS");
71278019 87 const char *output = NULL;
11682839 88 int compiling = 0;
89
6686e84d 90 while (p && *p)
91 {
3f24af9b 92 const char *q = extract_string (&p);
11682839 93
6686e84d 94 if (strcmp (q, "-o") == 0)
71278019 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 }
6686e84d 104 else if (strcmp (q, "-c") == 0)
105 compiling = 1;
4840a255 106 }
11682839 107
108 if (compiling && output)
109 return output;
110
3e1ffd94 111 if (p && ! compiling)
112 {
2f6d557f 113 warning (0, "%<-frepo%> must be used with %<-c%>");
3e1ffd94 114 flag_use_repository = 0;
115 return NULL;
116 }
117
40275504 118 return lbasename (filename);
9031d10b 119}
11682839 120
8b35a404 121static FILE *
26ac6687 122open_repo_file (const char *filename)
bb09dca5 123{
cd16867a 124 const char *p;
e1721763 125 const char *s = get_base_filename (filename);
3e1ffd94 126
3f7d79e4 127 if (s == NULL)
8b35a404 128 return NULL;
3e1ffd94 129
40275504 130 p = lbasename (s);
78dbff7c 131 p = strrchr (p, '.');
3f7d79e4 132 if (! p)
133 p = s + strlen (s);
bb09dca5 134
56e60747 135 repo_name = XNEWVEC (char, p - s + 5);
92192583 136 memcpy (repo_name, s, p - s);
137 memcpy (repo_name + (p - s), ".rpo", 5);
bb09dca5 138
8b35a404 139 return fopen (repo_name, "r");
bb09dca5 140}
141
3f7d79e4 142static char *
26ac6687 143afgets (FILE *stream)
3f7d79e4 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');
4e41d774 151 return (char *) obstack_finish (&temporary_obstack);
3f7d79e4 152}
153
bb09dca5 154void
caa6fdce 155init_repo (void)
bb09dca5 156{
3f7d79e4 157 char *buf;
3f24af9b 158 const char *p;
8b35a404 159 FILE *repo_file;
bb09dca5 160
161 if (! flag_use_repository)
162 return;
163
caa6fdce 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);
1e4853c2 171
8b35a404 172 repo_file = open_repo_file (main_input_filename);
bb09dca5 173
174 if (repo_file == 0)
175 return;
176
034b484a 177 while ((buf = afgets (repo_file)))
bb09dca5 178 {
bb09dca5 179 switch (buf[0])
180 {
181 case 'A':
92192583 182 old_args = ggc_strdup (buf + 2);
6686e84d 183 break;
3f7d79e4 184 case 'D':
92192583 185 old_dir = ggc_strdup (buf + 2);
6686e84d 186 break;
bb09dca5 187 case 'M':
92192583 188 old_main = ggc_strdup (buf + 2);
bb09dca5 189 break;
bb09dca5 190 case 'O':
caa6fdce 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. */
bb09dca5 197 {
3f7d79e4 198 tree id = get_identifier (buf + 2);
caa6fdce 199 IDENTIFIER_REPO_CHOSEN (id) = 1;
bb09dca5 200 }
201 break;
202 default:
905d4035 203 error ("mysterious repository information in %s", repo_name);
bb09dca5 204 }
3f7d79e4 205 obstack_free (&temporary_obstack, buf);
bb09dca5 206 }
caa6fdce 207 fclose (repo_file);
b6c1bd72 208
209 if (old_args && !get_random_seed (true)
3f24af9b 210 && (p = strstr (old_args, "'-frandom-seed=")))
211 set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
bb09dca5 212}
213
8b35a404 214static FILE *
26ac6687 215reopen_repo_file_for_write (void)
bb09dca5 216{
8b35a404 217 FILE *repo_file = fopen (repo_name, "w");
bb09dca5 218
219 if (repo_file == 0)
220 {
bf776685 221 error ("can%'t create repository information file %qs", repo_name);
bb09dca5 222 flag_use_repository = 0;
223 }
8b35a404 224
225 return repo_file;
bb09dca5 226}
227
228/* Emit any pending repos. */
229
230void
26ac6687 231finish_repo (void)
bb09dca5 232{
b640afb8 233 tree val;
6686e84d 234 char *dir, *args;
8b35a404 235 FILE *repo_file;
b640afb8 236 unsigned ix;
bb09dca5 237
71278019 238 if (!flag_use_repository || flag_compare_debug)
bb09dca5 239 return;
240
852f689e 241 if (seen_error ())
8b35a404 242 return;
bb09dca5 243
8b35a404 244 repo_file = reopen_repo_file_for_write ();
bb09dca5 245 if (repo_file == 0)
246 goto out;
247
11682839 248 fprintf (repo_file, "M %s\n", main_input_filename);
caa6fdce 249 dir = getpwd ();
6686e84d 250 fprintf (repo_file, "D %s\n", dir);
caa6fdce 251 args = getenv ("COLLECT_GCC_OPTIONS");
6686e84d 252 if (args)
2c3e097e 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="))
badc6cfa 260 fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'",
261 get_random_seed (false));
2c3e097e 262 fprintf (repo_file, "\n");
263 }
11682839 264
f1f41a6c 265 FOR_EACH_VEC_SAFE_ELT_REVERSE (pending_repo, ix, val)
bb09dca5 266 {
caa6fdce 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));
bb09dca5 270 }
271
272 out:
273 if (repo_file)
274 fclose (repo_file);
275}
1f3233d1 276
caa6fdce 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
284int
285repo_emit_p (tree decl)
286{
7133f4fc 287 int ret = 0;
b4df430b 288 gcc_assert (TREE_PUBLIC (decl));
4cace8cb 289 gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
cdc99fba 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));
caa6fdce 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. */
80a58eb0 304 if (VAR_P (decl))
caa6fdce 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)
c40c1730 312 && (!TYPE_LANG_SPECIFIC (type)
313 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
caa6fdce 314 return 2;
af3f756d 315 /* Const static data members initialized by constant expressions must
b3cee199 316 be processed where needed so that their definitions are
7133f4fc 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. */
d58b8a94 320 if (decl_maybe_constant_var_p (decl)
b3cee199 321 && DECL_CLASS_SCOPE_P (decl))
7133f4fc 322 ret = 2;
caa6fdce 323 }
324 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
325 return 2;
326
af3f756d 327 if (DECL_EXPLICIT_INSTANTIATION (decl))
328 return 2;
329
caa6fdce 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. */
c6e04fca 333 if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl))
caa6fdce 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;
f1f41a6c 352 vec_safe_push (pending_repo, decl);
caa6fdce 353 }
354
7133f4fc 355 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
caa6fdce 356}
357
358/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
359 export from this translation unit. */
360
361bool
9f627b1a 362repo_export_class_p (const_tree class_type)
caa6fdce 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. */
9031d10b 370 return (IDENTIFIER_REPO_CHOSEN
caa6fdce 371 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
372}
373
1f3233d1 374#include "gt-cp-repo.h"