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