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:
parent
b4042a039f
commit
4684cd27fc
|
@ -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):
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
100
gcc/cp/ChangeLog
100
gcc/cp/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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))
|
||||
|
|
617
gcc/cp/decl2.c
617
gcc/cp/decl2.c
|
@ -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"
|
||||
|
|
13
gcc/cp/lex.c
13
gcc/cp/lex.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
215
gcc/cp/pt.c
215
gcc/cp/pt.c
|
@ -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)
|
||||
|
@ -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:
|
||||
/* 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;
|
||||
|
||||
(1) D is a template static data member, for which a
|
||||
definition is available.
|
||||
|
||||
(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. */
|
||||
|
|
319
gcc/cp/repo.c
319
gcc/cp/repo.c
|
@ -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"
|
||||
|
|
194
gcc/cp/rtti.c
194
gcc/cp/rtti.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
struct S {
|
||||
S() {}
|
||||
virtual void g() {}
|
||||
};
|
||||
|
||||
// { dg-final { scan-assembler-not "_ZTV1S" } }
|
|
@ -0,0 +1,14 @@
|
|||
struct B {
|
||||
virtual void b() {}
|
||||
};
|
||||
|
||||
static B* f() {
|
||||
struct D : public B {
|
||||
};
|
||||
|
||||
return new D;
|
||||
}
|
||||
|
||||
B* g() {
|
||||
return f();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)>);
|
||||
|
|
|
@ -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\]" } }
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
struct Test {
|
||||
void f();
|
||||
};
|
||||
|
||||
Test t;
|
||||
|
||||
void g() {
|
||||
t.f();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#pragma interface "interface1.h"
|
||||
|
||||
struct Test {
|
||||
void f();
|
||||
};
|
||||
|
||||
inline void Test::f() {
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// { dg-options "-frepo" }
|
||||
|
||||
extern "C" inline void f() {}
|
||||
|
||||
int main () {
|
||||
f();
|
||||
}
|
|
@ -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 () {}
|
||||
|
|
@ -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); }
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue