]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cp/repo.c
2005-05-23 Alfred M. Szmidt <ams@gnu.org>
[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
c58d4270 20the Free Software Foundation, 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, 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"
bb09dca5 39
26ac6687 40static char *extract_string (char **);
41static const char *get_base_filename (const char *);
42static void open_repo_file (const char *);
43static char *afgets (FILE *);
44static void reopen_repo_file_for_write (void);
bb09dca5 45
1f3233d1 46static GTY(()) tree pending_repo;
3f7d79e4 47static char *repo_name;
bb09dca5 48static FILE *repo_file;
49
17dd1766 50static const char *old_args, *old_dir, *old_main;
6686e84d 51
d7c47c0e 52static struct obstack temporary_obstack;
caa6fdce 53static bool temporary_obstack_initialized_p;
dc76caae 54
6686e84d 55/* Parse a reasonable subset of shell quoting syntax. */
56
57static char *
26ac6687 58extract_string (char **pp)
6686e84d 59{
60 char *p = *pp;
61 int backquote = 0;
62 int inside = 0;
63
64 for (;;)
65 {
66 char c = *p;
67 if (c == '\0')
68 break;
69 ++p;
70 if (backquote)
4840a255 71 {
72 obstack_1grow (&temporary_obstack, c);
73 backquote = 0;
74 }
6686e84d 75 else if (! inside && c == ' ')
76 break;
77 else if (! inside && c == '\\')
78 backquote = 1;
79 else if (c == '\'')
80 inside = !inside;
81 else
82 obstack_1grow (&temporary_obstack, c);
83 }
84
85 obstack_1grow (&temporary_obstack, '\0');
86 *pp = p;
87 return obstack_finish (&temporary_obstack);
88}
89
9140e457 90static const char *
26ac6687 91get_base_filename (const char *filename)
11682839 92{
93 char *p = getenv ("COLLECT_GCC_OPTIONS");
6686e84d 94 char *output = NULL;
11682839 95 int compiling = 0;
96
6686e84d 97 while (p && *p)
98 {
99 char *q = extract_string (&p);
11682839 100
6686e84d 101 if (strcmp (q, "-o") == 0)
102 output = extract_string (&p);
103 else if (strcmp (q, "-c") == 0)
104 compiling = 1;
4840a255 105 }
11682839 106
107 if (compiling && output)
108 return output;
109
3e1ffd94 110 if (p && ! compiling)
111 {
c3ceba8e 112 warning (0, "-frepo must be used with -c");
3e1ffd94 113 flag_use_repository = 0;
114 return NULL;
115 }
116
40275504 117 return lbasename (filename);
11682839 118}
119
bb09dca5 120static void
26ac6687 121open_repo_file (const char *filename)
bb09dca5 122{
cd16867a 123 const char *p;
e1721763 124 const char *s = get_base_filename (filename);
3e1ffd94 125
3f7d79e4 126 if (s == NULL)
3e1ffd94 127 return;
128
40275504 129 p = lbasename (s);
78dbff7c 130 p = strrchr (p, '.');
3f7d79e4 131 if (! p)
132 p = s + strlen (s);
bb09dca5 133
92192583 134 repo_name = xmalloc (p - s + 5);
135 memcpy (repo_name, s, p - s);
136 memcpy (repo_name + (p - s), ".rpo", 5);
bb09dca5 137
138 repo_file = fopen (repo_name, "r");
139}
140
3f7d79e4 141static char *
26ac6687 142afgets (FILE *stream)
3f7d79e4 143{
144 int c;
145 while ((c = getc (stream)) != EOF && c != '\n')
146 obstack_1grow (&temporary_obstack, c);
147 if (obstack_object_size (&temporary_obstack) == 0)
148 return NULL;
149 obstack_1grow (&temporary_obstack, '\0');
150 return obstack_finish (&temporary_obstack);
151}
152
bb09dca5 153void
caa6fdce 154init_repo (void)
bb09dca5 155{
3f7d79e4 156 char *buf;
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
caa6fdce 169 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);
bb09dca5 205}
206
207static void
26ac6687 208reopen_repo_file_for_write (void)
bb09dca5 209{
bb09dca5 210 repo_file = fopen (repo_name, "w");
211
212 if (repo_file == 0)
213 {
44ed1032 214 error ("can't create repository information file %qs", repo_name);
bb09dca5 215 flag_use_repository = 0;
216 }
217}
218
219/* Emit any pending repos. */
220
221void
26ac6687 222finish_repo (void)
bb09dca5 223{
224 tree t;
6686e84d 225 char *dir, *args;
bb09dca5 226
26ac6687 227 if (!flag_use_repository)
bb09dca5 228 return;
229
caa6fdce 230 if (errorcount || sorrycount)
bb09dca5 231 goto out;
232
233 reopen_repo_file_for_write ();
bb09dca5 234 if (repo_file == 0)
235 goto out;
236
11682839 237 fprintf (repo_file, "M %s\n", main_input_filename);
caa6fdce 238 dir = getpwd ();
6686e84d 239 fprintf (repo_file, "D %s\n", dir);
caa6fdce 240 args = getenv ("COLLECT_GCC_OPTIONS");
6686e84d 241 if (args)
242 fprintf (repo_file, "A %s\n", args);
11682839 243
bb09dca5 244 for (t = pending_repo; t; t = TREE_CHAIN (t))
245 {
246 tree val = TREE_VALUE (t);
caa6fdce 247 tree name = DECL_ASSEMBLER_NAME (val);
248 char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
249 fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
bb09dca5 250 }
251
252 out:
253 if (repo_file)
254 fclose (repo_file);
255}
1f3233d1 256
caa6fdce 257/* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
258 definition is available in this translation unit. Returns 0 if
259 this definition should not be emitted in this translation unit
260 because it will be emitted elsewhere. Returns 1 if the repository
261 file indicates that that DECL should be emitted in this translation
262 unit, or 2 if the repository file is not in use. */
263
264int
265repo_emit_p (tree decl)
266{
b4df430b 267 gcc_assert (TREE_PUBLIC (decl));
268 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
269 || TREE_CODE (decl) == VAR_DECL);
270 gcc_assert (!DECL_REALLY_EXTERN (decl));
caa6fdce 271
272 /* When not using the repository, emit everything. */
273 if (!flag_use_repository)
274 return 2;
275
276 /* Only template instantiations are managed by the repository. This
277 is an artificial restriction; the code in the prelinker and here
278 will work fine if all entities with vague linkage are managed by
279 the repository. */
280 if (TREE_CODE (decl) == VAR_DECL)
281 {
282 tree type = NULL_TREE;
283 if (DECL_VTABLE_OR_VTT_P (decl))
284 type = DECL_CONTEXT (decl);
285 else if (DECL_TINFO_P (decl))
286 type = TREE_TYPE (DECL_NAME (decl));
287 if (!DECL_TEMPLATE_INSTANTIATION (decl)
288 && !CLASSTYPE_TEMPLATE_INSTANTIATION (type))
289 return 2;
290 }
291 else if (!DECL_TEMPLATE_INSTANTIATION (decl))
292 return 2;
293
294 /* For constructors and destructors, the repository contains
295 information about the clones -- not the original function --
296 because only the clones are emitted in the object file. */
297 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
298 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
299 {
300 int emit_p = 0;
301 tree clone;
302 /* There is no early exit from this loop because we want to
303 ensure that all of the clones are marked as available in this
304 object file. */
305 FOR_EACH_CLONE (clone, decl)
306 /* The only possible results from the recursive call to
307 repo_emit_p are 0 or 1. */
308 if (repo_emit_p (clone))
309 emit_p = 1;
310 return emit_p;
311 }
312
313 /* Keep track of all available entities. */
314 if (!DECL_REPO_AVAILABLE_P (decl))
315 {
316 DECL_REPO_AVAILABLE_P (decl) = 1;
317 pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
318 }
319
320 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
321}
322
323/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
324 export from this translation unit. */
325
326bool
327repo_export_class_p (tree class_type)
328{
329 if (!flag_use_repository)
330 return false;
331 if (!CLASSTYPE_VTABLES (class_type))
332 return false;
333 /* If the virtual table has been assigned to this translation unit,
334 export the class. */
335 return (IDENTIFIER_REPO_CHOSEN
336 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
337}
338
1f3233d1 339#include "gt-cp-repo.h"