1 /* Code to maintain a C++ template repository.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
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 char *extract_string (char **);
41 static const char *get_base_filename (const char *);
42 static void open_repo_file (const char *);
43 static char *afgets (FILE *);
44 static void reopen_repo_file_for_write (void);
46 static GTY(()) tree pending_repo
;
47 static char *repo_name
;
48 static FILE *repo_file
;
50 static const char *old_args
, *old_dir
, *old_main
;
52 static struct obstack temporary_obstack
;
53 static bool temporary_obstack_initialized_p
;
55 /* Parse a reasonable subset of shell quoting syntax. */
58 extract_string (char **pp
)
72 obstack_1grow (&temporary_obstack
, c
);
75 else if (! inside
&& c
== ' ')
77 else if (! inside
&& c
== '\\')
82 obstack_1grow (&temporary_obstack
, c
);
85 obstack_1grow (&temporary_obstack
, '\0');
87 return obstack_finish (&temporary_obstack
);
91 get_base_filename (const char *filename
)
93 char *p
= getenv ("COLLECT_GCC_OPTIONS");
99 char *q
= extract_string (&p
);
101 if (strcmp (q
, "-o") == 0)
102 output
= extract_string (&p
);
103 else if (strcmp (q
, "-c") == 0)
107 if (compiling
&& output
)
110 if (p
&& ! compiling
)
112 warning (0, "-frepo must be used with -c");
113 flag_use_repository
= 0;
117 return lbasename (filename
);
121 open_repo_file (const char *filename
)
124 const char *s
= get_base_filename (filename
);
130 p
= strrchr (p
, '.');
134 repo_name
= xmalloc (p
- s
+ 5);
135 memcpy (repo_name
, s
, p
- s
);
136 memcpy (repo_name
+ (p
- s
), ".rpo", 5);
138 repo_file
= fopen (repo_name
, "r");
142 afgets (FILE *stream
)
145 while ((c
= getc (stream
)) != EOF
&& c
!= '\n')
146 obstack_1grow (&temporary_obstack
, c
);
147 if (obstack_object_size (&temporary_obstack
) == 0)
149 obstack_1grow (&temporary_obstack
, '\0');
150 return obstack_finish (&temporary_obstack
);
158 if (! flag_use_repository
)
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
;
166 if (!temporary_obstack_initialized_p
)
167 gcc_obstack_init (&temporary_obstack
);
169 open_repo_file (main_input_filename
);
174 while ((buf
= afgets (repo_file
)))
179 old_args
= ggc_strdup (buf
+ 2);
182 old_dir
= ggc_strdup (buf
+ 2);
185 old_main
= ggc_strdup (buf
+ 2);
188 /* A symbol that we were able to define the last time this
189 file was compiled. */
192 /* A symbol that the prelinker has requested that we
195 tree id
= get_identifier (buf
+ 2);
196 IDENTIFIER_REPO_CHOSEN (id
) = 1;
200 error ("mysterious repository information in %s", repo_name
);
202 obstack_free (&temporary_obstack
, buf
);
208 reopen_repo_file_for_write (void)
210 repo_file
= fopen (repo_name
, "w");
214 error ("can't create repository information file %qs", repo_name
);
215 flag_use_repository
= 0;
219 /* Emit any pending repos. */
227 if (!flag_use_repository
)
230 if (errorcount
|| sorrycount
)
233 reopen_repo_file_for_write ();
237 fprintf (repo_file
, "M %s\n", main_input_filename
);
239 fprintf (repo_file
, "D %s\n", dir
);
240 args
= getenv ("COLLECT_GCC_OPTIONS");
242 fprintf (repo_file
, "A %s\n", args
);
244 for (t
= pending_repo
; t
; t
= TREE_CHAIN (t
))
246 tree val
= TREE_VALUE (t
);
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
));
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. */
265 repo_emit_p (tree decl
)
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
));
272 /* When not using the repository, emit everything. */
273 if (!flag_use_repository
)
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
280 if (TREE_CODE (decl
) == VAR_DECL
)
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
))
291 else if (!DECL_TEMPLATE_INSTANTIATION (decl
))
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
))
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
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
))
313 /* Keep track of all available entities. */
314 if (!DECL_REPO_AVAILABLE_P (decl
))
316 DECL_REPO_AVAILABLE_P (decl
) = 1;
317 pending_repo
= tree_cons (NULL_TREE
, decl
, pending_repo
);
320 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl
));
323 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
324 export from this translation unit. */
327 repo_export_class_p (tree class_type
)
329 if (!flag_use_repository
)
331 if (!CLASSTYPE_VTABLES (class_type
))
333 /* If the virtual table has been assigned to this translation unit,
335 return (IDENTIFIER_REPO_CHOSEN
336 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type
))));
339 #include "gt-cp-repo.h"