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, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, 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"
41 static char *extract_string (char **);
42 static const char *get_base_filename (const char *);
43 static FILE *open_repo_file (const char *);
44 static char *afgets (FILE *);
45 static FILE *reopen_repo_file_for_write (void);
47 static GTY(()) tree pending_repo
;
48 static char *repo_name
;
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 return 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
);
159 if (! flag_use_repository
)
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
;
167 if (!temporary_obstack_initialized_p
)
168 gcc_obstack_init (&temporary_obstack
);
170 repo_file
= open_repo_file (main_input_filename
);
175 while ((buf
= afgets (repo_file
)))
180 old_args
= ggc_strdup (buf
+ 2);
183 old_dir
= ggc_strdup (buf
+ 2);
186 old_main
= ggc_strdup (buf
+ 2);
189 /* A symbol that we were able to define the last time this
190 file was compiled. */
193 /* A symbol that the prelinker has requested that we
196 tree id
= get_identifier (buf
+ 2);
197 IDENTIFIER_REPO_CHOSEN (id
) = 1;
201 error ("mysterious repository information in %s", repo_name
);
203 obstack_free (&temporary_obstack
, buf
);
209 reopen_repo_file_for_write (void)
211 FILE *repo_file
= fopen (repo_name
, "w");
215 error ("can't create repository information file %qs", repo_name
);
216 flag_use_repository
= 0;
222 /* Emit any pending repos. */
231 if (!flag_use_repository
)
234 if (errorcount
|| sorrycount
)
237 repo_file
= reopen_repo_file_for_write ();
241 fprintf (repo_file
, "M %s\n", main_input_filename
);
243 fprintf (repo_file
, "D %s\n", dir
);
244 args
= getenv ("COLLECT_GCC_OPTIONS");
247 fprintf (repo_file
, "A %s", args
);
248 /* If -frandom-seed is not among the ARGS, then add the value
249 that we chose. That will ensure that the names of types from
250 anonymous namespaces will get the same mangling when this
251 file is recompiled. */
252 if (!strstr (args
, "'-frandom-seed="))
253 fprintf (repo_file
, " '-frandom-seed=%s'", flag_random_seed
);
254 fprintf (repo_file
, "\n");
257 for (t
= pending_repo
; t
; t
= TREE_CHAIN (t
))
259 tree val
= TREE_VALUE (t
);
260 tree name
= DECL_ASSEMBLER_NAME (val
);
261 char type
= IDENTIFIER_REPO_CHOSEN (name
) ? 'C' : 'O';
262 fprintf (repo_file
, "%c %s\n", type
, IDENTIFIER_POINTER (name
));
270 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
271 definition is available in this translation unit. Returns 0 if
272 this definition should not be emitted in this translation unit
273 because it will be emitted elsewhere. Returns 1 if the repository
274 file indicates that that DECL should be emitted in this translation
275 unit, or 2 if the repository file is not in use. */
278 repo_emit_p (tree decl
)
280 gcc_assert (TREE_PUBLIC (decl
));
281 gcc_assert (TREE_CODE (decl
) == FUNCTION_DECL
282 || TREE_CODE (decl
) == VAR_DECL
);
283 gcc_assert (!DECL_REALLY_EXTERN (decl
));
285 /* When not using the repository, emit everything. */
286 if (!flag_use_repository
)
289 /* Only template instantiations are managed by the repository. This
290 is an artificial restriction; the code in the prelinker and here
291 will work fine if all entities with vague linkage are managed by
293 if (TREE_CODE (decl
) == VAR_DECL
)
295 tree type
= NULL_TREE
;
296 if (DECL_VTABLE_OR_VTT_P (decl
))
297 type
= DECL_CONTEXT (decl
);
298 else if (DECL_TINFO_P (decl
))
299 type
= TREE_TYPE (DECL_NAME (decl
));
300 if (!DECL_TEMPLATE_INSTANTIATION (decl
)
301 && (!TYPE_LANG_SPECIFIC (type
)
302 || !CLASSTYPE_TEMPLATE_INSTANTIATION (type
)))
304 /* Static data members initialized by constant expressions must
305 be processed where needed so that their definitions are
307 if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl
)
308 && DECL_CLASS_SCOPE_P (decl
))
311 else if (!DECL_TEMPLATE_INSTANTIATION (decl
))
314 /* For constructors and destructors, the repository contains
315 information about the clones -- not the original function --
316 because only the clones are emitted in the object file. */
317 if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl
)
318 || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl
))
322 /* There is no early exit from this loop because we want to
323 ensure that all of the clones are marked as available in this
325 FOR_EACH_CLONE (clone
, decl
)
326 /* The only possible results from the recursive call to
327 repo_emit_p are 0 or 1. */
328 if (repo_emit_p (clone
))
333 /* Keep track of all available entities. */
334 if (!DECL_REPO_AVAILABLE_P (decl
))
336 DECL_REPO_AVAILABLE_P (decl
) = 1;
337 pending_repo
= tree_cons (NULL_TREE
, decl
, pending_repo
);
340 return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl
));
343 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
344 export from this translation unit. */
347 repo_export_class_p (tree class_type
)
349 if (!flag_use_repository
)
351 if (!CLASSTYPE_VTABLES (class_type
))
353 /* If the virtual table has been assigned to this translation unit,
355 return (IDENTIFIER_REPO_CHOSEN
356 (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type
))));
359 #include "gt-cp-repo.h"