1 /* Code to maintain a C++ template repository.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Jason Merrill (jason@cygnus.com)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* My strategy here is as follows:
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
31 #include "coretypes.h"
38 #include "diagnostic.h"
40 static tree
repo_get_id (tree
);
41 static char *extract_string (char **);
42 static const char *get_base_filename (const char *);
43 static void open_repo_file (const char *);
44 static char *afgets (FILE *);
45 static void reopen_repo_file_for_write (void);
47 static GTY(()) tree pending_repo
;
48 static GTY(()) tree original_repo
;
49 static char *repo_name
;
50 static FILE *repo_file
;
52 static const char *old_args
, *old_dir
, *old_main
;
54 static struct obstack temporary_obstack
;
56 #define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
57 #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
60 /* Record the flags used to compile this translation unit. */
63 repo_compile_flags (int argc
, char **argv
)
67 /* If this template has not been seen before, add a note to the repository
68 saying where the declaration was. This may be used to find the
69 definition at link time. */
72 repo_template_declared (tree t
)
75 /* Note where the definition of a template lives so that instantiations can
76 be generated later. */
79 repo_template_defined (tree t
)
82 /* Note where the definition of a class lives to that template
83 instantiations can use it. */
86 repo_class_defined (tree t
)
97 /* If we're not done setting up the class, we may not have set up
98 the vtable, so going ahead would give the wrong answer.
99 See g++.pt/instantiate4.C. */
100 if (!COMPLETE_TYPE_P (t
) || TYPE_BEING_DEFINED (t
))
103 vtable
= get_vtbl_decl_for_binfo (TYPE_BINFO (t
));
109 return DECL_ASSEMBLER_NAME (t
);
112 /* Note that a template has been used. If we can see the definition, offer
116 repo_template_used (tree t
)
120 if (! flag_use_repository
)
123 id
= repo_get_id (t
);
129 if (IDENTIFIER_REPO_CHOSEN (id
))
130 mark_class_instantiated (t
, 0);
134 if (IDENTIFIER_REPO_CHOSEN (id
))
135 /* It doesn't make sense to instantiate a clone, so we
136 instantiate the cloned function instead. Note that this
137 approach will not work correctly if collect2 assigns
138 different clones to different files -- but it shouldn't. */
139 mark_decl_instantiated (DECL_CLONED_FUNCTION_P (t
)
140 ? DECL_CLONED_FUNCTION (t
) : t
,
146 if (! IDENTIFIER_REPO_USED (id
))
148 IDENTIFIER_REPO_USED (id
) = 1;
149 pending_repo
= tree_cons (NULL_TREE
, id
, pending_repo
);
154 /* Note that the vtable for a class has been used, and offer to emit it. */
157 repo_vtable_used (tree t
)
159 if (! flag_use_repository
)
162 pending_repo
= tree_cons (NULL_TREE
, t
, pending_repo
);
165 /* Note that an inline with external linkage has been used, and offer to
169 repo_inline_used (tree fn
)
171 if (! flag_use_repository
)
174 /* Member functions of polymorphic classes go with their vtables. */
175 if (DECL_FUNCTION_MEMBER_P (fn
)
176 && TYPE_POLYMORPHIC_P (DECL_CONTEXT (fn
)))
178 repo_vtable_used (DECL_CONTEXT (fn
));
182 pending_repo
= tree_cons (NULL_TREE
, fn
, pending_repo
);
185 /* Note that a particular typeinfo node has been used, and offer to
189 repo_tinfo_used (tree ti
)
195 repo_template_instantiated (tree t
, bool extern_p
)
199 tree id
= repo_get_id (t
);
201 IDENTIFIER_REPO_CHOSEN (id
) = 1;
205 /* Parse a reasonable subset of shell quoting syntax. */
208 extract_string (char **pp
)
221 obstack_1grow (&temporary_obstack
, c
);
222 else if (! inside
&& c
== ' ')
224 else if (! inside
&& c
== '\\')
229 obstack_1grow (&temporary_obstack
, c
);
232 obstack_1grow (&temporary_obstack
, '\0');
234 return obstack_finish (&temporary_obstack
);
238 get_base_filename (const char *filename
)
240 char *p
= getenv ("COLLECT_GCC_OPTIONS");
246 char *q
= extract_string (&p
);
248 if (strcmp (q
, "-o") == 0)
249 output
= extract_string (&p
);
250 else if (strcmp (q
, "-c") == 0)
254 if (compiling
&& output
)
257 if (p
&& ! compiling
)
259 warning ("-frepo must be used with -c");
260 flag_use_repository
= 0;
264 return lbasename (filename
);
268 open_repo_file (const char *filename
)
271 const char *s
= get_base_filename (filename
);
277 p
= strrchr (p
, '.');
281 repo_name
= xmalloc (p
- s
+ 5);
282 memcpy (repo_name
, s
, p
- s
);
283 memcpy (repo_name
+ (p
- s
), ".rpo", 5);
285 repo_file
= fopen (repo_name
, "r");
289 afgets (FILE *stream
)
292 while ((c
= getc (stream
)) != EOF
&& c
!= '\n')
293 obstack_1grow (&temporary_obstack
, c
);
294 if (obstack_object_size (&temporary_obstack
) == 0)
296 obstack_1grow (&temporary_obstack
, '\0');
297 return obstack_finish (&temporary_obstack
);
301 init_repo (const char *filename
)
305 if (! flag_use_repository
)
308 gcc_obstack_init (&temporary_obstack
);
310 open_repo_file (filename
);
315 while ((buf
= afgets (repo_file
)))
320 old_args
= ggc_strdup (buf
+ 2);
323 old_dir
= ggc_strdup (buf
+ 2);
326 old_main
= ggc_strdup (buf
+ 2);
331 tree id
= get_identifier (buf
+ 2);
336 IDENTIFIER_REPO_CHOSEN (id
) = 1;
337 orig
= integer_one_node
;
342 original_repo
= tree_cons (orig
, id
, original_repo
);
346 error ("mysterious repository information in %s", repo_name
);
348 obstack_free (&temporary_obstack
, buf
);
353 reopen_repo_file_for_write (void)
357 repo_file
= fopen (repo_name
, "w");
361 error ("can't create repository information file `%s'", repo_name
);
362 flag_use_repository
= 0;
366 /* Emit any pending repos. */
372 bool repo_changed
= false;
375 if (!flag_use_repository
)
378 /* Do we have to write out a new info file? */
380 /* Are there any old templates that aren't used any longer or that are
383 for (t
= original_repo
; t
; t
= TREE_CHAIN (t
))
385 if (!IDENTIFIER_REPO_USED (TREE_VALUE (t
))
386 || (!TREE_PURPOSE (t
) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t
))))
391 IDENTIFIER_REPO_USED (TREE_VALUE (t
)) = 0;
394 /* Are there any templates that are newly used? */
397 for (t
= pending_repo
; t
; t
= TREE_CHAIN (t
))
399 if (IDENTIFIER_REPO_USED (TREE_VALUE (t
)))
407 args
= getenv ("COLLECT_GCC_OPTIONS");
409 if (!repo_changed
&& pending_repo
)
410 if (strcmp (old_main
, main_input_filename
) != 0
411 || strcmp (old_dir
, dir
) != 0
412 || (args
== NULL
) != (old_args
== NULL
)
413 || (args
&& strcmp (old_args
, args
) != 0))
416 if (!repo_changed
|| errorcount
|| sorrycount
)
419 reopen_repo_file_for_write ();
424 fprintf (repo_file
, "M %s\n", main_input_filename
);
425 fprintf (repo_file
, "D %s\n", dir
);
427 fprintf (repo_file
, "A %s\n", args
);
429 for (t
= pending_repo
; t
; t
= TREE_CHAIN (t
))
431 tree val
= TREE_VALUE (t
);
432 char type
= IDENTIFIER_REPO_CHOSEN (val
) ? 'C' : 'O';
434 fprintf (repo_file
, "%c %s\n", type
, IDENTIFIER_POINTER (val
));
442 #include "gt-cp-repo.h"