summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/c-common.h4
-rw-r--r--gcc/c-pch.c9
-rw-r--r--gcc/cgraphunit.c7
-rw-r--r--gcc/cp/ChangeLog100
-rw-r--r--gcc/cp/class.c55
-rw-r--r--gcc/cp/cp-tree.h76
-rw-r--r--gcc/cp/decl.c48
-rw-r--r--gcc/cp/decl2.c621
-rw-r--r--gcc/cp/lex.c13
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/optimize.c4
-rw-r--r--gcc/cp/pt.c217
-rw-r--r--gcc/cp/repo.c319
-rw-r--r--gcc/cp/rtti.c192
-rw-r--r--gcc/cp/semantics.c44
-rw-r--r--gcc/cp/tree.c26
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/g++.dg/abi/inline1.C6
-rw-r--r--gcc/testsuite/g++.dg/abi/local1-a.cc14
-rw-r--r--gcc/testsuite/g++.dg/abi/local1.C22
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle11.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle12.C4
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle17.C8
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle20-2.C4
-rw-r--r--gcc/testsuite/g++.dg/opt/interface1-a.cc9
-rw-r--r--gcc/testsuite/g++.dg/opt/interface1.C13
-rw-r--r--gcc/testsuite/g++.dg/opt/interface1.h8
-rw-r--r--gcc/testsuite/g++.dg/parse/repo1.C7
-rw-r--r--gcc/testsuite/g++.dg/template/repo1.C17
-rw-r--r--gcc/testsuite/g++.dg/warn/Winline-1.C6
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp6
-rw-r--r--gcc/tlink.c9
33 files changed, 1134 insertions, 773 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dbda154ab8d..1a6e4e130d3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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):
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 6df90a4f215..63972dc96bb 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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);
diff --git a/gcc/c-pch.c b/gcc/c-pch.c
index eb043bd089e..21c3135b110 100644
--- a/gcc/c-pch.c
+++ b/gcc/c-pch.c
@@ -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. */
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 059ae86081e..9e903e09b9d 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -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:
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index da4dad7448b..d87584ec711 100644
--- a/gcc/cp/ChangeLog
+++ b/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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 8da2e586548..365febbb704 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c69320fadbc..8d14911235d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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 *);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f901d98f3db..c84c4be7687 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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))
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index ea9aa49c13c..40322ab31cc 100644
--- a/gcc/cp/decl2.c
+++ b/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))
- {
- 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))
{
@@ -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);
-
- 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;
}
@@ -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"
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index c5b14460b94..00adb7239c5 100644
--- a/gcc/cp/lex.c
+++ b/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;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 07fbacf266a..d741d3d3cd1 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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;
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 000d6cc4c27..b94270eabd6 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -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;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index def63108bd4..0ecbda0fa15 100644
--- a/gcc/cp/pt.c
+++ b/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,38 +11013,22 @@ 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)
+ 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
@@ -11061,15 +11057,19 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
pop_access_scope (d);
}
- if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
- && DECL_INITIAL (d) == NULL_TREE)
- /* We should have set up DECL_INITIAL in instantiate_class_template. */
- abort ();
- /* Reject all external templates except inline functions. */
- else if (DECL_INTERFACE_KNOWN (d)
- && ! DECL_NOT_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL
- && DECL_INLINE (d)))
+ /* We should have set up DECL_INITIAL in instantiate_class_template
+ for in-class definitions of static data members. */
+ my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
+ && DECL_INITIALIZED_IN_CLASS_P (d)
+ && DECL_INITIAL (d) == NULL_TREE),
+ 20040726);
+
+ /* Do not instantiate templates that we know will be defined
+ elsewhere. */
+ if (DECL_INTERFACE_KNOWN (d)
+ && DECL_REALLY_EXTERN (d)
+ && ! (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_INLINE (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. We restore the source position here
@@ -11093,6 +11093,22 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
add_pending_template (d);
goto out;
}
+ /* Tell the repository that D is available in this translation unit
+ -- and see if it is supposed to be instantiated here. */
+ if (TREE_PUBLIC (d) && !DECL_REALLY_EXTERN (d) && !repo_emit_p (d))
+ {
+ /* In a PCH file, despite the fact that the repository hasn't
+ requested instantiation in the PCH it is still possible that
+ an instantiation will be required in a file that includes the
+ PCH. */
+ if (pch_file)
+ add_pending_template (d);
+ /* Instantiate inline functions so that the inliner can do its
+ job, even though we'll not be emitting a copy of this
+ function. */
+ if (!flag_inline_trees || !DECL_DECLARED_INLINE_P (d))
+ goto out;
+ }
need_push = !cfun || !global_bindings_p ();
if (need_push)
@@ -11105,7 +11121,7 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
input_location = DECL_SOURCE_LOCATION (d);
@@ -11115,51 +11131,27 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
-
DECL_IN_AGGR_P (d) = 0;
- import_export_decl (d);
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
-
- if (DECL_EXTERNAL (d))
- {
- /* The fact that this code is executing indicates that:
-
- (1) D is a template static data member, for which a
- definition is available.
-
- (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)
{
@@ -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. */
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index a9a5b35c293..b3edf4875fc 100644
--- a/gcc/cp/repo.c
+++ b/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;
+
+ 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;
@@ -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"
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index c6c9fc6acc4..83e24c4e21c 100644
--- a/gcc/cp/rtti.c
+++ b/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))
- 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;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f6f71759478..152d75ca1f0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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. */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 79070f0629a..6a626e9470d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c82cbe55ddc..5dc06fc7beb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/abi/inline1.C b/gcc/testsuite/g++.dg/abi/inline1.C
new file mode 100644
index 00000000000..97082aa7377
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/inline1.C
@@ -0,0 +1,6 @@
+struct S {
+ S() {}
+ virtual void g() {}
+};
+
+// { dg-final { scan-assembler-not "_ZTV1S" } }
diff --git a/gcc/testsuite/g++.dg/abi/local1-a.cc b/gcc/testsuite/g++.dg/abi/local1-a.cc
new file mode 100644
index 00000000000..638479e7459
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/local1-a.cc
@@ -0,0 +1,14 @@
+struct B {
+ virtual void b() {}
+};
+
+static B* f() {
+ struct D : public B {
+ };
+
+ return new D;
+}
+
+B* g() {
+ return f();
+}
diff --git a/gcc/testsuite/g++.dg/abi/local1.C b/gcc/testsuite/g++.dg/abi/local1.C
new file mode 100644
index 00000000000..518193c8980
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/local1.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/abi/mangle11.C b/gcc/testsuite/g++.dg/abi/mangle11.C
index a049a956671..6d09b51a6a1 100644
--- a/gcc/testsuite/g++.dg/abi/mangle11.C
+++ b/gcc/testsuite/g++.dg/abi/mangle11.C
@@ -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);
diff --git a/gcc/testsuite/g++.dg/abi/mangle12.C b/gcc/testsuite/g++.dg/abi/mangle12.C
index 406a13b3f79..a3bd9ff6fa7 100644
--- a/gcc/testsuite/g++.dg/abi/mangle12.C
+++ b/gcc/testsuite/g++.dg/abi/mangle12.C
@@ -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);
diff --git a/gcc/testsuite/g++.dg/abi/mangle17.C b/gcc/testsuite/g++.dg/abi/mangle17.C
index 994da88edca..134b976a271 100644
--- a/gcc/testsuite/g++.dg/abi/mangle17.C
+++ b/gcc/testsuite/g++.dg/abi/mangle17.C
@@ -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)>);
diff --git a/gcc/testsuite/g++.dg/abi/mangle20-2.C b/gcc/testsuite/g++.dg/abi/mangle20-2.C
index bf3d189bf0c..38ac52371ab 100644
--- a/gcc/testsuite/g++.dg/abi/mangle20-2.C
+++ b/gcc/testsuite/g++.dg/abi/mangle20-2.C
@@ -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\]" } }
diff --git a/gcc/testsuite/g++.dg/opt/interface1-a.cc b/gcc/testsuite/g++.dg/opt/interface1-a.cc
new file mode 100644
index 00000000000..595585257c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/interface1-a.cc
@@ -0,0 +1,9 @@
+struct Test {
+ void f();
+};
+
+Test t;
+
+void g() {
+ t.f();
+}
diff --git a/gcc/testsuite/g++.dg/opt/interface1.C b/gcc/testsuite/g++.dg/opt/interface1.C
new file mode 100644
index 00000000000..850fe384011
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/interface1.C
@@ -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();
+}
diff --git a/gcc/testsuite/g++.dg/opt/interface1.h b/gcc/testsuite/g++.dg/opt/interface1.h
new file mode 100644
index 00000000000..125f4b59ea0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/interface1.h
@@ -0,0 +1,8 @@
+#pragma interface "interface1.h"
+
+struct Test {
+ void f();
+};
+
+inline void Test::f() {
+}
diff --git a/gcc/testsuite/g++.dg/parse/repo1.C b/gcc/testsuite/g++.dg/parse/repo1.C
new file mode 100644
index 00000000000..fa9a1409270
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/repo1.C
@@ -0,0 +1,7 @@
+// { dg-options "-frepo" }
+
+extern "C" inline void f() {}
+
+int main () {
+ f();
+}
diff --git a/gcc/testsuite/g++.dg/template/repo1.C b/gcc/testsuite/g++.dg/template/repo1.C
new file mode 100644
index 00000000000..3650247cd12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/repo1.C
@@ -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 () {}
+
diff --git a/gcc/testsuite/g++.dg/warn/Winline-1.C b/gcc/testsuite/g++.dg/warn/Winline-1.C
index f9ee4658315..e1a7e832a30 100644
--- a/gcc/testsuite/g++.dg/warn/Winline-1.C
+++ b/gcc/testsuite/g++.dg/warn/Winline-1.C
@@ -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); }
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 803d609068f..7080df8267b 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -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]
diff --git a/gcc/tlink.c b/gcc/tlink.c
index 6406615b5e3..2c5da908394 100644
--- a/gcc/tlink.c
+++ b/gcc/tlink.c
@@ -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;
}