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