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