c-common.h (lang_post_pch_load): New variable.

* c-common.h (lang_post_pch_load): New variable.
	* c-pch.c (lang_post_pch_load): Define it.
	(c_common_read_pch): Use it.
	* cgraphunit.c (record_call_1): Give the front end a chance to
	record additional needed entities when a variable is marked as
	needed.
	* tlink.c (recompile_files): Robustify.
	(scan_linker_output): If a symbol is assigned to a file,
	but after recompilation is not present there, issue an error
	message.

	* cp-tree.h (IDENTIFIER_REPO_CHOSEN): Define.
	(lang_decl_flags): Narrow the width of "languages".  Add
	repo_available_p.
	(DECL_NEEDED_P): Remove.
	(FOR_EACH_CLONE): New macro.
	(DECL_REPO_AVAILABLE_P): Likewise.
	(DECL_TINFO_P): Likewise.
	(set_linkage_according_to_type): Declare.
	(import_export_vtable): Remove.
	(import_export_tinfo): Likewise.
	(mark_needed): New function.
	(decl_needed_p): Likewise.
	(note_vauge_linkage_fn): Likewise.
	(init_repo): Change prototype.
	(repo_template_used): Remove.
	(repo_template_instantiated): Likewise.
	(repo_emit_p): New function.
	(repo_export_class_p): Likewise.
	(no_linkage_check): Change prototype.
	* class.c (set_linkage_according_to_type): New function.
	(build_vtable): Use it.  Do not call import_export_vtable.  Set
	DECL_IGNORED_P if appropriate.
	* decl.c (duplicate_decls): Preserve DECL_REPO_AVAILABLE_P.
	(make_rtL_for_nonlocal_decls): Check for template instantiations
	explicitly.
	(grokfndecl): Adjust call to no_linkage_check.
	(set_linkage_for_static_data_member): New function.
	(grokvardecl): Use it.  Adjust call to no_linkage_check.
	(grokdeclarator): Use set_linkage_for_static_data_member.
	* decl2.c (note_vague_linkage_fn): New function.
	(note_vague_linkage_var): Likewise.
	(finish_static_data_member_decl): Use it.
	(import_export_vtable): Remove.
	(import_export_class): Use repo_export_class_p.
	(var_finalized_p): Simplify.
	(maybe_emit_vtables): Simplify.
	(mark_needed): New function.
	(decl_needed_p): Likewise.
	(import_export_decl): Add documentation and consistency checks.
	Use repo_emit_p.  Handle virtual tables and RTTI information
	here.
	(import_export_tinfo): Remove.
	(write_out_vars): Call import_export_decl.
	(cxx_callgraph_analyze_expr): Ensure that all vtables are emitted
	whenever one is.
	(finish_file): Use decl_needed_p.  Do not call import_export_decl
	for undefined static data members.  Do not warn about undefined
	inlines when using a repository.
	(mark_used): Use note_vague_linkage_fn.  Always defer template
	instantiations.
	* lex.c (cxx_init): Adjust call to init_repo.  Always set
	flag_unit_at_a-time.
	* method.c (synthesize_method): Remove unncessary
	import_export_decl call.
	(implicitly_declare_fn): Use set_linkage_according_to_type.
	* optimize.c (maybe_clone_body): Use FOR_EACH_CLONE.
	* pt.c (instantiate_class_template): Don't redundantly add classes
	to keyed_classes.  Don't call repo_template_used.
	(tsubst_decl): Set DECL_INTERFACE_KNOWN for instantiations of
	templates with internal linkage.
	(check_instantiated_args): Adjust call to no_linkage_check.
	(instantiate_template): Use FOR_EACH_CLONE.
	(mark_definable): New function.
	(mark_decl_instantiated): Use it.
	(do_decl_instantiation): Adjust tests for explicit instantiation
	after "extern template".
	(instantiate_class_member): Do not use repo_template_instantiated.
	(do_type_instantiation): Simplify.
	(instantiate_decl): Use mark_definable.  Check repo_emit_p.
	Simplify.
	* repo.c (repo_get_id): Remove.
	(original_repo): Remove.
	(IDENTIFIER_REPO_USED): Remove.
	(IDENTIFIER_REPO_CHOSEN): Remove.
	Remove all #if 0'd code.
	(repo_template_used): Remove.
	(repo_template_instantiated): Remove.
	(temporary_obstack_initialized_p): New variable.
	(init_repo): Register with lang_post_pch_load.  Avoid creating
	identifiers unnecessarily.  Don't use original_repo.  Close the
	file here.
	(reopen_repo_file_for_write): Not here.
	(finish_repo): Always write out a new repository file.
	(repo_emit_p): New function.
	(repo_export_class_p): Likewise.
	* rtti.c (get_tinfo_decl): Use set_linkage_according_to_type.
	(involves_incomplete_p): New function.
	(tinfo_base_init): Use it.
	(ptr_initializer): Remove non_public_ptr parameter.
	(ptm_initializer): Likewise.
	(get_pseudo_ti_init): Likewise.
	(unemitted_tinfo_decl_p): Remove.
	(emit_tinfo_decl): Use import_export_decl.
	* semantics.c (expand_body): Move updates of static_ctors and
	static_dtors to ...
	(expand_or_defer_fn): ... here.
	* tree.c (no_linkage_check): Add relaxed_p parameter.

	* g++.dg/abi/inline1.C: New test.
	* g++.dg/abi/local1-a.cc: Likewise.
	* g++.dg/abi/local1.C: Likewise.
	* g++.dg/abi/mangle11.C: Tweak location of warnings.
	* g++.dg/abi/mangle12.C: Likewise.
	* g++.dg/abi/mangle17.C: Likewise.
	* g++.dg/abi/mangle20-2.C: Likewise.
	* g++.dg/opt/interface1.C: Likewise.
	* g++.dg/opt/interface1.h: Likewise.
	* g++.dg/opt/interface1-a.cc: New test.
	* g++.dg/parse/repo1.C: New test.
	* g++.dg/template/repo1.C: Likewise.
	* g++.dg/warn/Winline-1.C: Likewise.
	* lib/gcc-dg.exp (gcc-dg-test-1): Fix -frepo handling.

From-SVN: r85309
This commit is contained in:
Mark Mitchell 2004-07-29 17:59:31 +00:00 committed by Mark Mitchell
parent b4042a039f
commit 4684cd27fc
33 changed files with 1133 additions and 772 deletions

View File

@ -1,3 +1,16 @@
2004-07-29 Mark Mitchell <mark@codesourcery.com>
* c-common.h (lang_post_pch_load): New variable.
* c-pch.c (lang_post_pch_load): Define it.
(c_common_read_pch): Use it.
* cgraphunit.c (record_call_1): Give the front end a chance to
record additional needed entities when a variable is marked as
needed.
* tlink.c (recompile_files): Robustify.
(scan_linker_output): If a symbol is assigned to a file,
but after recompilation is not present there, issue an error
message.
2004-07-29 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* tree-ssa-loop-im.c (force_move_till_expr, force_move_till):

View File

@ -286,6 +286,10 @@ extern void (*lang_expand_function_end) (void);
noreturn attribute. */
extern int (*lang_missing_noreturn_ok_p) (tree);
/* If non-NULL, this function is called after a precompile header file
is loaded. */
extern void (*lang_post_pch_load) (void);
extern void push_file_scope (void);
extern void pop_file_scope (void);
extern int yyparse (void);

View File

@ -384,6 +384,10 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
return result == 0;
}
/* If non-NULL, this function is called after a precompile header file
is loaded. */
void (*lang_post_pch_load) (void);
/* Load in the PCH file NAME, open on FD. It was originally searched for
by ORIG_NAME. */
@ -443,6 +447,11 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
return;
fclose (f);
/* Give the front end a chance to take action after a PCH file has
been loadeded. */
if (lang_post_pch_load)
(*lang_post_pch_load) ();
}
/* Indicate that no more PCH files should be read. */

View File

@ -400,7 +400,12 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
by this function and re-examine whether the decl is actually used
after rtl has been generated. */
if (TREE_STATIC (t))
cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
{
cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
if (lang_hooks.callgraph.analyze_expr)
return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees,
data);
}
break;
case ADDR_EXPR:

View File

@ -1,3 +1,103 @@
2004-07-29 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (IDENTIFIER_REPO_CHOSEN): Define.
(lang_decl_flags): Narrow the width of "languages". Add
repo_available_p.
(DECL_NEEDED_P): Remove.
(FOR_EACH_CLONE): New macro.
(DECL_REPO_AVAILABLE_P): Likewise.
(DECL_TINFO_P): Likewise.
(set_linkage_according_to_type): Declare.
(import_export_vtable): Remove.
(import_export_tinfo): Likewise.
(mark_needed): New function.
(decl_needed_p): Likewise.
(note_vauge_linkage_fn): Likewise.
(init_repo): Change prototype.
(repo_template_used): Remove.
(repo_template_instantiated): Likewise.
(repo_emit_p): New function.
(repo_export_class_p): Likewise.
(no_linkage_check): Change prototype.
* class.c (set_linkage_according_to_type): New function.
(build_vtable): Use it. Do not call import_export_vtable. Set
DECL_IGNORED_P if appropriate.
* decl.c (duplicate_decls): Preserve DECL_REPO_AVAILABLE_P.
(make_rtL_for_nonlocal_decls): Check for template instantiations
explicitly.
(grokfndecl): Adjust call to no_linkage_check.
(set_linkage_for_static_data_member): New function.
(grokvardecl): Use it. Adjust call to no_linkage_check.
(grokdeclarator): Use set_linkage_for_static_data_member.
* decl2.c (note_vague_linkage_fn): New function.
(note_vague_linkage_var): Likewise.
(finish_static_data_member_decl): Use it.
(import_export_vtable): Remove.
(import_export_class): Use repo_export_class_p.
(var_finalized_p): Simplify.
(maybe_emit_vtables): Simplify.
(mark_needed): New function.
(decl_needed_p): Likewise.
(import_export_decl): Add documentation and consistency checks.
Use repo_emit_p. Handle virtual tables and RTTI information
here.
(import_export_tinfo): Remove.
(write_out_vars): Call import_export_decl.
(cxx_callgraph_analyze_expr): Ensure that all vtables are emitted
whenever one is.
(finish_file): Use decl_needed_p. Do not call import_export_decl
for undefined static data members. Do not warn about undefined
inlines when using a repository.
(mark_used): Use note_vague_linkage_fn. Always defer template
instantiations.
* lex.c (cxx_init): Adjust call to init_repo. Always set
flag_unit_at_a-time.
* method.c (synthesize_method): Remove unncessary
import_export_decl call.
(implicitly_declare_fn): Use set_linkage_according_to_type.
* optimize.c (maybe_clone_body): Use FOR_EACH_CLONE.
* pt.c (instantiate_class_template): Don't redundantly add classes
to keyed_classes. Don't call repo_template_used.
(tsubst_decl): Set DECL_INTERFACE_KNOWN for instantiations of
templates with internal linkage.
(check_instantiated_args): Adjust call to no_linkage_check.
(instantiate_template): Use FOR_EACH_CLONE.
(mark_definable): New function.
(mark_decl_instantiated): Use it.
(do_decl_instantiation): Adjust tests for explicit instantiation
after "extern template".
(instantiate_class_member): Do not use repo_template_instantiated.
(do_type_instantiation): Simplify.
(instantiate_decl): Use mark_definable. Check repo_emit_p.
Simplify.
* repo.c (repo_get_id): Remove.
(original_repo): Remove.
(IDENTIFIER_REPO_USED): Remove.
(IDENTIFIER_REPO_CHOSEN): Remove.
Remove all #if 0'd code.
(repo_template_used): Remove.
(repo_template_instantiated): Remove.
(temporary_obstack_initialized_p): New variable.
(init_repo): Register with lang_post_pch_load. Avoid creating
identifiers unnecessarily. Don't use original_repo. Close the
file here.
(reopen_repo_file_for_write): Not here.
(finish_repo): Always write out a new repository file.
(repo_emit_p): New function.
(repo_export_class_p): Likewise.
* rtti.c (get_tinfo_decl): Use set_linkage_according_to_type.
(involves_incomplete_p): New function.
(tinfo_base_init): Use it.
(ptr_initializer): Remove non_public_ptr parameter.
(ptm_initializer): Likewise.
(get_pseudo_ti_init): Likewise.
(unemitted_tinfo_decl_p): Remove.
(emit_tinfo_decl): Use import_export_decl.
* semantics.c (expand_body): Move updates of static_ctors and
static_dtors to ...
(expand_or_defer_fn): ... here.
* tree.c (no_linkage_check): Add relaxed_p parameter.
2004-07-28 Eric Christopher <echristo@redhat.com>
* cp-lang.c (LANG_HOOKS_UNSAFE_FOR_REEVAL): Delete.

View File

@ -581,6 +581,32 @@ get_vtt_name (tree type)
return mangle_vtt_for_type (type);
}
/* DECL is an entity associated with TYPE, like a virtual table or an
implicitly generated constructor. Determine whether or not DECL
should have external or internal linkage at the object file
level. This routine does not deal with COMDAT linkage and other
similar complexities; it simply sets TREE_PUBLIC if it possible for
entities in other translation units to contain copies of DECL, in
the abstract. */
void
set_linkage_according_to_type (tree type, tree decl)
{
/* If TYPE involves a local class in a function with internal
linkage, then DECL should have internal linkage too. Other local
classes have no linkage -- but if their containing functions
have external linkage, it makes sense for DECL to have external
linkage too. That will allow template definitions to be merged,
for example. */
if (no_linkage_check (type, /*relaxed_p=*/true))
{
TREE_PUBLIC (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
TREE_PUBLIC (decl) = 1;
}
/* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
(For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */
@ -601,17 +627,42 @@ build_vtable (tree class_type, tree name, tree vtable_type)
DECL_VIRTUAL_P (decl) = 1;
DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
DECL_VTABLE_OR_VTT_P (decl) = 1;
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (decl));
set_linkage_according_to_type (class_type, decl);
/* The vtable has not been defined -- yet. */
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 1;
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
/* Mark the VAR_DECL node representing the vtable itself as a
"gratuitous" one, thereby forcing dwarfout.c to ignore it. It
is rather important that such things be ignored because any
effort to actually generate DWARF for them will run into
trouble when/if we encounter code like:
#pragma interface
struct S { virtual void member (); };
because the artificial declaration of the vtable itself (as
manufactured by the g++ front end) will say that the vtable is
a static member of `S' but only *after* the debug output for
the definition of `S' has already been output. This causes
grief because the DWARF entry for the definition of the vtable
will try to refer back to an earlier *declaration* of the
vtable as a static member of `S' and there won't be one. We
might be able to arrange to have the "vtable static member"
attached to the member list for `S' before the debug info for
`S' get written (which would solve the problem) but that would
require more intrusive changes to the g++ front end. */
DECL_IGNORED_P (decl) = 1;
/* The vtable's visibility is the class visibility. There is no way
to override the visibility for just the vtable. */
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
DECL_VISIBILITY_SPECIFIED (decl) = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
import_export_vtable (decl, class_type, 0);
return decl;
}

View File

@ -48,7 +48,7 @@ struct diagnostic_context;
STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
1: IDENTIFIER_VIRTUAL_P.
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
DELETE_EXPR_USE_VEC (in DELETE_EXPR).
@ -56,7 +56,7 @@ struct diagnostic_context;
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
ICS_ELLIPSIS_FLAG (in _CONV)
DECL_INITIALIZED_P (in VAR_DECL)
2: IDENTIFIER_OPNAME_P.
2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
TYPE_POLYMORPHIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@ -70,9 +70,10 @@ struct diagnostic_context;
4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
DECL_TINFO_P (in VAR_DECL)
5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
DECL_VTABLE_OR_VTT_P (in VAR_DECL)
6: For future expansion
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
@ -375,6 +376,12 @@ typedef enum cp_id_kind
#define IDENTIFIER_CTOR_OR_DTOR_P(NODE) \
TREE_LANG_FLAG_3 (NODE)
/* True iff NAME is the DECL_ASSEMBLER_NAME for an entity with vague
linkage which the prelinker has assigned to this translation
unit. */
#define IDENTIFIER_REPO_CHOSEN(NAME) \
(TREE_LANG_FLAG_6 (NAME))
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(TYPE) \
(LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly)
@ -1515,7 +1522,11 @@ struct lang_type GTY(())
struct lang_decl_flags GTY(())
{
ENUM_BITFIELD(languages) language : 8;
ENUM_BITFIELD(languages) language : 4;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
unsigned anticipated_p : 1;
unsigned template_conv_p : 1;
unsigned operator_attr : 1;
unsigned constructor_attr : 1;
@ -1534,14 +1545,12 @@ struct lang_decl_flags GTY(())
unsigned initialized_in_class : 1;
unsigned assignment_operator_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
unsigned anticipated_p : 1;
unsigned template_conv_p : 1;
unsigned u1sel : 1;
unsigned u2sel : 1;
unsigned can_be_full : 1;
unsigned this_thunk_p : 1;
unsigned repo_available_p : 1;
unsigned dummy : 3;
union lang_decl_u {
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
@ -1631,19 +1640,6 @@ struct lang_decl GTY(())
#endif /* ENABLE_TREE_CHECKING */
/* DECL_NEEDED_P holds of a declaration when we need to emit its
definition. This is true when the back-end tells us that
the symbol has been referenced in the generated code. If, however,
we are not generating code, then it is also true when a symbol has
just been used somewhere, even if it's not really needed. We need
anything that isn't comdat, but we don't know for sure whether or
not something is comdat until end-of-file. */
#define DECL_NEEDED_P(DECL) \
((at_eof && TREE_PUBLIC (DECL) && !DECL_COMDAT (DECL)) \
|| (DECL_ASSEMBLER_NAME_SET_P (DECL) \
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \
|| (((flag_syntax_only || flag_unit_at_a_time) && TREE_USED (DECL))))
/* For a FUNCTION_DECL or a VAR_DECL, the language linkage for the
declaration. Some entities (like a member function in a local
class, or a local variable) do not have linkage at all, and this
@ -1730,6 +1726,21 @@ struct lang_decl GTY(())
#define DECL_CLONED_FUNCTION(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function)
/* Perform an action for each clone of FN, if FN is a function with
clones. This macro should be used like:
FOR_EACH_CLONE (clone, fn)
{ ... }
*/
#define FOR_EACH_CLONE(CLONE, FN) \
if (TREE_CODE (FN) == FUNCTION_DECL \
&& (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (FN) \
|| DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (FN))) \
for (CLONE = TREE_CHAIN (FN); \
CLONE && DECL_CLONED_FUNCTION_P (CLONE); \
CLONE = TREE_CHAIN (CLONE))
/* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */
#define DECL_DISCRIMINATOR_P(NODE) \
(TREE_CODE (NODE) == VAR_DECL \
@ -1921,6 +1932,11 @@ struct lang_decl GTY(())
DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \
DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING))
/* True iff DECL is an entity with vague linkage whose definition is
available in this translation unit. */
#define DECL_REPO_AVAILABLE_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.repo_available_p)
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
#define DECL_PRETTY_FUNCTION_P(NODE) \
@ -1965,6 +1981,10 @@ struct lang_decl GTY(())
(DECL_CONTEXT (NODE) \
&& TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
/* 1 iff VAR_DECL node NODE is a type-info decl. This flag is set for
both the primary typeinfo object and the associated NTBS name. */
#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE))
/* 1 iff VAR_DECL node NODE is virtual table or VTT. */
#define DECL_VTABLE_OR_VTT_P(NODE) TREE_LANG_FLAG_5 (VAR_DECL_CHECK (NODE))
@ -3643,6 +3663,7 @@ extern tree get_primary_binfo (tree);
extern void debug_class (tree);
extern void debug_thunks (tree);
extern tree cp_fold_obj_type_ref (tree, tree);
extern void set_linkage_according_to_type (tree, tree);
/* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree);
@ -3787,9 +3808,7 @@ extern tree finish_table (tree, tree, tree, int);
extern tree coerce_new_type (tree);
extern tree coerce_delete_type (tree);
extern void comdat_linkage (tree);
extern void import_export_vtable (tree, tree, int);
extern void import_export_decl (tree);
extern void import_export_tinfo (tree, tree, bool);
extern tree build_cleanup (tree);
extern tree build_offset_ref_call_from_tree (tree, tree);
extern void check_default_args (tree);
@ -3801,6 +3820,9 @@ extern tree get_guard (tree);
extern tree get_guard_cond (tree);
extern tree set_guard (tree);
extern tree cxx_callgraph_analyze_expr (tree *, int *, tree);
extern void mark_needed (tree);
extern bool decl_needed_p (tree);
extern void note_vague_linkage_fn (tree);
/* XXX Not i18n clean. */
#define cp_deprecated(STR) \
@ -3973,9 +3995,9 @@ extern bool reregister_specialization (tree, tree, tree);
extern tree fold_non_dependent_expr (tree);
/* in repo.c */
extern void repo_template_used (tree);
extern void repo_template_instantiated (tree, bool);
extern void init_repo (const char *);
extern void init_repo (void);
extern int repo_emit_p (tree);
extern bool repo_export_class_p (tree);
extern void finish_repo (void);
/* in rtti.c */
@ -4192,7 +4214,7 @@ extern tree error_type (tree);
extern int varargs_function_p (tree);
extern int really_overloaded_fn (tree);
extern bool cp_tree_equal (tree, tree);
extern tree no_linkage_check (tree);
extern tree no_linkage_check (tree, bool);
extern void debug_binfo (tree);
extern tree build_dummy_object (tree);
extern tree maybe_dummy_object (tree, tree *);

View File

@ -1753,6 +1753,7 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
@ -4571,7 +4572,8 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
defer_p = 1;
}
/* Likewise for template instantiations. */
else if (DECL_COMDAT (decl))
else if (DECL_LANG_SPECIFIC (decl)
&& DECL_IMPLICIT_INSTANTIATION (decl))
defer_p = 1;
/* If we're deferring the variable, we only need to make RTL if
@ -5513,7 +5515,8 @@ grokfndecl (tree ctype,
declare an entity with linkage.
Only check this for public decls for now. See core 319, 389. */
t = no_linkage_check (TREE_TYPE (decl));
t = no_linkage_check (TREE_TYPE (decl),
/*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
@ -5723,6 +5726,25 @@ grokfndecl (tree ctype,
return decl;
}
/* DECL is a VAR_DECL for a static data member. Set flags to reflect
the linkage that DECL will receive in the object file. */
static void
set_linkage_for_static_data_member (tree decl)
{
/* A static data member always has static storage duration and
external linkage. Note that static data members are forbidden in
local classes -- the only situation in which a class has
non-external linkage. */
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
/* For non-template classes, static data members are always put
out in exactly those files where they are defined, just as
with ordinarly namespace-scope variables. */
if (!processing_template_decl)
DECL_INTERFACE_KNOWN (decl) = 1;
}
/* Create a VAR_DECL named NAME with the indicated TYPE.
If SCOPE is non-NULL, it is the class type or namespace containing
@ -5782,12 +5804,10 @@ grokvardecl (tree type,
DECL_EXTERNAL (decl) = !initialized;
}
/* In class context, static means one per class,
public access, and static storage. */
if (DECL_CLASS_SCOPE_P (decl))
{
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
set_linkage_for_static_data_member (decl);
/* This function is only called with out-of-class definitions. */
DECL_EXTERNAL (decl) = 0;
}
/* At top level, either `static' or no s.c. makes a definition
@ -5822,7 +5842,8 @@ grokvardecl (tree type,
declare an entity with linkage.
Only check this for public decls for now. */
tree t = no_linkage_check (TREE_TYPE (decl));
tree t = no_linkage_check (TREE_TYPE (decl),
/*relaxed_p=*/false);
if (t)
{
if (TYPE_ANONYMOUS_P (t))
@ -7859,9 +7880,11 @@ grokdeclarator (const cp_declarator *declarator,
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl (VAR_DECL, unqualified_id, type);
TREE_STATIC (decl) = 1;
/* In class context, 'static' means public access. */
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
set_linkage_for_static_data_member (decl);
/* Even if there is an in-class initialization, DECL
is considered undefined until an out-of-class
definition is provided. */
DECL_EXTERNAL (decl) = 1;
}
else
{
@ -9842,6 +9865,11 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
/* If this function is in an interface implemented in this file,
make sure that the backend knows to emit this function
here. */
if (!DECL_EXTERNAL (decl1))
mark_needed (decl1);
}
else if (interface_unknown && interface_only
&& ! DECL_TEMPLATE_INSTANTIATION (decl1))

View File

@ -729,6 +729,33 @@ check_classfn (tree ctype, tree function, tree template_parms)
return NULL_TREE;
}
/* DECL is a function with vague linkage. Remember it so that at the
end of the translation unit we can decide whether or not to emit
it. */
void
note_vague_linkage_fn (tree decl)
{
if (!DECL_DEFERRED_FN (decl))
{
DECL_DEFERRED_FN (decl) = 1;
DECL_DEFER_OUTPUT (decl) = 1;
if (!deferred_fns)
VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
VARRAY_PUSH_TREE (deferred_fns, decl);
}
}
/* Like note_vague_linkage_fn but for variables. */
static void
note_vague_linkage_var (tree var)
{
if (!pending_statics)
VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
VARRAY_PUSH_TREE (pending_statics, var);
}
/* We have just processed the DECL, which is a static data member.
Its initializer, if present, is INIT. The ASMSPEC_TREE, if
present, is the assembly-language name for the data member.
@ -750,11 +777,7 @@ finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
DECL_INITIAL (decl) = error_mark_node;
if (! processing_template_decl)
{
if (!pending_statics)
VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
VARRAY_PUSH_TREE (pending_statics, decl);
}
note_vague_linkage_var (decl);
if (LOCAL_CLASS_P (current_class_type))
pedwarn ("local class `%#T' shall not have static data member `%#D'",
@ -1403,51 +1426,6 @@ maybe_make_one_only (tree decl)
}
}
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
based on TYPE and other static flags.
Note that anything public is tagged TREE_PUBLIC, whether
it's public in this file or in another one. */
void
import_export_vtable (tree decl, tree type, int final)
{
if (DECL_INTERFACE_KNOWN (decl))
return;
if (TYPE_FOR_JAVA (type))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type);
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
{
/* We can only wait to decide if we have real non-inline virtual
functions in our class, or if we come from a template. */
int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
|| CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
if (final || ! found)
{
comdat_linkage (decl);
DECL_EXTERNAL (decl) = 0;
}
else
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
}
}
}
/* Determine whether or not we want to specifically import or export CTYPE,
using various heuristics. */
@ -1479,21 +1457,18 @@ import_export_class (tree ctype)
import_export = -1;
else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
/* If we got -fno-implicit-templates, we import template classes that
weren't explicitly instantiated. */
if (import_export == 0
&& CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
&& ! flag_implicit_templates)
import_export = -1;
/* Base our import/export status on that of the first non-inline,
non-pure virtual function, if any. */
if (import_export == 0
&& TYPE_POLYMORPHIC_P (ctype))
else if (CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
&& !flag_implicit_templates)
/* For a template class, without -fimplicit-templates, check the
repository. If the virtual table is assigned to this
translation unit, then export the class; otherwise, import
it. */
import_export = repo_export_class_p (ctype) ? 1 : -1;
else if (TYPE_POLYMORPHIC_P (ctype))
{
/* The ABI specifies that the virtual table and associated
information are emitted with the key method, if any. */
tree method = CLASSTYPE_KEY_METHOD (ctype);
/* If weak symbol support is not available, then we must be
careful not to emit the vtable when the key function is
inline. An inline function can be defined in multiple
@ -1525,10 +1500,52 @@ import_export_class (tree ctype)
static bool
var_finalized_p (tree var)
{
if (flag_unit_at_a_time)
return cgraph_varpool_node (var)->finalized;
else
return TREE_ASM_WRITTEN (var);
return cgraph_varpool_node (var)->finalized;
}
/* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
must be emitted in this translation unit. Mark it as such. */
void
mark_needed (tree decl)
{
/* It's possible that we no longer need to set
TREE_SYMBOL_REFERENCED here directly, but doing so is
harmless. */
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
mark_decl_referenced (decl);
}
/* DECL is either a FUNCTION_DECL or a VAR_DECL. This function
returns true if a definition of this entity should be provided in
this object file. Callers use this function to determine whether
or not to let the back end know that a definition of DECL is
available in this translation unit. */
bool
decl_needed_p (tree decl)
{
my_friendly_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL,
20040726);
/* This function should only be called at the end of the translation
unit. We cannot be sure of whether or not something will be
COMDAT until that point. */
my_friendly_assert (at_eof, 20040726);
/* All entities with external linkage that are not COMDAT should be
emitted; they may be referred to from other object files. */
if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
return true;
/* If this entity was used, let the back-end see it; it will decide
whether or not to emit it into the object file. */
if (TREE_USED (decl)
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
return true;
/* Otherwise, DECL does not need to be emitted -- yet. A subsequent
reference to DECL might cause it to be emitted later. */
return false;
}
/* If necessary, write out the vtables for the dynamic class CTYPE.
@ -1539,8 +1556,7 @@ maybe_emit_vtables (tree ctype)
{
tree vtbl;
tree primary_vtbl;
bool needed = false;
bool weaken_vtables;
int needed = 0;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
@ -1551,16 +1567,14 @@ maybe_emit_vtables (tree ctype)
if (TREE_TYPE (primary_vtbl) == void_type_node)
return false;
import_export_class (ctype);
/* See if any of the vtables are needed. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
import_export_vtable (vtbl, ctype, 1);
if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
break;
import_export_decl (vtbl);
if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl))
needed = 1;
}
if (!vtbl)
if (!needed)
{
/* If the references to this class' vtables are optimized away,
still emit the appropriate debugging information. See
@ -1570,45 +1584,14 @@ maybe_emit_vtables (tree ctype)
note_debug_info_needed (ctype);
return false;
}
else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl))
needed = true;
/* Determine whether to make vtables weak. The ABI requires that we
do so. There are two cases in which we have to violate the ABI
specification: targets where we don't have weak symbols
(obviously), and targets where weak symbols don't appear in
static archives' tables of contents. On such targets, avoiding
undefined symbol link errors requires that we only make a symbol
weak if we know that it will be emitted everywhere it's needed.
So on such targets we don't make vtables weak in the common case
where we're emitting a vtable of a nontemplate class in the
translation unit containing the definition of a noninline key
method. */
if (flag_weak && !TARGET_WEAK_NOT_IN_ARCHIVE_TOC)
weaken_vtables = true;
else if (flag_weak)
{
if (CLASSTYPE_USE_TEMPLATE (ctype))
weaken_vtables = CLASSTYPE_IMPLICIT_INSTANTIATION (ctype);
else
weaken_vtables = !CLASSTYPE_KEY_METHOD (ctype)
|| DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (ctype));
}
else
weaken_vtables = false;
/* The ABI requires that we emit all of the vtables if we emit any
of them. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
/* Write it out. */
import_export_vtable (vtbl, ctype, 1);
/* Mark entities references from the virtual table as used. */
mark_vtable_entries (vtbl);
/* If we know that DECL is needed, mark it as such for the varpool. */
if (needed)
cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
{
/* It had better be all done at compile-time. */
@ -1616,36 +1599,8 @@ maybe_emit_vtables (tree ctype)
abort ();
}
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
/* Mark the VAR_DECL node representing the vtable itself as a
"gratuitous" one, thereby forcing dwarfout.c to ignore it.
It is rather important that such things be ignored because
any effort to actually generate DWARF for them will run
into trouble when/if we encounter code like:
#pragma interface
struct S { virtual void member (); };
because the artificial declaration of the vtable itself (as
manufactured by the g++ front end) will say that the vtable
is a static member of `S' but only *after* the debug output
for the definition of `S' has already been output. This causes
grief because the DWARF entry for the definition of the vtable
will try to refer back to an earlier *declaration* of the
vtable as a static member of `S' and there won't be one.
We might be able to arrange to have the "vtable static member"
attached to the member list for `S' before the debug info for
`S' get written (which would solve the problem) but that would
require more intrusive changes to the g++ front end. */
DECL_IGNORED_P (vtbl) = 1;
}
/* Always make vtables weak. Or at least almost always; see above. */
if (weaken_vtables)
comdat_linkage (vtbl);
/* Write it out. */
DECL_EXTERNAL (vtbl) = 0;
rest_of_decl_compilation (vtbl, NULL, 1, 1);
/* Because we're only doing syntax-checking, we'll never end up
@ -1661,38 +1616,194 @@ maybe_emit_vtables (tree ctype)
return true;
}
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
inline function or template instantiation at end-of-file. */
/* DECL is a FUNCTION_DECL or VAR_DECL. If the object file linkage
for DECL has not already been determined, do so now by setting
DECL_EXTERNAL, DECL_COMDAT and other related flags. Until this
function is called entities with vague linkage whose definitions
are available must have TREE_PUBLIC set.
If this function decides to place DECL in COMDAT, it will set
appropriate flags -- but will not clear DECL_EXTERNAL. It is up to
the caller to decide whether or not to clear DECL_EXTERNAL. Some
callers defer that decision until it is clear that DECL is actually
required. */
void
import_export_decl (tree decl)
{
int emit_p;
bool comdat_p;
bool import_p;
if (DECL_INTERFACE_KNOWN (decl))
return;
if (DECL_TEMPLATE_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
/* We cannot determine what linkage to give to an entity with vague
linkage until the end of the file. For example, a virtual table
for a class will be defined if and only if the key method is
defined in this translation unit. As a further example, consider
that when compiling a translation unit that uses PCH file with
"-frepo" it would be incorrect to make decisions about what
entities to emit when building the PCH; those decisions must be
delayed until the repository information has been processed. */
my_friendly_assert (at_eof, 20040727);
/* Object file linkage for explicit instantiations is handled in
mark_decl_instantiated. For static variables in functions with
vague linkage, maybe_commonize_var is used.
Therefore, the only declarations that should be provided to this
function are those with external linkage that:
* implicit instantiations of function templates
* inline function
* implicit instantiations of static data members of class
templates
* virtual tables
* typeinfo objects
Furthermore, all entities that reach this point must have a
definition available in this translation unit.
The following assertions check these conditions. */
my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL,
2004725);
/* Any code that creates entities with TREE_PUBLIC cleared should
also set DECL_INTERFACE_KNOWN. */
my_friendly_assert (TREE_PUBLIC (decl), 20040725);
if (TREE_CODE (decl) == FUNCTION_DECL)
my_friendly_assert (DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
|| DECL_DECLARED_INLINE_P (decl),
20040725);
else
my_friendly_assert (DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_VTABLE_OR_VTT_P (decl)
|| DECL_TINFO_P (decl),
20040725);
/* Check that a definition of DECL is available in this translation
unit. */
my_friendly_assert (!DECL_REALLY_EXTERN (decl), 20040725);
/* Assume that DECL will not have COMDAT linkage. */
comdat_p = false;
/* Assume that DECL will not be imported into this translation
unit. */
import_p = false;
/* See if the repository tells us whether or not to emit DECL in
this translation unit. */
emit_p = repo_emit_p (decl);
if (emit_p == 0)
import_p = true;
else if (emit_p == 1)
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
if ((DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
&& (flag_implicit_templates
|| (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl))))
/* The repository indicates that this entity should be defined
here. Make sure the back end honors that request. */
if (TREE_CODE (decl) == VAR_DECL)
mark_needed (decl);
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
|| DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
{
if (!TREE_PUBLIC (decl))
/* Templates are allowed to have internal linkage. See
[basic.link]. */
;
else
comdat_linkage (decl);
tree clone;
FOR_EACH_CLONE (clone, decl)
mark_needed (clone);
}
else
mark_needed (decl);
/* Output the definition as an ordinary strong definition. */
DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
return;
}
if (import_p)
/* We have already decided what to do with this DECL; there is no
need to check anything further. */
;
else if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
{
tree type = DECL_CONTEXT (decl);
import_export_class (type);
if (TYPE_FOR_JAVA (type))
import_p = true;
else if (CLASSTYPE_INTERFACE_KNOWN (type)
&& CLASSTYPE_INTERFACE_ONLY (type))
import_p = true;
else if (TARGET_WEAK_NOT_IN_ARCHIVE_TOC
&& !CLASSTYPE_USE_TEMPLATE (type)
&& CLASSTYPE_KEY_METHOD (type)
&& !DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type)))
/* The ABI requires that all virtual tables be emitted with
COMDAT linkage. However, on systems where COMDAT symbols
don't show up in the table of contents for a static
archive, the linker will report errors about undefined
symbols because it will not see the virtual table
definition. Therefore, in the case that we know that the
virtual table will be emitted in only one translation
unit, we make the virtual table an ordinary definition
with external linkage. */
DECL_EXTERNAL (decl) = 0;
else if (CLASSTYPE_INTERFACE_KNOWN (type))
{
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
/* TYPE is being exported from this translation unit, so DECL
should be defined here. The ABI requires COMDAT
linkage. Normally, we only emit COMDAT things when they
are needed; make sure that we realize that this entity is
indeed needed. */
comdat_p = true;
mark_needed (decl);
}
else if (!flag_implicit_templates
&& CLASSTYPE_IMPLICIT_INSTANTIATION (type))
import_p = true;
else
comdat_p = true;
}
else if (TREE_CODE (decl) == VAR_DECL && DECL_TINFO_P (decl))
{
tree type = TREE_TYPE (DECL_NAME (decl));
if (CLASS_TYPE_P (type))
{
import_export_class (type);
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& TYPE_POLYMORPHIC_P (type)
&& CLASSTYPE_INTERFACE_ONLY (type)
/* If -fno-rtti was specified, then we cannot be sure
that RTTI information will be emitted with the
virtual table of the class, so we must emit it
wherever it is used. */
&& flag_rtti)
import_p = true;
else
{
comdat_p = true;
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& !CLASSTYPE_INTERFACE_ONLY (type))
mark_needed (decl);
}
}
else
comdat_p = true;
}
else if (DECL_TEMPLATE_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
{
/* DECL is an implicit instantiation of a function or static
data member. */
if (flag_implicit_templates
|| (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)))
comdat_p = true;
else
/* If we are not implicitly generating templates, then mark
this entity as undefined in this translation unit. */
import_p = true;
}
else if (DECL_FUNCTION_MEMBER_P (decl))
{
@ -1713,55 +1824,31 @@ import_export_decl (tree decl)
/* Always make artificials weak. */
if (DECL_ARTIFICIAL (decl) && flag_weak)
comdat_linkage (decl);
comdat_p = true;
else
maybe_make_one_only (decl);
}
}
else
comdat_linkage (decl);
comdat_p = true;
}
else
comdat_linkage (decl);
comdat_p = true;
DECL_INTERFACE_KNOWN (decl) = 1;
}
/* Here, we only decide whether or not the tinfo node should be
emitted with the vtable. IS_IN_LIBRARY is nonzero iff the
typeinfo for TYPE should be in the runtime library. */
void
import_export_tinfo (tree decl, tree type, bool is_in_library)
{
if (DECL_INTERFACE_KNOWN (decl))
return;
if (IS_AGGR_TYPE (type))
import_export_class (type);
if (IS_AGGR_TYPE (type) && CLASSTYPE_INTERFACE_KNOWN (type)
&& TYPE_POLYMORPHIC_P (type)
/* If -fno-rtti, we're not necessarily emitting this stuff with
the class, so go ahead and emit it now. This can happen when
a class is used in exception handling. */
&& flag_rtti)
if (import_p)
{
DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type);
DECL_COMDAT (decl) = 0;
/* If we are importing DECL into this translation unit, mark is
an undefined here. */
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
}
else
else if (comdat_p)
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
DECL_COMDAT (decl) = 1;
/* If we decided to put DECL in COMDAT, mark it accordingly at
this point. */
comdat_linkage (decl);
}
/* Now override some cases. */
if (flag_weak)
DECL_COMDAT (decl) = 1;
else if (is_in_library)
DECL_COMDAT (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
@ -2403,8 +2490,14 @@ write_out_vars (tree vars)
tree v;
for (v = vars; v; v = TREE_CHAIN (v))
if (!var_finalized_p (TREE_VALUE (v)))
rest_of_decl_compilation (TREE_VALUE (v), 0, 1, 1);
{
tree var = TREE_VALUE (v);
if (!var_finalized_p (var))
{
import_export_decl (var);
rest_of_decl_compilation (var, 0, 1, 1);
}
}
}
/* Generate a static constructor (if CONSTRUCTOR_P) or destructor
@ -2520,21 +2613,36 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
{
tree t = *tp;
if (flag_unit_at_a_time)
switch (TREE_CODE (t))
{
case PTRMEM_CST:
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
break;
case BASELINK:
if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
break;
default:
break;
}
switch (TREE_CODE (t))
{
case PTRMEM_CST:
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
break;
case BASELINK:
if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
break;
case VAR_DECL:
if (DECL_VTABLE_OR_VTT_P (t))
{
/* The ABI requires that all virtual tables be emitted
whenever one of them is. */
tree vtbl;
for (vtbl = CLASSTYPE_VTABLES (DECL_CONTEXT (t));
vtbl;
vtbl = TREE_CHAIN (vtbl))
mark_decl_referenced (vtbl);
}
else if (DECL_CONTEXT (t)
&& TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
/* If we need a static variable in a function, then we
need the containing function. */
mark_decl_referenced (DECL_CONTEXT (t));
break;
default:
break;
}
return NULL;
}
@ -2732,16 +2840,15 @@ finish_file (void)
#endif
}
/* Go through the set of inline functions whose bodies have not
been emitted yet. If out-of-line copies of these functions
are required, emit them. */
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
if (! DECL_DECLARED_INLINE_P (decl) || ! TREE_USED (decl))
abort ();
/* Does it need synthesizing? */
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& TREE_USED (decl)
&& (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
{
/* Even though we're already at the top-level, we push
@ -2772,7 +2879,7 @@ finish_file (void)
function twice. */
if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl)
&& DECL_NEEDED_P (decl))
&& decl_needed_p (decl))
DECL_EXTERNAL (decl) = 0;
/* If we're going to need to write this function out, and
@ -2780,10 +2887,9 @@ finish_file (void)
(There might be no body if this is a method we haven't
gotten around to synthesizing yet.) */
if (!DECL_EXTERNAL (decl)
&& DECL_NEEDED_P (decl)
&& decl_needed_p (decl)
&& !TREE_ASM_WRITTEN (decl)
&& (!flag_unit_at_a_time
|| !cgraph_node (decl)->local.finalized))
&& !cgraph_node (decl)->local.finalized)
{
/* We will output the function; no longer consider it in this
loop. */
@ -2807,10 +2913,12 @@ finish_file (void)
for (i = 0; i < pending_statics_used; ++i)
{
tree decl = VARRAY_TREE (pending_statics, i);
if (var_finalized_p (decl))
if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl))
continue;
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
/* If this static data member is needed, provide it to the
back end. */
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
DECL_EXTERNAL (decl) = 0;
}
if (pending_statics
@ -2818,8 +2926,13 @@ finish_file (void)
pending_statics_used))
reconsider = true;
/* Ask the back end to emit functions and variables that are
enqued. These emissions may result in marking more entities
as needed. */
if (cgraph_assemble_pending_functions ())
reconsider = true;
if (cgraph_varpool_assemble_pending_decls ())
reconsider = true;
}
while (reconsider);
@ -2828,7 +2941,17 @@ finish_file (void)
{
tree decl = VARRAY_TREE (deferred_fns, i);
if (!TREE_ASM_WRITTEN (decl) && !DECL_SAVED_TREE (decl)
if (/* Check online inline functions that were actually used. */
TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
/* But not defined. */
&& DECL_REALLY_EXTERN (decl)
/* If we decided to emit this function in another
translation unit, the fact that the definition was
missing here likely indicates only that the repository
decided to place the function elsewhere. With -Winline,
we will still warn if we could not inline the
function. */
&& !flag_use_repository
/* An explicit instantiation can be used to specify
that the body is in another unit. It will have
already verified there was a definition. */
@ -2840,7 +2963,6 @@ finish_file (void)
warning. */
TREE_PUBLIC (decl) = 1;
}
}
/* We give C linkage to static constructors and destructors. */
@ -2871,11 +2993,8 @@ finish_file (void)
linkage now. */
pop_lang_context ();
if (flag_unit_at_a_time)
{
cgraph_finalize_compilation_unit ();
cgraph_optimize ();
}
cgraph_finalize_compilation_unit ();
cgraph_optimize ();
/* Emit mudflap static registration function. This must be done
after all the user functions have been expanded. */
@ -3009,12 +3128,7 @@ mark_used (tree decl)
{
if (DECL_DEFERRED_FN (decl))
return;
DECL_DEFERRED_FN (decl) = 1;
DECL_DEFER_OUTPUT (decl) = 1;
if (!deferred_fns)
VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
VARRAY_PUSH_TREE (deferred_fns, decl);
note_vague_linkage_fn (decl);
}
assemble_external (decl);
@ -3044,40 +3158,11 @@ mark_used (tree decl)
|| (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INLINE (DECL_TEMPLATE_RESULT
(template_for_substitution (decl))))))
{
bool defer;
/* Normally, we put off instantiating functions in order to
improve compile times. Maintaining a stack of active
functions is expensive, and the inliner knows to
instantiate any functions it might need.
However, if instantiating this function might help us mark
the current function TREE_NOTHROW, we go ahead and
instantiate it now.
This is not needed for unit-at-a-time since we reorder the functions
in topological order anyway.
*/
defer = (!flag_exceptions
|| flag_unit_at_a_time
|| !optimize
|| TREE_CODE (decl) != FUNCTION_DECL
/* If the called function can't throw, we don't need to
generate its body to find that out. */
|| TREE_NOTHROW (decl)
|| !cfun
|| !current_function_decl
/* If we already know the current function can't throw,
then we don't need to work hard to prove it. */
|| TREE_NOTHROW (current_function_decl)
/* If we already know that the current function *can*
throw, there's no point in gathering more
information. */
|| cp_function_chain->can_throw);
instantiate_decl (decl, defer, /*undefined_ok=*/0);
}
/* We put off instantiating functions in order to improve compile
times. Maintaining a stack of active functions is expensive,
and the inliner knows to instantiate any functions it might
need. */
instantiate_decl (decl, /*defer_ok=*/true, /*undefined_ok=*/0);
}
#include "gt-cp-decl2.h"

View File

@ -361,6 +361,17 @@ cxx_init (void)
interface_unknown = 1;
/* The fact that G++ uses COMDAT for many entities (inline
functions, template instantiations, virtual tables, etc.) mean
that it is fundamentally unreliable to try to make decisions
about whether or not to output a particular entity until the end
of the compilation. However, the inliner requires that functions
be provided to the back end if they are to be inlined.
Therefore, we always use unit-at-a-time mode; in that mode, we
can provide entities to the back end and it will decide what to
emit based on what is actually needed. */
flag_unit_at_a_time = 1;
if (c_common_init () == false)
{
pop_srcloc();
@ -369,7 +380,7 @@ cxx_init (void)
init_cp_pragma ();
init_repo (main_input_filename);
init_repo ();
pop_srcloc();
return true;

View File

@ -700,9 +700,6 @@ synthesize_method (tree fndecl)
bool need_body = true;
tree stmt;
if (at_eof)
import_export_decl (fndecl);
/* If we've been asked to synthesize a clone, just synthesize the
cloned function instead. Doing so will automatically fill in the
body for the clone. */
@ -1014,7 +1011,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
TYPE_UNQUALIFIED);
grok_special_member_properties (fn);
TREE_PUBLIC (fn) = !decl_function_context (TYPE_MAIN_DECL (type));
set_linkage_according_to_type (type, fn);
rest_of_decl_compilation (fn, /*asmspec=*/NULL,
toplevel_bindings_p (), at_eof);
DECL_IN_AGGR_P (fn) = 1;

View File

@ -89,9 +89,7 @@ maybe_clone_body (tree fn)
/* We know that any clones immediately follow FN in the TYPE_METHODS
list. */
push_to_top_level ();
for (clone = TREE_CHAIN (fn);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
FOR_EACH_CLONE (clone, fn)
{
tree parm;
tree clone_parm;

View File

@ -5693,10 +5693,7 @@ instantiate_class_template (tree type)
unreverse_member_declarations (type);
finish_struct_1 (type);
/* Clear this now so repo_template_used is happy. */
TYPE_BEING_DEFINED (type) = 0;
repo_template_used (type);
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
@ -5715,7 +5712,11 @@ instantiate_class_template (tree type)
pop_deferring_access_checks ();
pop_tinst_level ();
if (TYPE_CONTAINS_VPTR_P (type))
/* The vtable for a template class can be emitted in any translation
unit in which the class is instantiated. When there is no key
method, however, finish_struct_1 will already have added TYPE to
the keyed_classes list. */
if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type))
keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
return type;
@ -6235,7 +6236,10 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t);
DECL_EXTERNAL (r) = 1;
DECL_INTERFACE_KNOWN (r) = 0;
/* If this is an instantiation of a function with internal
linkage, we already know what object file linkage will be
assigned to the instantiation. */
DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);
DECL_DEFER_OUTPUT (r) = 0;
TREE_CHAIN (r) = NULL_TREE;
DECL_PENDING_INLINE_INFO (r) = 0;
@ -8564,7 +8568,7 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
shall not be used to declare an entity with linkage.
This implies that names with no linkage cannot be used as
template arguments. */
tree nt = no_linkage_check (t);
tree nt = no_linkage_check (t, /*relaxed_p=*/false);
if (nt)
{
@ -8628,9 +8632,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
return error_mark_node;
/* Look for the clone. */
for (clone = TREE_CHAIN (spec);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
FOR_EACH_CLONE (clone, spec)
if (DECL_NAME (clone) == DECL_NAME (tmpl))
return clone;
/* We should always have found the clone by now. */
@ -10076,9 +10078,20 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
}
}
/* Note that DECL can be defined in this translation unit, if
required. */
static void
mark_definable (tree decl)
{
tree clone;
DECL_NOT_REALLY_EXTERN (decl) = 1;
FOR_EACH_CLONE (clone, decl)
DECL_NOT_REALLY_EXTERN (clone) = 1;
}
/* Called if RESULT is explicitly instantiated, or is a member of an
explicitly instantiated class, or if using -frepo and the
instantiation of RESULT has been assigned to this file. */
explicitly instantiated class. */
void
mark_decl_instantiated (tree result, int extern_p)
@ -10098,11 +10111,11 @@ mark_decl_instantiated (tree result, int extern_p)
/* This might have been set by an earlier implicit instantiation. */
DECL_COMDAT (result) = 0;
if (! extern_p)
if (extern_p)
DECL_NOT_REALLY_EXTERN (result) = 0;
else
{
DECL_INTERFACE_KNOWN (result) = 1;
DECL_NOT_REALLY_EXTERN (result) = 1;
mark_definable (result);
/* Always make artificials weak. */
if (DECL_ARTIFICIAL (result) && flag_weak)
comdat_linkage (result);
@ -10111,6 +10124,13 @@ mark_decl_instantiated (tree result, int extern_p)
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
/* If EXTERN_P, then this function will not be emitted -- unless
followed by an explicit instantiation, at which point its linkage
will be adjusted. If !EXTERN_P, then this function will be
emitted here. In neither circumstance do we want
import_export_decl to adjust the linkage. */
DECL_INTERFACE_KNOWN (result) = 1;
}
/* Given two function templates PAT1 and PAT2, return:
@ -10548,15 +10568,14 @@ do_decl_instantiation (tree decl, tree storage)
No program shall explicitly instantiate any template more
than once.
We check DECL_INTERFACE_KNOWN so as not to complain when the first
instantiation was `extern' and the second is not, and EXTERN_P for
the opposite case. If -frepo, chances are we already got marked
as an explicit instantiation because of the repo file. */
if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
We check DECL_NOT_REALLY_EXTERN so as not to complain when
the first instantiation was `extern' and the second is not,
and EXTERN_P for the opposite case. */
if (DECL_NOT_REALLY_EXTERN (result) && !extern_p)
pedwarn ("duplicate explicit instantiation of `%#D'", result);
/* If we've already instantiated the template, just return now. */
if (DECL_INTERFACE_KNOWN (result))
/* If an "extern" explicit instantiation follows an ordinary
explicit instantiation, the template is instantiated. */
if (extern_p)
return;
}
else if (!DECL_IMPLICIT_INSTANTIATION (result))
@ -10583,7 +10602,6 @@ do_decl_instantiation (tree decl, tree storage)
storage);
mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
if (! extern_p)
instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
}
@ -10621,7 +10639,6 @@ static void
instantiate_class_member (tree decl, int extern_p)
{
mark_decl_instantiated (decl, extern_p);
repo_template_instantiated (decl, extern_p);
if (! extern_p)
instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
}
@ -10701,14 +10718,10 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
instantiation was `extern'. If EXTERN_P then the second is.
If -frepo, chances are we already got marked as an explicit
instantiation because of the repo file. All these cases are
OK. */
These cases are OK. */
previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
if (!previous_instantiation_extern_p && !extern_p
&& !flag_use_repository
&& (complain & tf_error))
pedwarn ("duplicate explicit instantiation of `%#T'", t);
@ -10718,7 +10731,6 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
}
mark_class_instantiated (t, extern_p);
repo_template_instantiated (t, extern_p);
if (nomem_p)
return;
@ -11001,37 +11013,21 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
else
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
/* Unless an explicit instantiation directive has already determined
the linkage of D, remember that a definition is available for
this entity. */
if (pattern_defined
&& !DECL_INTERFACE_KNOWN (d)
&& !DECL_NOT_REALLY_EXTERN (d))
mark_definable (d);
input_location = DECL_SOURCE_LOCATION (d);
if (pattern_defined)
{
/* Let the repository code that this template definition is
available.
The repository doesn't need to know about cloned functions
because they never actually show up in the object file. It
does need to know about the clones; those are the symbols
that the linker will be emitting error messages about. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (d)
|| DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (d))
{
tree t;
for (t = TREE_CHAIN (d);
t && DECL_CLONED_FUNCTION_P (t);
t = TREE_CHAIN (t))
repo_template_used (t);
}
else
repo_template_used (d);
if (at_eof)
import_export_decl (d);
}
if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
SET_DECL_IMPLICIT_INSTANTIATION (d);
{
DECL_NOT_REALLY_EXTERN (d) = 0;
SET_DECL_IMPLICIT_INSTANTIATION (d);
}
if (!defer_ok)
{
@ -11061,15 +11057,19 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
pop_access_scope (d);
}
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
&& DECL_INITIAL (d) == NULL_TREE)
/* We should have set up DECL_INITIAL in instantiate_class_template. */
abort ();
/* Reject all external templates except inline functions. */
else if (DECL_INTERFACE_KNOWN (d)
&& ! DECL_NOT_REALLY_EXTERN (d)
&& ! (TREE_CODE (d) == FUNCTION_DECL
&& DECL_INLINE (d)))
/* We should have set up DECL_INITIAL in instantiate_class_template
for in-class definitions of static data members. */
my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
&& DECL_INITIALIZED_IN_CLASS_P (d)
&& DECL_INITIAL (d) == NULL_TREE),
20040726);
/* Do not instantiate templates that we know will be defined
elsewhere. */
if (DECL_INTERFACE_KNOWN (d)
&& DECL_REALLY_EXTERN (d)
&& ! (TREE_CODE (d) == FUNCTION_DECL
&& DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here
@ -11093,6 +11093,22 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
add_pending_template (d);
goto out;
}
/* Tell the repository that D is available in this translation unit
-- and see if it is supposed to be instantiated here. */
if (TREE_PUBLIC (d) && !DECL_REALLY_EXTERN (d) && !repo_emit_p (d))
{
/* In a PCH file, despite the fact that the repository hasn't
requested instantiation in the PCH it is still possible that
an instantiation will be required in a file that includes the
PCH. */
if (pch_file)
add_pending_template (d);
/* Instantiate inline functions so that the inliner can do its
job, even though we'll not be emitting a copy of this
function. */
if (!flag_inline_trees || !DECL_DECLARED_INLINE_P (d))
goto out;
}
need_push = !cfun || !global_bindings_p ();
if (need_push)
@ -11105,7 +11121,7 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
input_location = DECL_SOURCE_LOCATION (d);
@ -11115,51 +11131,27 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
DECL_IN_AGGR_P (d) = 0;
import_export_decl (d);
DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
if (DECL_EXTERNAL (d))
{
/* The fact that this code is executing indicates that:
(1) D is a template static data member, for which a
definition is available.
/* Clear DECL_EXTERNAL so that cp_finish_decl will process the
initializer. That function will defer actual emission until
we have a chance to determine linkage. */
DECL_EXTERNAL (d) = 0;
(2) An implicit or explicit instantiation has occurred.
(3) We are not going to emit a definition of the static
data member at this time.
This situation is peculiar, but it occurs on platforms
without weak symbols when performing an implicit
instantiation. There, we cannot implicitly instantiate a
defined static data member in more than one translation
unit, so import_export_decl marks the declaration as
external; we must rely on explicit instantiation.
Reset instantiated marker to make sure that later
explicit instantiation will be processed. */
DECL_TEMPLATE_INSTANTIATED (d) = 0;
}
else
{
/* This is done in analogous to `start_decl'. It is
required for correct access checking. */
push_nested_class (DECL_CONTEXT (d));
cp_finish_decl (d,
(!DECL_INITIALIZED_IN_CLASS_P (d)
? DECL_INITIAL (d) : NULL_TREE),
NULL_TREE, 0);
/* Normally, pop_nested_class is called by cp_finish_decl
above. But when instantiate_decl is triggered during
instantiate_class_template processing, its DECL_CONTEXT
is still not completed yet, and pop_nested_class isn't
called. */
if (!COMPLETE_TYPE_P (DECL_CONTEXT (d)))
pop_nested_class ();
}
/* This is done in analogous to `start_decl'. It is required
for correct access checking. */
push_nested_class (DECL_CONTEXT (d));
cp_finish_decl (d,
(!DECL_INITIALIZED_IN_CLASS_P (d)
? DECL_INITIAL (d) : NULL_TREE),
NULL_TREE, 0);
/* Normally, pop_nested_class is called by cp_finish_decl above.
But when instantiate_decl is triggered during
instantiate_class_template processing, its DECL_CONTEXT is
still not completed yet, and pop_nested_class isn't
called. */
if (!COMPLETE_TYPE_P (DECL_CONTEXT (d)))
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
@ -11168,10 +11160,6 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
tree tmpl_parm;
tree spec_parm;
/* Mark D as instantiated so that recursive calls to
instantiate_decl do not try to instantiate it again. */
DECL_TEMPLATE_INSTANTIATED (d) = 1;
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
saved_local_specializations = local_specializations;
@ -11183,7 +11171,6 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
NULL);
/* Set up context. */
import_export_decl (d);
start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Create substitution entries for the parameters. */

View File

@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "diagnostic.h"
static tree repo_get_id (tree);
static char *extract_string (char **);
static const char *get_base_filename (const char *);
static void open_repo_file (const char *);
@ -45,162 +44,13 @@ static char *afgets (FILE *);
static void reopen_repo_file_for_write (void);
static GTY(()) tree pending_repo;
static GTY(()) tree original_repo;
static char *repo_name;
static FILE *repo_file;
static const char *old_args, *old_dir, *old_main;
static struct obstack temporary_obstack;
#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
#if 0
/* Record the flags used to compile this translation unit. */
void
repo_compile_flags (int argc, char **argv)
{
}
/* If this template has not been seen before, add a note to the repository
saying where the declaration was. This may be used to find the
definition at link time. */
void
repo_template_declared (tree t)
{}
/* Note where the definition of a template lives so that instantiations can
be generated later. */
void
repo_template_defined (tree t)
{}
/* Note where the definition of a class lives to that template
instantiations can use it. */
void
repo_class_defined (tree t)
{}
#endif
static tree
repo_get_id (tree t)
{
if (TYPE_P (t))
{
tree vtable;
/* If we're not done setting up the class, we may not have set up
the vtable, so going ahead would give the wrong answer.
See g++.pt/instantiate4.C. */
if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
abort ();
vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
t = vtable;
if (t == NULL_TREE)
return t;
}
return DECL_ASSEMBLER_NAME (t);
}
/* Note that a template has been used. If we can see the definition, offer
to emit it. */
void
repo_template_used (tree t)
{
tree id;
if (! flag_use_repository)
return;
id = repo_get_id (t);
if (id == NULL_TREE)
return;
if (TYPE_P (t))
{
if (IDENTIFIER_REPO_CHOSEN (id))
mark_class_instantiated (t, 0);
}
else if (DECL_P (t))
{
if (IDENTIFIER_REPO_CHOSEN (id))
/* It doesn't make sense to instantiate a clone, so we
instantiate the cloned function instead. Note that this
approach will not work correctly if collect2 assigns
different clones to different files -- but it shouldn't. */
mark_decl_instantiated (DECL_CLONED_FUNCTION_P (t)
? DECL_CLONED_FUNCTION (t) : t,
0);
}
else
abort ();
if (! IDENTIFIER_REPO_USED (id))
{
IDENTIFIER_REPO_USED (id) = 1;
pending_repo = tree_cons (NULL_TREE, id, pending_repo);
}
}
#if 0
/* Note that the vtable for a class has been used, and offer to emit it. */
static void
repo_vtable_used (tree t)
{
if (! flag_use_repository)
return;
pending_repo = tree_cons (NULL_TREE, t, pending_repo);
}
/* Note that an inline with external linkage has been used, and offer to
emit it. */
void
repo_inline_used (tree fn)
{
if (! flag_use_repository)
return;
/* Member functions of polymorphic classes go with their vtables. */
if (DECL_FUNCTION_MEMBER_P (fn)
&& TYPE_POLYMORPHIC_P (DECL_CONTEXT (fn)))
{
repo_vtable_used (DECL_CONTEXT (fn));
return;
}
pending_repo = tree_cons (NULL_TREE, fn, pending_repo);
}
/* Note that a particular typeinfo node has been used, and offer to
emit it. */
void
repo_tinfo_used (tree ti)
{
}
#endif
void
repo_template_instantiated (tree t, bool extern_p)
{
if (! extern_p)
{
tree id = repo_get_id (t);
if (id)
IDENTIFIER_REPO_CHOSEN (id) = 1;
}
}
static bool temporary_obstack_initialized_p;
/* Parse a reasonable subset of shell quoting syntax. */
@ -298,16 +148,22 @@ afgets (FILE *stream)
}
void
init_repo (const char *filename)
init_repo (void)
{
char *buf;
if (! flag_use_repository)
return;
gcc_obstack_init (&temporary_obstack);
/* When a PCH file is loaded, the entire identifier table is
replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
So, we have to reread the repository file. */
lang_post_pch_load = init_repo;
open_repo_file (filename);
if (!temporary_obstack_initialized_p)
gcc_obstack_init (&temporary_obstack);
open_repo_file (main_input_filename);
if (repo_file == 0)
return;
@ -325,21 +181,16 @@ init_repo (const char *filename)
case 'M':
old_main = ggc_strdup (buf + 2);
break;
case 'C':
case 'O':
/* A symbol that we were able to define the last time this
file was compiled. */
break;
case 'C':
/* A symbol that the prelinker has requested that we
define. */
{
tree id = get_identifier (buf + 2);
tree orig;
if (buf[0] == 'C')
{
IDENTIFIER_REPO_CHOSEN (id) = 1;
orig = integer_one_node;
}
else
orig = NULL_TREE;
original_repo = tree_cons (orig, id, original_repo);
IDENTIFIER_REPO_CHOSEN (id) = 1;
}
break;
default:
@ -347,13 +198,12 @@ init_repo (const char *filename)
}
obstack_free (&temporary_obstack, buf);
}
fclose (repo_file);
}
static void
reopen_repo_file_for_write (void)
{
if (repo_file)
fclose (repo_file);
repo_file = fopen (repo_name, "w");
if (repo_file == 0)
@ -369,69 +219,31 @@ void
finish_repo (void)
{
tree t;
bool repo_changed = false;
char *dir, *args;
if (!flag_use_repository)
return;
/* Do we have to write out a new info file? */
/* Are there any old templates that aren't used any longer or that are
newly chosen? */
for (t = original_repo; t; t = TREE_CHAIN (t))
{
if (!IDENTIFIER_REPO_USED (TREE_VALUE (t))
|| (!TREE_PURPOSE (t) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t))))
{
repo_changed = true;
break;
}
IDENTIFIER_REPO_USED (TREE_VALUE (t)) = 0;
}
/* Are there any templates that are newly used? */
if (!repo_changed)
for (t = pending_repo; t; t = TREE_CHAIN (t))
{
if (IDENTIFIER_REPO_USED (TREE_VALUE (t)))
{
repo_changed = true;
break;
}
}
dir = getpwd ();
args = getenv ("COLLECT_GCC_OPTIONS");
if (!repo_changed && pending_repo)
if (strcmp (old_main, main_input_filename) != 0
|| strcmp (old_dir, dir) != 0
|| (args == NULL) != (old_args == NULL)
|| (args && strcmp (old_args, args) != 0))
repo_changed = true;
if (!repo_changed || errorcount || sorrycount)
if (errorcount || sorrycount)
goto out;
reopen_repo_file_for_write ();
if (repo_file == 0)
goto out;
fprintf (repo_file, "M %s\n", main_input_filename);
dir = getpwd ();
fprintf (repo_file, "D %s\n", dir);
args = getenv ("COLLECT_GCC_OPTIONS");
if (args)
fprintf (repo_file, "A %s\n", args);
for (t = pending_repo; t; t = TREE_CHAIN (t))
{
tree val = TREE_VALUE (t);
char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
tree name = DECL_ASSEMBLER_NAME (val);
char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
}
out:
@ -439,4 +251,87 @@ finish_repo (void)
fclose (repo_file);
}
/* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
definition is available in this translation unit. Returns 0 if
this definition should not be emitted in this translation unit
because it will be emitted elsewhere. Returns 1 if the repository
file indicates that that DECL should be emitted in this translation
unit, or 2 if the repository file is not in use. */
int
repo_emit_p (tree decl)
{
my_friendly_assert (TREE_PUBLIC (decl), 20040725);
my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL,
20040725);
my_friendly_assert (!DECL_REALLY_EXTERN (decl), 20040725);
/* When not using the repository, emit everything. */
if (!flag_use_repository)
return 2;
/* Only template instantiations are managed by the repository. This
is an artificial restriction; the code in the prelinker and here
will work fine if all entities with vague linkage are managed by
the repository. */
if (TREE_CODE (decl) == VAR_DECL)
{
tree type = NULL_TREE;
if (DECL_VTABLE_OR_VTT_P (decl))
type = DECL_CONTEXT (decl);
else if (DECL_TINFO_P (decl))
type = TREE_TYPE (DECL_NAME (decl));
if (!DECL_TEMPLATE_INSTANTIATION (decl)
&& !CLASSTYPE_TEMPLATE_INSTANTIATION (type))
return 2;
}
else if (!DECL_TEMPLATE_INSTANTIATION (decl))
return 2;
/* For constructors and destructors, the repository contains
information about the clones -- not the original function --
because only the clones are emitted in the object file. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
|| DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
{
int emit_p = 0;
tree clone;
/* There is no early exit from this loop because we want to
ensure that all of the clones are marked as available in this
object file. */
FOR_EACH_CLONE (clone, decl)
/* The only possible results from the recursive call to
repo_emit_p are 0 or 1. */
if (repo_emit_p (clone))
emit_p = 1;
return emit_p;
}
/* Keep track of all available entities. */
if (!DECL_REPO_AVAILABLE_P (decl))
{
DECL_REPO_AVAILABLE_P (decl) = 1;
pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
}
return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl));
}
/* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
export from this translation unit. */
bool
repo_export_class_p (tree class_type)
{
if (!flag_use_repository)
return false;
if (!CLASSTYPE_VTABLES (class_type))
return false;
/* If the virtual table has been assigned to this translation unit,
export the class. */
return (IDENTIFIER_REPO_CHOSEN
(DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
}
#include "gt-cp-repo.h"

View File

@ -89,18 +89,15 @@ static int qualifier_flags (tree);
static bool target_incomplete_p (tree);
static tree tinfo_base_init (tree, tree);
static tree generic_initializer (tree, tree);
static tree ptr_initializer (tree, tree, bool *);
static tree ptm_initializer (tree, tree, bool *);
static tree dfs_class_hint_mark (tree, void *);
static tree dfs_class_hint_unmark (tree, void *);
static int class_hint_flags (tree);
static tree class_initializer (tree, tree, tree);
static tree create_pseudo_type_info (const char *, int, ...);
static tree get_pseudo_ti_init (tree, tree, bool *);
static tree get_pseudo_ti_init (tree, tree);
static tree get_pseudo_ti_desc (tree);
static void create_tinfo_types (void);
static bool typeinfo_in_lib_p (tree);
static bool unemitted_tinfo_decl_p (tree);
static int doing_runtime = 0;
@ -348,14 +345,16 @@ get_tinfo_decl (tree type)
tree var_desc = get_pseudo_ti_desc (type);
d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
SET_DECL_ASSEMBLER_NAME (d, name);
DECL_TINFO_P (d) = 1;
DECL_ARTIFICIAL (d) = 1;
TREE_READONLY (d) = 1;
TREE_STATIC (d) = 1;
/* Mark the variable as undefined -- but remember that we can
define it later if we need to do so. */
DECL_EXTERNAL (d) = 1;
DECL_COMDAT (d) = 1;
TREE_PUBLIC (d) = 1;
SET_DECL_ASSEMBLER_NAME (d, name);
DECL_NOT_REALLY_EXTERN (d) = 1;
set_linkage_according_to_type (type, d);
pushdecl_top_level_and_finish (d, NULL_TREE);
@ -732,6 +731,38 @@ target_incomplete_p (tree type)
return !COMPLETE_OR_VOID_TYPE_P (type);
}
/* Returns true if TYPE involves an incomplete class type; in that
case, typeinfo variables for TYPE should be emitted with internal
linkage. */
static bool
involves_incomplete_p (tree type)
{
switch (TREE_CODE (type))
{
case POINTER_TYPE:
return target_incomplete_p (TREE_TYPE (type));
case OFFSET_TYPE:
ptrmem:
return
(target_incomplete_p (TYPE_PTRMEM_POINTED_TO_TYPE (type))
|| !COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type)));
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
goto ptrmem;
/* Fall through. */
case UNION_TYPE:
if (!COMPLETE_TYPE_P (type))
return true;
default:
/* All other types do not involve incomplete class types. */
return false;
}
}
/* Return a CONSTRUCTOR for the common part of the type_info objects. This
is the vtable pointer and NTBS name. The NTBS name is emitted as a
comdat const char array, so it becomes a unique key for the type. Generate
@ -754,20 +785,32 @@ tinfo_base_init (tree desc, tree target)
NULL_TREE);
tree name_string = tinfo_name (target);
/* Determine the name of the variable -- and remember with which
type it is associated. */
name_name = mangle_typeinfo_string_for_type (target);
TREE_TYPE (name_name) = target;
name_decl = build_lang_decl (VAR_DECL, name_name, name_type);
DECL_ARTIFICIAL (name_decl) = 1;
TREE_READONLY (name_decl) = 1;
TREE_STATIC (name_decl) = 1;
DECL_EXTERNAL (name_decl) = 0;
TREE_PUBLIC (name_decl) = 1;
DECL_TINFO_P (name_decl) = 1;
if (CLASS_TYPE_P (target))
{
DECL_VISIBILITY (name_decl) = CLASSTYPE_VISIBILITY (target);
DECL_VISIBILITY_SPECIFIED (name_decl) = CLASSTYPE_VISIBILITY_SPECIFIED (target);
DECL_VISIBILITY_SPECIFIED (name_decl)
= CLASSTYPE_VISIBILITY_SPECIFIED (target);
}
import_export_tinfo (name_decl, target, typeinfo_in_lib_p (target));
if (involves_incomplete_p (target))
{
TREE_PUBLIC (name_decl) = 0;
DECL_INTERFACE_KNOWN (name_decl) = 1;
}
else
set_linkage_according_to_type (target, name_decl);
import_export_decl (name_decl);
/* External name of the string containing the type's name has a
special name. */
SET_DECL_ASSEMBLER_NAME (name_decl,
@ -843,7 +886,7 @@ generic_initializer (tree desc, tree target)
which adds target type and qualifier flags members to the type_info base. */
static tree
ptr_initializer (tree desc, tree target, bool *non_public_ptr)
ptr_initializer (tree desc, tree target)
{
tree init = tinfo_base_init (desc, target);
tree to = TREE_TYPE (target);
@ -851,10 +894,7 @@ ptr_initializer (tree desc, tree target, bool *non_public_ptr)
bool incomplete = target_incomplete_p (to);
if (incomplete)
{
flags |= 8;
*non_public_ptr = true;
}
flags |= 8;
init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
init = tree_cons (NULL_TREE,
get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
@ -873,7 +913,7 @@ ptr_initializer (tree desc, tree target, bool *non_public_ptr)
base. */
static tree
ptm_initializer (tree desc, tree target, bool *non_public_ptr)
ptm_initializer (tree desc, tree target)
{
tree init = tinfo_base_init (desc, target);
tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target);
@ -882,15 +922,9 @@ ptm_initializer (tree desc, tree target, bool *non_public_ptr)
bool incomplete = target_incomplete_p (to);
if (incomplete)
{
flags |= 0x8;
*non_public_ptr = true;
}
flags |= 0x8;
if (!COMPLETE_TYPE_P (klass))
{
flags |= 0x10;
*non_public_ptr = true;
}
flags |= 0x10;
init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
init = tree_cons (NULL_TREE,
get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
@ -1003,22 +1037,18 @@ typeinfo_in_lib_p (tree type)
}
}
/* Generate the initializer for the type info describing
TYPE. VAR_DESC is a . NON_PUBLIC_P is set nonzero, if the VAR_DECL
should not be exported from this object file. This should only be
called at the end of translation, when we know that no further
types will be completed. */
/* Generate the initializer for the type info describing TYPE. */
static tree
get_pseudo_ti_init (tree type, tree var_desc, bool *non_public_p)
get_pseudo_ti_init (tree type, tree var_desc)
{
my_friendly_assert (at_eof, 20021120);
switch (TREE_CODE (type))
{
case OFFSET_TYPE:
return ptm_initializer (var_desc, type, non_public_p);
return ptm_initializer (var_desc, type);
case POINTER_TYPE:
return ptr_initializer (var_desc, type, non_public_p);
return ptr_initializer (var_desc, type);
case ENUMERAL_TYPE:
return generic_initializer (var_desc, type);
break;
@ -1031,14 +1061,9 @@ get_pseudo_ti_init (tree type, tree var_desc, bool *non_public_p)
case UNION_TYPE:
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
return ptm_initializer (var_desc, type, non_public_p);
return ptm_initializer (var_desc, type);
else if (var_desc == class_desc_type_node)
{
if (!COMPLETE_TYPE_P (type))
/* Emit a non-public class_type_info. */
*non_public_p = true;
return class_initializer (var_desc, type, NULL_TREE);
}
return class_initializer (var_desc, type, NULL_TREE);
else if (var_desc == si_class_desc_type_node)
{
tree base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), 0);
@ -1414,30 +1439,6 @@ emit_support_tinfos (void)
}
}
/* Return true, iff T is a type_info variable which has not had a
definition emitted for it. */
static bool
unemitted_tinfo_decl_p (tree t)
{
if (/* It's a var decl */
TREE_CODE (t) == VAR_DECL
/* which has a name */
&& DECL_NAME (t)
/* whose name points back to itself */
&& IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == t
/* whose name's type is non-null */
&& TREE_TYPE (DECL_NAME (t))
/* and whose type is a struct */
&& TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
/* with a field */
&& TYPE_FIELDS (TREE_TYPE (t))
/* which is our pseudo type info */
&& TREE_TYPE (TYPE_FIELDS (TREE_TYPE (t))) == ti_desc_type_node)
return true;
return false;
}
/* Finish a type info decl. DECL_PTR is a pointer to an unemitted
tinfo decl. Determine whether it needs emitting, and if so
generate the initializer. */
@ -1446,35 +1447,48 @@ bool
emit_tinfo_decl (tree decl)
{
tree type = TREE_TYPE (DECL_NAME (decl));
bool non_public;
int in_library = typeinfo_in_lib_p (type);
tree var_desc, var_init;
my_friendly_assert (unemitted_tinfo_decl_p (decl), 20030307);
my_friendly_assert (DECL_TINFO_P (decl), 20030307);
import_export_tinfo (decl, type, in_library);
if (DECL_REALLY_EXTERN (decl) || !DECL_NEEDED_P (decl))
if (in_library)
{
if (doing_runtime)
DECL_EXTERNAL (decl) = 0;
else
{
/* If we're not in the runtime, then DECL (which is already
DECL_EXTERNAL) will not be defined here. */
DECL_INTERFACE_KNOWN (decl) = 1;
return false;
}
}
else if (involves_incomplete_p (type))
{
if (!decl_needed_p (decl))
return false;
/* If TYPE involves an incomplete class type, then the typeinfo
object will be emitted with internal linkage. There is no
way to know whether or not types are incomplete until the end
of the compilation, so this determination must be deferred
until this point. */
TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))
{
DECL_EXTERNAL (decl) = 0;
var_desc = get_pseudo_ti_desc (type);
var_init = get_pseudo_ti_init (type, var_desc);
DECL_INITIAL (decl) = var_init;
mark_used (decl);
cp_finish_decl (decl, var_init, NULL_TREE, 0);
return true;
}
else
return false;
if (!doing_runtime && in_library)
return false;
non_public = false;
var_desc = get_pseudo_ti_desc (type);
var_init = get_pseudo_ti_init (type, var_desc, &non_public);
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = !non_public;
if (non_public)
DECL_COMDAT (decl) = 0;
DECL_INITIAL (decl) = var_init;
mark_used (decl);
cp_finish_decl (decl, var_init, NULL_TREE, 0);
/* cp_finish_decl will have dealt with linkage. */
/* Say we've dealt with it. */
TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
return true;
}

View File

@ -2892,18 +2892,6 @@ expand_body (tree fn)
extract_interface_info ();
/* If this function is marked with the constructor attribute, add it
to the list of functions to be called along with constructors
from static duration objects. */
if (DECL_STATIC_CONSTRUCTOR (fn))
static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
/* If this function is marked with the destructor attribute, add it
to the list of functions to be called along with destructors from
static duration objects. */
if (DECL_STATIC_DESTRUCTOR (fn))
static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
if (DECL_CLONED_FUNCTION_P (fn))
{
/* If this is a clone, go through the other clones now and mark
@ -2957,15 +2945,39 @@ expand_or_defer_fn (tree fn)
return;
}
/* If this function is marked with the constructor attribute, add it
to the list of functions to be called along with constructors
from static duration objects. */
if (DECL_STATIC_CONSTRUCTOR (fn))
static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
/* If this function is marked with the destructor attribute, add it
to the list of functions to be called along with destructors from
static duration objects. */
if (DECL_STATIC_DESTRUCTOR (fn))
static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
/* We make a decision about linkage for these functions at the end
of the compilation. Until that point, we do not want the back
end to output them -- but we do want it to see the bodies of
these fucntions so that it can inline them as appropriate. */
if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
{
if (!at_eof)
{
DECL_EXTERNAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
note_vague_linkage_fn (fn);
}
else
import_export_decl (fn);
}
/* There's no reason to do any of the work here if we're only doing
semantic analysis; this code just generates RTL. */
if (flag_syntax_only)
return;
/* Compute the appropriate object-file linkage for inline functions. */
if (DECL_DECLARED_INLINE_P (fn))
import_export_decl (fn);
function_depth++;
/* Expand or defer, at the whim of the compilation unit manager. */

View File

@ -1062,10 +1062,11 @@ find_tree (tree t, tree x)
}
/* Check if the type T depends on a type with no linkage and if so, return
it. */
it. If RELAXED_P then do not consider a class type declared within
a TREE_PUBLIC function to have no linkage. */
tree
no_linkage_check (tree t)
no_linkage_check (tree t, bool relaxed_p)
{
tree r;
@ -1076,6 +1077,8 @@ no_linkage_check (tree t)
switch (TREE_CODE (t))
{
tree fn;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
goto ptrmem;
@ -1085,25 +1088,28 @@ no_linkage_check (tree t)
return NULL_TREE;
/* Fall through. */
case ENUMERAL_TYPE:
if (decl_function_context (TYPE_MAIN_DECL (t))
|| TYPE_ANONYMOUS_P (t))
if (TYPE_ANONYMOUS_P (t))
return t;
fn = decl_function_context (TYPE_MAIN_DECL (t));
if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
return t;
return NULL_TREE;
case ARRAY_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
return no_linkage_check (TREE_TYPE (t));
return no_linkage_check (TREE_TYPE (t), relaxed_p);
case OFFSET_TYPE:
ptrmem:
r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t));
r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t),
relaxed_p);
if (r)
return r;
return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t));
return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t), relaxed_p);
case METHOD_TYPE:
r = no_linkage_check (TYPE_METHOD_BASETYPE (t));
r = no_linkage_check (TYPE_METHOD_BASETYPE (t), relaxed_p);
if (r)
return r;
/* Fall through. */
@ -1114,11 +1120,11 @@ no_linkage_check (tree t)
parm && parm != void_list_node;
parm = TREE_CHAIN (parm))
{
r = no_linkage_check (TREE_VALUE (parm));
r = no_linkage_check (TREE_VALUE (parm), relaxed_p);
if (r)
return r;
}
return no_linkage_check (TREE_TYPE (t));
return no_linkage_check (TREE_TYPE (t), relaxed_p);
}
default:

View File

@ -1,3 +1,20 @@
2004-07-29 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/inline1.C: New test.
* g++.dg/abi/local1-a.cc: Likewise.
* g++.dg/abi/local1.C: Likewise.
* g++.dg/abi/mangle11.C: Tweak location of warnings.
* g++.dg/abi/mangle12.C: Likewise.
* g++.dg/abi/mangle17.C: Likewise.
* g++.dg/abi/mangle20-2.C: Likewise.
* g++.dg/opt/interface1.C: Likewise.
* g++.dg/opt/interface1.h: Likewise.
* g++.dg/opt/interface1-a.cc: New test.
* g++.dg/parse/repo1.C: New test.
* g++.dg/template/repo1.C: Likewise.
* g++.dg/warn/Winline-1.C: Likewise.
* lib/gcc-dg.exp (gcc-dg-test-1): Fix -frepo handling.
2004-07-29 Diego Novillo <dnovillo@redhat.com>
* gcc.dg/tree-ssa/20040729-1.c: New test.

View File

@ -0,0 +1,6 @@
struct S {
S() {}
virtual void g() {}
};
// { dg-final { scan-assembler-not "_ZTV1S" } }

View File

@ -0,0 +1,14 @@
struct B {
virtual void b() {}
};
static B* f() {
struct D : public B {
};
return new D;
}
B* g() {
return f();
}

View File

@ -0,0 +1,22 @@
// { dg-do run }
// { dg-additional-sources "local1-a.cc" }
#include <typeinfo>
struct B {
virtual void b() {}
};
static B* f() {
struct D : public B {
};
return new D;
}
extern B* g();
int main () {
if (typeid (*f()) == typeid (*g()))
return 1;
}

View File

@ -1,10 +1,10 @@
// { dg-options "-Wabi -fabi-version=1" }
template <typename Q>
void f (typename Q::X) {}
void f (typename Q::X) {} // { dg-warning "mangle" }
struct S {
typedef int X;
};
template void f<S> (int); // { dg-warning "mangle" }
template void f<S> (int);

View File

@ -1,11 +1,11 @@
// { dg-options "-Wabi -fabi-version=1" }
template <template <typename> class Q>
void f (typename Q<int>::X) {}
void f (typename Q<int>::X) {} // { dg-warning "mangle" }
template <typename Q>
struct S {
typedef int X;
};
template void f<S> (int); // { dg-warning "mangle" }
template void f<S> (int);

View File

@ -4,8 +4,8 @@ enum E { e = 3 };
template <int I> struct S {};
template <int I> void f (S<I + e + int (3.7)>) {}
template void f<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
template <int I> void f (S<I + e + int (3.7)>) {} // { dg-warning "mangle" }
template void f<7>(S<7 + e + int (3.7)>);
template <int I> void g (S<I + e + int (3.7)>) {}
template void g<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
template <int I> void g (S<I + e + int (3.7)>) {} // { dg-warning "mangle" }
template void g<7>(S<7 + e + int (3.7)>);

View File

@ -7,10 +7,10 @@
// PR 9043
// mangled array types in templates
template <int I> void f(int (*)[2]) {}
template <int I> void f(int (*)[2]) {} // { dg-warning "mangled name" }
template <int I> void g(int (*)[I+2]) {}
template void f<1>(int (*)[2]); // { dg-warning "mangled name" }
template void f<1>(int (*)[2]);
// { dg-final { scan-assembler "\n_?_Z1fILi1EEvPALi2E_i\[: \t\n\]" } }
template void g<1>(int (*)[3]);
// { dg-final { scan-assembler "\n_?_Z1gILi1EEvPAplT_Li2E_i\[: \t\n\]" } }

View File

@ -0,0 +1,9 @@
struct Test {
void f();
};
Test t;
void g() {
t.f();
}

View File

@ -0,0 +1,13 @@
// { dg-do run }
// { dg-options "-O2" }
// { dg-additional-sources "interface1-a.cc" }
#pragma implementation "interface1.h"
#include "interface1.h"
extern void g();
int main () {
g();
}

View File

@ -0,0 +1,8 @@
#pragma interface "interface1.h"
struct Test {
void f();
};
inline void Test::f() {
}

View File

@ -0,0 +1,7 @@
// { dg-options "-frepo" }
extern "C" inline void f() {}
int main () {
f();
}

View File

@ -0,0 +1,17 @@
// { dg-options "-frepo" }
struct A {
A();
};
A::A() {}
template <typename T>
struct B : public A {
B() {} // { dg-bogus "" }
};
B<int> b;
int main () {}

View File

@ -1,10 +1,10 @@
// { dg-options "-Winline -O2 -fno-unit-at-a-time" }
// { dg-options "-Winline -O2" }
static inline int foo(int x); // { dg-warning "" }
static inline int foo(int x);
int main()
{
return(foo(17)); // { dg-warning "" }
return(foo(17));
}
inline int foo(int x) { return(x); }

View File

@ -119,8 +119,10 @@ proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } {
if { $do_what == "repo" } {
set object_file "$output_file"
set output_file "[file rootname [file tail $prog]].exe"
concat comp_output \
[$target_compile "$object_file" "$output_file" "executable" $options]
set comp_output \
[ concat $comp_output \
[$target_compile "$object_file" "$output_file" \
"executable" $options] ]
}
return [list $comp_output $output_file]

View File

@ -470,6 +470,12 @@ recompile_files (void)
obstack_grow (&temporary_obstack, "; ", 2);
obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
obstack_1grow (&temporary_obstack, ' ');
if (!f->args)
{
error ("repository file `%s' does not contain command-line "
"arguments", f->key);
return 0;
}
obstack_grow (&temporary_obstack, f->args, strlen (f->args));
obstack_1grow (&temporary_obstack, ' ');
command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
@ -645,6 +651,9 @@ scan_linker_output (const char *fname)
if (sym && sym->tweaked)
{
error ("`%s' was assigned to `%s', but was not defined "
"during recompilation, or vice versa",
sym->key, sym->file->key);
fclose (stream);
return 0;
}