* 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
+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):
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);
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. */
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. */
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:
+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.
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. */
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;
}
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).
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)
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
#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)
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;
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
#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
#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 \
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) \
(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))
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);
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);
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) \
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 */
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 *);
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);
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
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))
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
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
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))
/* 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
{
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))
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.
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'",
}
}
-/* 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. */
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
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.
{
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. */
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
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. */
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
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))
- {
- 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))))
+ /* 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)
+ {
+ /* 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))
{
/* 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);
-
- 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. */
+ comdat_p = true;
-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;
}
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
{
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;
}
#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
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
(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. */
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
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);
{
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. */
warning. */
TREE_PUBLIC (decl) = 1;
}
-
}
/* We give C linkage to static constructors and destructors. */
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. */
{
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);
|| (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"
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();
init_cp_pragma ();
- init_repo (main_input_filename);
+ init_repo ();
pop_srcloc();
return true;
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. */
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;
/* 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;
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
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;
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;
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)
{
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. */
}
}
\f
+/* 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)
/* 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);
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:
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))
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);
}
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);
}
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);
}
mark_class_instantiated (t, extern_p);
- repo_template_instantiated (t, extern_p);
if (nomem_p)
return;
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)
+ if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
{
- /* 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);
+ DECL_NOT_REALLY_EXTERN (d) = 0;
+ SET_DECL_IMPLICIT_INSTANTIATION (d);
}
- if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
- SET_DECL_IMPLICIT_INSTANTIATION (d);
-
if (!defer_ok)
{
/* Recheck the substitutions to obtain any warning messages
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
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)
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
input_location = DECL_SOURCE_LOCATION (d);
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
-
DECL_IN_AGGR_P (d) = 0;
- import_export_decl (d);
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
-
- if (DECL_EXTERNAL (d))
- {
- /* The fact that this code is executing indicates that:
-
- (1) D is a template static data member, for which a
- definition is available.
-
- (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 ();
- }
+ /* 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;
+
+ /* 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)
{
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;
NULL);
/* Set up context. */
- import_export_decl (d);
start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Create substitution entries for the parameters. */
#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 *);
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. */
}
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;
+
+ if (!temporary_obstack_initialized_p)
+ gcc_obstack_init (&temporary_obstack);
- open_repo_file (filename);
+ open_repo_file (main_input_filename);
if (repo_file == 0)
return;
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:
}
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)
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:
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"
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;
\f
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);
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
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,
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);
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)),
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);
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)),
}
}
-/* 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;
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);
}
}
-/* 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. */
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))
- return false;
+ 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;
+ }
- if (!doing_runtime && in_library)
+ 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;
-
- 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;
}
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
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. */
}
/* 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;
switch (TREE_CODE (t))
{
+ tree fn;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
goto ptrmem;
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. */
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:
+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.
--- /dev/null
+struct S {
+ S() {}
+ virtual void g() {}
+};
+
+// { dg-final { scan-assembler-not "_ZTV1S" } }
--- /dev/null
+struct B {
+ virtual void b() {}
+};
+
+static B* f() {
+ struct D : public B {
+ };
+
+ return new D;
+}
+
+B* g() {
+ return f();
+}
--- /dev/null
+// { 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;
+}
// { 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);
// { 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);
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)>);
// 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\]" } }
--- /dev/null
+struct Test {
+ void f();
+};
+
+Test t;
+
+void g() {
+ t.f();
+}
--- /dev/null
+// { 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();
+}
--- /dev/null
+#pragma interface "interface1.h"
+
+struct Test {
+ void f();
+};
+
+inline void Test::f() {
+}
--- /dev/null
+// { dg-options "-frepo" }
+
+extern "C" inline void f() {}
+
+int main () {
+ f();
+}
--- /dev/null
+// { dg-options "-frepo" }
+
+struct A {
+ A();
+};
+
+A::A() {}
+
+template <typename T>
+struct B : public A {
+ B() {} // { dg-bogus "" }
+};
+
+B<int> b;
+
+int main () {}
+
-// { 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); }
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]
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));
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;
}