]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cp/repo.c
* gcc.dg/lvalue-2.c (f0): Put "error: " marker back.
[thirdparty/gcc.git] / gcc / cp / repo.c
CommitLineData
bb09dca5 1/* Code to maintain a C++ template repository.
99ae5467 2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
06fb4c5c 3 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
10the Free Software Foundation; either version 2, or (at your option)
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
6f0d25a6 19along with GCC; see the file COPYING. If not, write to
beaeca68 20the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA. */
bb09dca5 22
23/* My strategy here is as follows:
24
25 Everything should be emitted in a translation unit where it is used.
26 The results of the automatic process should be easily reproducible with
11682839 27 explicit code. */
bb09dca5 28
11682839 29#include "config.h"
b3ef7553 30#include "system.h"
805e22b2 31#include "coretypes.h"
32#include "tm.h"
bb09dca5 33#include "tree.h"
34#include "cp-tree.h"
35#include "input.h"
3e1ffd94 36#include "obstack.h"
2a4e40b0 37#include "toplev.h"
a587b03b 38#include "diagnostic.h"
2c3e097e 39#include "flags.h"
bb09dca5 40
26ac6687 41static char *extract_string (char **);
42static const char *get_base_filename (const char *);
43static void open_repo_file (const char *);
44static char *afgets (FILE *);
45static void reopen_repo_file_for_write (void);
bb09dca5 46
1f3233d1 47static GTY(()) tree pending_repo;
3f7d79e4 48static char *repo_name;
bb09dca5 49static FILE *repo_file;
50
17dd1766 51static const char *old_args, *old_dir, *old_main;
6686e84d 52
d7c47c0e 53static struct obstack temporary_obstack;
caa6fdce 54static bool temporary_obstack_initialized_p;
dc76caae 55
6686e84d 56/* Parse a reasonable subset of shell quoting syntax. */
57
58static char *
26ac6687 59extract_string (char **pp)
6686e84d 60{
61 char *p = *pp;
62 int backquote = 0;
63 int inside = 0;
64
65 for (;;)
66 {
67 char c = *p;
68 if (c == '\0')
69 break;
70 ++p;
71 if (backquote)
4840a255 72 {
73 obstack_1grow (&temporary_obstack, c);
74 backquote = 0;
75 }
6686e84d 76 else if (! inside && c == ' ')
77 break;
78 else if (! inside && c == '\\')
79 backquote = 1;
80 else if (c == '\'')
81 inside = !inside;
82 else
83 obstack_1grow (&temporary_obstack, c);
84 }
85
86 obstack_1grow (&temporary_obstack, '\0');
87 *pp = p;
88 return obstack_finish (&temporary_obstack);
89}
90
9140e457 91static const char *
26ac6687 92get_base_filename (const char *filename)
11682839 93{
94 char *p = getenv ("COLLECT_GCC_OPTIONS");
6686e84d 95 char *output = NULL;
11682839 96 int compiling = 0;
97
6686e84d 98 while (p && *p)
99 {
100 char *q = extract_string (&p);
11682839 101
6686e84d 102 if (strcmp (q, "-o") == 0)
103 output = extract_string (&p);
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 {
c3ceba8e 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
bb09dca5 121static void
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)
3e1ffd94 128 return;
129
40275504 130 p = lbasename (s);
78dbff7c 131 p = strrchr (p, '.');
3f7d79e4 132 if (! p)
133 p = s + strlen (s);
bb09dca5 134
92192583 135 repo_name = xmalloc (p - s + 5);
136 memcpy (repo_name, s, p - s);
137 memcpy (repo_name + (p - s), ".rpo", 5);
bb09dca5 138
139 repo_file = fopen (repo_name, "r");
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');
151 return obstack_finish (&temporary_obstack);
152}
153
bb09dca5 154void
caa6fdce 155init_repo (void)
bb09dca5 156{
3f7d79e4 157 char *buf;
bb09dca5 158
159 if (! flag_use_repository)
160 return;
161
caa6fdce 162 /* When a PCH file is loaded, the entire identifier table is
163 replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
164 So, we have to reread the repository file. */
165 lang_post_pch_load = init_repo;
166
167 if (!temporary_obstack_initialized_p)
168 gcc_obstack_init (&temporary_obstack);
1e4853c2 169
caa6fdce 170 open_repo_file (main_input_filename);
bb09dca5 171
172 if (repo_file == 0)
173 return;
174
034b484a 175 while ((buf = afgets (repo_file)))
bb09dca5 176 {
bb09dca5 177 switch (buf[0])
178 {
179 case 'A':
92192583 180 old_args = ggc_strdup (buf + 2);
6686e84d 181 break;
3f7d79e4 182 case 'D':
92192583 183 old_dir = ggc_strdup (buf + 2);
6686e84d 184 break;
bb09dca5 185 case 'M':
92192583 186 old_main = ggc_strdup (buf + 2);
bb09dca5 187 break;
bb09dca5 188 case 'O':
caa6fdce 189 /* A symbol that we were able to define the last time this
190 file was compiled. */
191 break;
192 case 'C':
193 /* A symbol that the prelinker has requested that we
194 define. */
bb09dca5 195 {
3f7d79e4 196 tree id = get_identifier (buf + 2);
caa6fdce 197 IDENTIFIER_REPO_CHOSEN (id) = 1;
bb09dca5 198 }
199 break;
200 default:
905d4035 201 error ("mysterious repository information in %s", repo_name);
bb09dca5 202 }
3f7d79e4 203 obstack_free (&temporary_obstack, buf);
bb09dca5 204 }
caa6fdce 205 fclose (repo_file);
bb09dca5 206}
207
208static void
26ac6687 209reopen_repo_file_for_write (void)
bb09dca5 210{
bb09dca5 211 repo_file = fopen (repo_name, "w");
212
213 if (repo_file == 0)
214 {
44ed1032 215 error ("can't create repository information file %qs", repo_name);
bb09dca5 216 flag_use_repository = 0;
217 }
218}
219
220/* Emit any pending repos. */
221
222void
26ac6687 223finish_repo (void)
bb09dca5 224{
225 tree t;
6686e84d 226 char *dir, *args;
bb09dca5 227
26ac6687 228 if (!flag_use_repository)
bb09dca5 229 return;
230
caa6fdce 231 if (errorcount || sorrycount)
bb09dca5 232 goto out;
233
234 reopen_repo_file_for_write ();
bb09dca5 235 if (repo_file == 0)
236 goto out;
237
11682839 238 fprintf (repo_file, "M %s\n", main_input_filename);
caa6fdce 239 dir = getpwd ();
6686e84d 240 fprintf (repo_file, "D %s\n", dir);
caa6fdce 241 args = getenv ("COLLECT_GCC_OPTIONS");
6686e84d 242 if (args)
2c3e097e 243 {
244 fprintf (repo_file, "A %s", args);
245 /* If -frandom-seed is not among the ARGS, then add the value
246 that we chose. That will ensure that the names of types from
247 anonymous namespaces will get the same mangling when this
248 file is recompiled. */
249 if (!strstr (args, "'-frandom-seed="))
250 fprintf (repo_file, " '-frandom-seed=%s'", flag_random_seed);
251 fprintf (repo_file, "\n");
252 }
11682839 253
bb09dca5 254 for (t = pending_repo; t; t = TREE_CHAIN (t))
255 {
256 tree val = TREE_VALUE (t);
caa6fdce 257 tree name = DECL_ASSEMBLER_NAME (val);
258 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
259 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
bb09dca5 260 }
261
262 out:
263 if (repo_file)
264 fclose (repo_file);
265}
1f3233d1 266
caa6fdce 267/* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
268 definition is available in this translation unit. Returns 0 if
269 this definition should not be emitted in this translation unit
270 because it will be emitted elsewhere. Returns 1 if the repository
271 file indicates that that DECL should be emitted in this translation
272 unit, or 2 if the repository file is not in use. */
273
274int
275repo_emit_p (tree decl)
276{
b4df430b 277 gcc_assert (TREE_PUBLIC (decl));
278 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
279 || TREE_CODE (decl) == VAR_DECL);
280 gcc_assert (!DECL_REALLY_EXTERN (decl));
caa6fdce 281
282 /* When not using the repository, emit everything. */
283 if (!flag_use_repository)
284 return 2;
285
286 /* Only template instantiations are managed by the repository. This
287 is an artificial restriction; the code in the prelinker and here
288 will work fine if all entities with vague linkage are managed by
289 the repository. */
290 if (TREE_CODE (decl) == VAR_DECL)
291 {
292 tree type = NULL_TREE;
293 if (DECL_VTABLE_OR_VTT_P (decl))
294 type = DECL_CONTEXT (decl);
295 else if (DECL_TINFO_P (decl))
296 type = TREE_TYPE (DECL_NAME (decl));
297 if (!DECL_TEMPLATE_INSTANTIATION (decl)
c40c1730 298 && (!TYPE_LANG_SPECIFIC (type)
299 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
caa6fdce 300 return 2;
301 }
302 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
303 return 2;
304
305 /* For constructors and destructors, the repository contains
306 information about the clones -- not the original function --
307 because only the clones are emitted in the object file. */
308 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
309 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
310 {
311 int emit_p = 0;
312 tree clone;
313 /* There is no early exit from this loop because we want to
314 ensure that all of the clones are marked as available in this
315 object file. */
316 FOR_EACH_CLONE (clone, decl)
317 /* The only possible results from the recursive call to
318 repo_emit_p are 0 or 1. */
319 if (repo_emit_p (clone))
320 emit_p = 1;
321 return emit_p;
322 }
323
324 /* Keep track of all available entities. */
325 if (!DECL_REPO_AVAILABLE_P (decl))
326 {
327 DECL_REPO_AVAILABLE_P (decl) = 1;
328 pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
329 }
330
331 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
332}
333
334/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
335 export from this translation unit. */
336
337bool
338repo_export_class_p (tree class_type)
339{
340 if (!flag_use_repository)
341 return false;
342 if (!CLASSTYPE_VTABLES (class_type))
343 return false;
344 /* If the virtual table has been assigned to this translation unit,
345 export the class. */
9031d10b 346 return (IDENTIFIER_REPO_CHOSEN
caa6fdce 347 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
348}
349
1f3233d1 350#include "gt-cp-repo.h"