c-common.h (lang_post_pch_load): New variable.
authorMark Mitchell <mark@codesourcery.com>
Thu, 29 Jul 2004 17:59:31 +0000 (17:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 29 Jul 2004 17:59:31 +0000 (17:59 +0000)
* c-common.h (lang_post_pch_load): New variable.
* c-pch.c (lang_post_pch_load): Define it.
(c_common_read_pch): Use it.
* cgraphunit.c (record_call_1): Give the front end a chance to
record additional needed entities when a variable is marked as
needed.
* tlink.c (recompile_files): Robustify.
(scan_linker_output): If a symbol is assigned to a file,
but after recompilation is not present there, issue an error
message.

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

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

From-SVN: r85309

33 files changed:
gcc/ChangeLog
gcc/c-common.h
gcc/c-pch.c
gcc/cgraphunit.c
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/optimize.c
gcc/cp/pt.c
gcc/cp/repo.c
gcc/cp/rtti.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/inline1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/local1-a.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/local1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle11.C
gcc/testsuite/g++.dg/abi/mangle12.C
gcc/testsuite/g++.dg/abi/mangle17.C
gcc/testsuite/g++.dg/abi/mangle20-2.C
gcc/testsuite/g++.dg/opt/interface1-a.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/interface1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/interface1.h [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/repo1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/repo1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Winline-1.C
gcc/testsuite/lib/gcc-dg.exp
gcc/tlink.c

index dbda154ab8d9f779158da42c41dc2309936f9bf9..1a6e4e130d3b2e47d13db0952f93791b5771416e 100644 (file)
@@ -1,3 +1,16 @@
+2004-07-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * c-common.h (lang_post_pch_load): New variable.
+       * c-pch.c (lang_post_pch_load): Define it.
+       (c_common_read_pch): Use it.
+       * cgraphunit.c (record_call_1): Give the front end a chance to
+       record additional needed entities when a variable is marked as
+       needed.
+       * tlink.c (recompile_files): Robustify.
+       (scan_linker_output): If a symbol is assigned to a file,
+       but after recompilation is not present there, issue an error
+       message.
+
 2004-07-29  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
 
        * tree-ssa-loop-im.c (force_move_till_expr, force_move_till):
index 6df90a4f21556ecbc9e82cedfbb6edfc127c272b..63972dc96bb56a9748515ec4d605288f9950954b 100644 (file)
@@ -286,6 +286,10 @@ extern void (*lang_expand_function_end) (void);
    noreturn attribute.  */
 extern int (*lang_missing_noreturn_ok_p) (tree);
 
+/* If non-NULL, this function is called after a precompile header file
+   is loaded.  */
+extern void (*lang_post_pch_load) (void);
+
 extern void push_file_scope (void);
 extern void pop_file_scope (void);
 extern int yyparse (void);
index eb043bd089eaca213c14afcf70fcb4d9f7779902..21c3135b1102b0f4d0e2e791c3769913d5d87a13 100644 (file)
@@ -384,6 +384,10 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
     return result == 0;
 }
 
+/* If non-NULL, this function is called after a precompile header file
+   is loaded.  */
+void (*lang_post_pch_load) (void);
+
 /* Load in the PCH file NAME, open on FD.  It was originally searched for
    by ORIG_NAME.  */
 
@@ -443,6 +447,11 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
     return;
 
   fclose (f);
+  
+  /* Give the front end a chance to take action after a PCH file has
+     been loadeded.  */
+  if (lang_post_pch_load)
+    (*lang_post_pch_load) ();
 }
 
 /* Indicate that no more PCH files should be read.  */
index 059ae86081e3bd718cf03beea0f20165a38d3176..9e903e09b9db27a03657c1c14cf04bb6377062a7 100644 (file)
@@ -400,7 +400,12 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
         by this function and re-examine whether the decl is actually used
         after rtl has been generated.  */
       if (TREE_STATIC (t))
-        cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
+       {
+         cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
+         if (lang_hooks.callgraph.analyze_expr)
+           return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees, 
+                                                     data);
+       }
       break;
 
     case ADDR_EXPR:
index da4dad7448b0e6010542b2b289bc5ad71e45f8ea..d87584ec711181767084a29bac7d9a8a23cfc979 100644 (file)
@@ -1,3 +1,103 @@
+2004-07-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (IDENTIFIER_REPO_CHOSEN): Define.
+       (lang_decl_flags): Narrow the width of "languages".  Add
+       repo_available_p.
+       (DECL_NEEDED_P): Remove.
+       (FOR_EACH_CLONE): New macro.
+       (DECL_REPO_AVAILABLE_P): Likewise.
+       (DECL_TINFO_P): Likewise.
+       (set_linkage_according_to_type): Declare.
+       (import_export_vtable): Remove.
+       (import_export_tinfo): Likewise.
+       (mark_needed): New function.
+       (decl_needed_p): Likewise.
+       (note_vauge_linkage_fn): Likewise.
+       (init_repo): Change prototype.
+       (repo_template_used): Remove.
+       (repo_template_instantiated): Likewise.
+       (repo_emit_p): New function.
+       (repo_export_class_p): Likewise.
+       (no_linkage_check): Change prototype.
+       * class.c (set_linkage_according_to_type): New function.
+       (build_vtable): Use it.  Do not call import_export_vtable.  Set
+       DECL_IGNORED_P if appropriate.
+       * decl.c (duplicate_decls): Preserve DECL_REPO_AVAILABLE_P.
+       (make_rtL_for_nonlocal_decls): Check for template instantiations
+       explicitly.
+       (grokfndecl): Adjust call to no_linkage_check.
+       (set_linkage_for_static_data_member): New function.
+       (grokvardecl): Use it.  Adjust call to no_linkage_check.
+       (grokdeclarator): Use set_linkage_for_static_data_member.
+       * decl2.c (note_vague_linkage_fn): New function.
+       (note_vague_linkage_var): Likewise.
+       (finish_static_data_member_decl): Use it.
+       (import_export_vtable): Remove.
+       (import_export_class): Use repo_export_class_p.
+       (var_finalized_p): Simplify.
+       (maybe_emit_vtables): Simplify.
+       (mark_needed): New function.
+       (decl_needed_p): Likewise.
+       (import_export_decl): Add documentation and consistency checks.
+       Use repo_emit_p.  Handle virtual tables and RTTI information
+       here.
+       (import_export_tinfo): Remove.
+       (write_out_vars): Call import_export_decl.
+       (cxx_callgraph_analyze_expr): Ensure that all vtables are emitted
+       whenever one is.
+       (finish_file): Use decl_needed_p.  Do not call import_export_decl
+       for undefined static data members.  Do not warn about undefined
+       inlines when using a repository.
+       (mark_used): Use note_vague_linkage_fn.  Always defer template
+       instantiations.
+       * lex.c (cxx_init): Adjust call to init_repo.  Always set
+       flag_unit_at_a-time.
+       * method.c (synthesize_method): Remove unncessary
+       import_export_decl call.
+       (implicitly_declare_fn): Use set_linkage_according_to_type.
+       * optimize.c (maybe_clone_body): Use FOR_EACH_CLONE.
+       * pt.c (instantiate_class_template): Don't redundantly add classes
+       to keyed_classes.  Don't call repo_template_used.
+       (tsubst_decl): Set DECL_INTERFACE_KNOWN for instantiations of
+       templates with internal linkage.
+       (check_instantiated_args): Adjust call to no_linkage_check.
+       (instantiate_template): Use FOR_EACH_CLONE.
+       (mark_definable): New function.
+       (mark_decl_instantiated): Use it.
+       (do_decl_instantiation): Adjust tests for explicit instantiation
+       after "extern template".
+       (instantiate_class_member): Do not use repo_template_instantiated.
+       (do_type_instantiation): Simplify.
+       (instantiate_decl): Use mark_definable.  Check repo_emit_p.
+       Simplify.
+       * repo.c (repo_get_id): Remove.
+       (original_repo): Remove.
+       (IDENTIFIER_REPO_USED): Remove.
+       (IDENTIFIER_REPO_CHOSEN): Remove.
+       Remove all #if 0'd code.
+       (repo_template_used): Remove.
+       (repo_template_instantiated): Remove.
+       (temporary_obstack_initialized_p): New variable.
+       (init_repo): Register with lang_post_pch_load.  Avoid creating
+       identifiers unnecessarily.  Don't use original_repo.  Close the
+       file here.
+       (reopen_repo_file_for_write): Not here.
+       (finish_repo): Always write out a new repository file.
+       (repo_emit_p): New function.
+       (repo_export_class_p): Likewise.
+       * rtti.c (get_tinfo_decl): Use set_linkage_according_to_type.
+       (involves_incomplete_p): New function.
+       (tinfo_base_init): Use it.
+       (ptr_initializer): Remove non_public_ptr parameter.
+       (ptm_initializer): Likewise.
+       (get_pseudo_ti_init): Likewise.
+       (unemitted_tinfo_decl_p): Remove.
+       (emit_tinfo_decl): Use import_export_decl.
+       * semantics.c (expand_body): Move updates of static_ctors and
+       static_dtors to ...
+       (expand_or_defer_fn): ... here.
+       * tree.c (no_linkage_check): Add relaxed_p parameter.
+       
 2004-07-28  Eric Christopher  <echristo@redhat.com>
 
        * cp-lang.c (LANG_HOOKS_UNSAFE_FOR_REEVAL): Delete.
index 8da2e5865486dfa24fff00051b69b72ca78f175f..365febbb7040ecd9a8cecc7bb8f433d2d22da908 100644 (file)
@@ -581,6 +581,32 @@ get_vtt_name (tree type)
   return mangle_vtt_for_type (type);
 }
 
+/* DECL is an entity associated with TYPE, like a virtual table or an
+   implicitly generated constructor.  Determine whether or not DECL
+   should have external or internal linkage at the object file
+   level.  This routine does not deal with COMDAT linkage and other
+   similar complexities; it simply sets TREE_PUBLIC if it possible for
+   entities in other translation units to contain copies of DECL, in
+   the abstract.  */
+
+void
+set_linkage_according_to_type (tree type, tree decl)
+{
+  /* If TYPE involves a local class in a function with internal
+     linkage, then DECL should have internal linkage too.  Other local
+     classes have no linkage -- but if their containing functions
+     have external linkage, it makes sense for DECL to have external
+     linkage too.  That will allow template definitions to be merged,
+     for example.  */
+  if (no_linkage_check (type, /*relaxed_p=*/true))
+    {
+      TREE_PUBLIC (decl) = 0;
+      DECL_INTERFACE_KNOWN (decl) = 1;
+    }
+  else
+    TREE_PUBLIC (decl) = 1;
+}
+
 /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
    (For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
    Use NAME for the name of the vtable, and VTABLE_TYPE for its type.  */
@@ -601,17 +627,42 @@ build_vtable (tree class_type, tree name, tree vtable_type)
   DECL_VIRTUAL_P (decl) = 1;
   DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
   DECL_VTABLE_OR_VTT_P (decl) = 1;
-
   /* At one time the vtable info was grabbed 2 words at a time.  This
      fails on sparc unless you have 8-byte alignment.  (tiemann) */
   DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
                           DECL_ALIGN (decl));
+  set_linkage_according_to_type (class_type, decl);
+  /* The vtable has not been defined -- yet.  */
+  DECL_EXTERNAL (decl) = 1;
+  DECL_NOT_REALLY_EXTERN (decl) = 1;
+
+  if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
+    /* Mark the VAR_DECL node representing the vtable itself as a
+       "gratuitous" one, thereby forcing dwarfout.c to ignore it.  It
+       is rather important that such things be ignored because any
+       effort to actually generate DWARF for them will run into
+       trouble when/if we encounter code like:
+       
+         #pragma interface
+        struct S { virtual void member (); };
+          
+       because the artificial declaration of the vtable itself (as
+       manufactured by the g++ front end) will say that the vtable is
+       a static member of `S' but only *after* the debug output for
+       the definition of `S' has already been output.  This causes
+       grief because the DWARF entry for the definition of the vtable
+       will try to refer back to an earlier *declaration* of the
+       vtable as a static member of `S' and there won't be one.  We
+       might be able to arrange to have the "vtable static member"
+       attached to the member list for `S' before the debug info for
+       `S' get written (which would solve the problem) but that would
+       require more intrusive changes to the g++ front end.  */
+    DECL_IGNORED_P (decl) = 1;
 
   /* The vtable's visibility is the class visibility.  There is no way
      to override the visibility for just the vtable. */
   DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
   DECL_VISIBILITY_SPECIFIED (decl) = CLASSTYPE_VISIBILITY_SPECIFIED (class_type);
-  import_export_vtable (decl, class_type, 0);
 
   return decl;
 }
index c69320fadbc07febc107d178e8eaba2af05c73a8..8d14911235d56df59240aaf15f2f7f310ca12273 100644 (file)
@@ -48,7 +48,7 @@ struct diagnostic_context;
       STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
       EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
       BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
-   1: IDENTIFIER_VIRTUAL_P.
+   1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
       DELETE_EXPR_USE_VEC (in DELETE_EXPR).
@@ -56,7 +56,7 @@ struct diagnostic_context;
       TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
       ICS_ELLIPSIS_FLAG (in _CONV)
       DECL_INITIALIZED_P (in VAR_DECL)
-   2: IDENTIFIER_OPNAME_P.
+   2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
       TYPE_POLYMORPHIC_P (in _TYPE)
       ICS_THIS_FLAG (in _CONV)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@@ -70,9 +70,10 @@ struct diagnostic_context;
    4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
           or FIELD_DECL).
       IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
+      DECL_TINFO_P (in VAR_DECL)
    5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
       DECL_VTABLE_OR_VTT_P (in VAR_DECL)
-   6: For future expansion
+   6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
 
    Usage of TYPE_LANG_FLAG_?:
    0: TYPE_DEPENDENT_P
@@ -375,6 +376,12 @@ typedef enum cp_id_kind
 #define IDENTIFIER_CTOR_OR_DTOR_P(NODE) \
   TREE_LANG_FLAG_3 (NODE)
 
+/* True iff NAME is the DECL_ASSEMBLER_NAME for an entity with vague
+   linkage which the prelinker has assigned to this translation
+   unit.  */
+#define IDENTIFIER_REPO_CHOSEN(NAME) \
+  (TREE_LANG_FLAG_6 (NAME))
+
 /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
 #define C_TYPE_FIELDS_READONLY(TYPE) \
   (LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly)
@@ -1515,7 +1522,11 @@ struct lang_type GTY(())
 
 struct lang_decl_flags GTY(())
 {
-  ENUM_BITFIELD(languages) language : 8;
+  ENUM_BITFIELD(languages) language : 4;
+  unsigned global_ctor_p : 1;
+  unsigned global_dtor_p : 1;
+  unsigned anticipated_p : 1;
+  unsigned template_conv_p : 1;
 
   unsigned operator_attr : 1;
   unsigned constructor_attr : 1;
@@ -1534,14 +1545,12 @@ struct lang_decl_flags GTY(())
   unsigned initialized_in_class : 1;
   unsigned assignment_operator_p : 1;
 
-  unsigned global_ctor_p : 1;
-  unsigned global_dtor_p : 1;
-  unsigned anticipated_p : 1;
-  unsigned template_conv_p : 1;
   unsigned u1sel : 1;
   unsigned u2sel : 1;
   unsigned can_be_full : 1;
   unsigned this_thunk_p : 1;
+  unsigned repo_available_p : 1;
+  unsigned dummy : 3;
 
   union lang_decl_u {
     /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
@@ -1631,19 +1640,6 @@ struct lang_decl GTY(())
 
 #endif /* ENABLE_TREE_CHECKING */
 
-/* DECL_NEEDED_P holds of a declaration when we need to emit its
-   definition.  This is true when the back-end tells us that
-   the symbol has been referenced in the generated code.  If, however,
-   we are not generating code, then it is also true when a symbol has
-   just been used somewhere, even if it's not really needed.  We need
-   anything that isn't comdat, but we don't know for sure whether or
-   not something is comdat until end-of-file.  */
-#define DECL_NEEDED_P(DECL)                                    \
-  ((at_eof && TREE_PUBLIC (DECL) && !DECL_COMDAT (DECL))       \
-   || (DECL_ASSEMBLER_NAME_SET_P (DECL)                                \
-       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \
-   || (((flag_syntax_only || flag_unit_at_a_time) && TREE_USED (DECL))))
-
 /* For a FUNCTION_DECL or a VAR_DECL, the language linkage for the
    declaration.  Some entities (like a member function in a local
    class, or a local variable) do not have linkage at all, and this
@@ -1730,6 +1726,21 @@ struct lang_decl GTY(())
 #define DECL_CLONED_FUNCTION(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function)
 
+/* Perform an action for each clone of FN, if FN is a function with
+   clones.  This macro should be used like:
+   
+      FOR_EACH_CLONE (clone, fn)
+        { ... }
+
+  */
+#define FOR_EACH_CLONE(CLONE, FN)                      \
+  if (TREE_CODE (FN) == FUNCTION_DECL                  \
+      && (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (FN)      \
+         || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (FN)))   \
+     for (CLONE = TREE_CHAIN (FN);                     \
+         CLONE && DECL_CLONED_FUNCTION_P (CLONE);      \
+         CLONE = TREE_CHAIN (CLONE))
+
 /* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS.  */
 #define DECL_DISCRIMINATOR_P(NODE)     \
   (TREE_CODE (NODE) == VAR_DECL                \
@@ -1921,6 +1932,11 @@ struct lang_decl GTY(())
    DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1,                   \
    DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING))
 
+/* True iff DECL is an entity with vague linkage whose definition is
+   available in this translation unit.  */
+#define DECL_REPO_AVAILABLE_P(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->decl_flags.repo_available_p)
+
 /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
    template function.  */
 #define DECL_PRETTY_FUNCTION_P(NODE) \
@@ -1965,6 +1981,10 @@ struct lang_decl GTY(())
   (DECL_CONTEXT (NODE) \
    && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL)
 
+/* 1 iff VAR_DECL node NODE is a type-info decl.  This flag is set for
+   both the primary typeinfo object and the associated NTBS name.  */
+#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE))
+
 /* 1 iff VAR_DECL node NODE is virtual table or VTT.  */
 #define DECL_VTABLE_OR_VTT_P(NODE) TREE_LANG_FLAG_5 (VAR_DECL_CHECK (NODE))
 
@@ -3643,6 +3663,7 @@ extern tree get_primary_binfo                   (tree);
 extern void debug_class                                (tree);
 extern void debug_thunks                       (tree);
 extern tree cp_fold_obj_type_ref               (tree, tree);
+extern void set_linkage_according_to_type       (tree, tree);
 
 /* in cvt.c */
 extern tree convert_to_reference (tree, tree, int, int, tree);
@@ -3787,9 +3808,7 @@ extern tree finish_table (tree, tree, tree, int);
 extern tree coerce_new_type (tree);
 extern tree coerce_delete_type (tree);
 extern void comdat_linkage (tree);
-extern void import_export_vtable (tree, tree, int);
 extern void import_export_decl (tree);
-extern void import_export_tinfo        (tree, tree, bool);
 extern tree build_cleanup                      (tree);
 extern tree build_offset_ref_call_from_tree     (tree, tree);
 extern void check_default_args (tree);
@@ -3801,6 +3820,9 @@ extern tree get_guard (tree);
 extern tree get_guard_cond (tree);
 extern tree set_guard (tree);
 extern tree cxx_callgraph_analyze_expr (tree *, int *, tree);
+extern void mark_needed (tree);
+extern bool decl_needed_p (tree);
+extern void note_vague_linkage_fn (tree);
 
 /* XXX Not i18n clean.  */
 #define cp_deprecated(STR)                                             \
@@ -3973,9 +3995,9 @@ extern bool reregister_specialization           (tree, tree, tree);
 extern tree fold_non_dependent_expr             (tree);
 
 /* in repo.c */
-extern void repo_template_used (tree);
-extern void repo_template_instantiated (tree, bool);
-extern void init_repo (const char *);
+extern void init_repo (void);
+extern int repo_emit_p (tree);
+extern bool repo_export_class_p (tree);
 extern void finish_repo (void);
 
 /* in rtti.c */
@@ -4192,7 +4214,7 @@ extern tree error_type                            (tree);
 extern int varargs_function_p                  (tree);
 extern int really_overloaded_fn                        (tree);
 extern bool cp_tree_equal                      (tree, tree);
-extern tree no_linkage_check                   (tree);
+extern tree no_linkage_check                   (tree, bool);
 extern void debug_binfo                                (tree);
 extern tree build_dummy_object                 (tree);
 extern tree maybe_dummy_object                 (tree, tree *);
index f901d98f3dbe097ec011fd7f2fd3dc96c5454975..c84c4be7687fe9e36fc8f1196dd7d3a77f89143e 100644 (file)
@@ -1753,6 +1753,7 @@ duplicate_decls (tree newdecl, tree olddecl)
       DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
        DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+      DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       DECL_INITIALIZED_IN_CLASS_P (newdecl)
         |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
@@ -4571,7 +4572,8 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
       defer_p = 1;
     }
   /* Likewise for template instantiations.  */
-  else if (DECL_COMDAT (decl))
+  else if (DECL_LANG_SPECIFIC (decl)
+          && DECL_IMPLICIT_INSTANTIATION (decl))
     defer_p = 1;
 
   /* If we're deferring the variable, we only need to make RTL if
@@ -5513,7 +5515,8 @@ grokfndecl (tree ctype,
         declare an entity with linkage.
 
         Only check this for public decls for now.  See core 319, 389.  */
-      t = no_linkage_check (TREE_TYPE (decl));
+      t = no_linkage_check (TREE_TYPE (decl),
+                           /*relaxed_p=*/false);
       if (t)
        {
          if (TYPE_ANONYMOUS_P (t))
@@ -5723,6 +5726,25 @@ grokfndecl (tree ctype,
   return decl;
 }
 
+/* DECL is a VAR_DECL for a static data member.  Set flags to reflect
+   the linkage that DECL will receive in the object file.  */
+
+static void
+set_linkage_for_static_data_member (tree decl)
+{
+  /* A static data member always has static storage duration and
+     external linkage.  Note that static data members are forbidden in
+     local classes -- the only situation in which a class has
+     non-external linkage.  */
+  TREE_PUBLIC (decl) = 1;
+  TREE_STATIC (decl) = 1;
+  /* For non-template classes, static data members are always put
+     out in exactly those files where they are defined, just as
+     with ordinarly namespace-scope variables.  */
+  if (!processing_template_decl)
+    DECL_INTERFACE_KNOWN (decl) = 1;
+}
+
 /* Create a VAR_DECL named NAME with the indicated TYPE.
 
    If SCOPE is non-NULL, it is the class type or namespace containing
@@ -5782,12 +5804,10 @@ grokvardecl (tree type,
       DECL_EXTERNAL (decl) = !initialized;
     }
 
-  /* In class context, static means one per class,
-     public access, and static storage.  */
   if (DECL_CLASS_SCOPE_P (decl))
     {
-      TREE_PUBLIC (decl) = 1;
-      TREE_STATIC (decl) = 1;
+      set_linkage_for_static_data_member (decl);
+      /* This function is only called with out-of-class definitions.  */
       DECL_EXTERNAL (decl) = 0;
     }
   /* At top level, either `static' or no s.c. makes a definition
@@ -5822,7 +5842,8 @@ grokvardecl (tree type,
         declare an entity with linkage.
 
         Only check this for public decls for now.  */
-      tree t = no_linkage_check (TREE_TYPE (decl));
+      tree t = no_linkage_check (TREE_TYPE (decl),
+                                /*relaxed_p=*/false);
       if (t)
        {
          if (TYPE_ANONYMOUS_P (t))
@@ -7859,9 +7880,11 @@ grokdeclarator (const cp_declarator *declarator,
                /* C++ allows static class members.  All other work
                   for this is done by grokfield.  */
                decl = build_lang_decl (VAR_DECL, unqualified_id, type);
-               TREE_STATIC (decl) = 1;
-               /* In class context, 'static' means public access.  */
-               TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
+               set_linkage_for_static_data_member (decl);
+               /* Even if there is an in-class initialization, DECL
+                  is considered undefined until an out-of-class
+                  definition is provided.  */
+               DECL_EXTERNAL (decl) = 1;
              }
            else
              {
@@ -9842,6 +9865,11 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        DECL_EXTERNAL (decl1) = 0;
       DECL_NOT_REALLY_EXTERN (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
+      /* If this function is in an interface implemented in this file,
+        make sure that the backend knows to emit this function 
+        here.  */
+      if (!DECL_EXTERNAL (decl1))
+       mark_needed (decl1);
     }
   else if (interface_unknown && interface_only
           && ! DECL_TEMPLATE_INSTANTIATION (decl1))
index ea9aa49c13c574fb36c08f575876ecf3f87f91d3..40322ab31cc4e5362a5a6c60a73b380db33b94db 100644 (file)
@@ -729,6 +729,33 @@ check_classfn (tree ctype, tree function, tree template_parms)
   return NULL_TREE;
 }
 
+/* DECL is a function with vague linkage.  Remember it so that at the
+   end of the translation unit we can decide whether or not to emit
+   it.  */
+
+void
+note_vague_linkage_fn (tree decl)
+{
+  if (!DECL_DEFERRED_FN (decl))
+    {
+      DECL_DEFERRED_FN (decl) = 1;
+      DECL_DEFER_OUTPUT (decl) = 1;
+      if (!deferred_fns)
+       VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
+      VARRAY_PUSH_TREE (deferred_fns, decl);
+    }
+}
+
+/* Like note_vague_linkage_fn but for variables.  */
+
+static void
+note_vague_linkage_var (tree var)
+{
+  if (!pending_statics)
+    VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
+  VARRAY_PUSH_TREE (pending_statics, var);
+}
+
 /* We have just processed the DECL, which is a static data member.
    Its initializer, if present, is INIT.  The ASMSPEC_TREE, if
    present, is the assembly-language name for the data member.
@@ -750,11 +777,7 @@ finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
     DECL_INITIAL (decl) = error_mark_node;
 
   if (! processing_template_decl)
-    {
-      if (!pending_statics)
-       VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
-      VARRAY_PUSH_TREE (pending_statics, decl);
-    }
+    note_vague_linkage_var (decl);
 
   if (LOCAL_CLASS_P (current_class_type))
     pedwarn ("local class `%#T' shall not have static data member `%#D'",
@@ -1403,51 +1426,6 @@ maybe_make_one_only (tree decl)
     }
 }
 
-/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
-   based on TYPE and other static flags.
-
-   Note that anything public is tagged TREE_PUBLIC, whether
-   it's public in this file or in another one.  */
-
-void
-import_export_vtable (tree decl, tree type, int final)
-{
-  if (DECL_INTERFACE_KNOWN (decl))
-    return;
-
-  if (TYPE_FOR_JAVA (type))
-    {
-      TREE_PUBLIC (decl) = 1;
-      DECL_EXTERNAL (decl) = 1;
-      DECL_INTERFACE_KNOWN (decl) = 1;
-    }
-  else if (CLASSTYPE_INTERFACE_KNOWN (type))
-    {
-      TREE_PUBLIC (decl) = 1;
-      DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type);
-      DECL_INTERFACE_KNOWN (decl) = 1;
-    }
-  else
-    {
-      /* We can only wait to decide if we have real non-inline virtual
-        functions in our class, or if we come from a template.  */
-
-      int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
-                  || CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
-
-      if (final || ! found)
-       {
-         comdat_linkage (decl);
-         DECL_EXTERNAL (decl) = 0;
-       }
-      else
-       {
-         TREE_PUBLIC (decl) = 1;
-         DECL_EXTERNAL (decl) = 1;
-       }
-    }
-}
-
 /* Determine whether or not we want to specifically import or export CTYPE,
    using various heuristics.  */
 
@@ -1479,21 +1457,18 @@ import_export_class (tree ctype)
     import_export = -1;
   else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
     import_export = 1;
-
-  /* If we got -fno-implicit-templates, we import template classes that
-     weren't explicitly instantiated.  */
-  if (import_export == 0
-      && CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
-      && ! flag_implicit_templates)
-    import_export = -1;
-
-  /* Base our import/export status on that of the first non-inline,
-     non-pure virtual function, if any.  */
-  if (import_export == 0
-      && TYPE_POLYMORPHIC_P (ctype))
-    {
+  else if (CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
+          && !flag_implicit_templates)
+    /* For a template class, without -fimplicit-templates, check the
+       repository.  If the virtual table is assigned to this
+       translation unit, then export the class; otherwise, import
+       it.  */
+      import_export = repo_export_class_p (ctype) ? 1 : -1;
+  else if (TYPE_POLYMORPHIC_P (ctype))
+    {
+      /* The ABI specifies that the virtual table and associated
+        information are emitted with the key method, if any.  */
       tree method = CLASSTYPE_KEY_METHOD (ctype);
-
       /* If weak symbol support is not available, then we must be
         careful not to emit the vtable when the key function is
         inline.  An inline function can be defined in multiple
@@ -1525,10 +1500,52 @@ import_export_class (tree ctype)
 static bool
 var_finalized_p (tree var)
 {
-  if (flag_unit_at_a_time)
-    return cgraph_varpool_node (var)->finalized;
-  else
-    return TREE_ASM_WRITTEN (var);
+  return cgraph_varpool_node (var)->finalized;
+}
+
+/* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
+   must be emitted in this translation unit.  Mark it as such.  */
+
+void
+mark_needed (tree decl)
+{
+  /* It's possible that we no longer need to set
+     TREE_SYMBOL_REFERENCED here directly, but doing so is
+     harmless.  */
+  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
+  mark_decl_referenced (decl);
+}
+
+/* DECL is either a FUNCTION_DECL or a VAR_DECL.  This function
+   returns true if a definition of this entity should be provided in
+   this object file.  Callers use this function to determine whether
+   or not to let the back end know that a definition of DECL is
+   available in this translation unit.  */
+
+bool
+decl_needed_p (tree decl)
+{
+  my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+                     || TREE_CODE (decl) == FUNCTION_DECL,
+                     20040726);
+  /* This function should only be called at the end of the translation
+     unit.  We cannot be sure of whether or not something will be
+     COMDAT until that point.  */
+  my_friendly_assert (at_eof, 20040726);
+
+  /* All entities with external linkage that are not COMDAT should be
+     emitted; they may be referred to from other object files.  */
+  if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
+    return true;
+  /* If this entity was used, let the back-end see it; it will decide
+     whether or not to emit it into the object file.  */
+  if (TREE_USED (decl) 
+      || (DECL_ASSEMBLER_NAME_SET_P (decl)
+         && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+      return true;
+  /* Otherwise, DECL does not need to be emitted -- yet.  A subsequent
+     reference to DECL might cause it to be emitted later.  */
+  return false;
 }
 
 /* If necessary, write out the vtables for the dynamic class CTYPE.
@@ -1539,8 +1556,7 @@ maybe_emit_vtables (tree ctype)
 {
   tree vtbl;
   tree primary_vtbl;
-  bool needed = false;
-  bool weaken_vtables;
+  int needed = 0;
 
   /* If the vtables for this class have already been emitted there is
      nothing more to do.  */
@@ -1551,16 +1567,14 @@ maybe_emit_vtables (tree ctype)
   if (TREE_TYPE (primary_vtbl) == void_type_node)
     return false;
 
-  import_export_class (ctype);
-
   /* See if any of the vtables are needed.  */
   for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
     {
-      import_export_vtable (vtbl, ctype, 1);
-      if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
-       break;
+      import_export_decl (vtbl);
+      if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl))
+       needed = 1;
     }
-  if (!vtbl)
+  if (!needed)
     {
       /* If the references to this class' vtables are optimized away,
         still emit the appropriate debugging information.  See
@@ -1570,45 +1584,14 @@ maybe_emit_vtables (tree ctype)
        note_debug_info_needed (ctype);
       return false;
     }
-  else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl))
-    needed = true;
-  
-  /* Determine whether to make vtables weak.  The ABI requires that we
-      do so.  There are two cases in which we have to violate the ABI
-      specification: targets where we don't have weak symbols
-      (obviously), and targets where weak symbols don't appear in
-      static archives' tables of contents.  On such targets, avoiding
-      undefined symbol link errors requires that we only make a symbol
-      weak if we know that it will be emitted everywhere it's needed.
-      So on such targets we don't make vtables weak in the common case
-      where we're emitting a vtable of a nontemplate class in the 
-      translation unit containing the definition of a noninline key
-      method. */
-  if (flag_weak && !TARGET_WEAK_NOT_IN_ARCHIVE_TOC)
-    weaken_vtables = true;
-  else if (flag_weak)
-    {
-      if (CLASSTYPE_USE_TEMPLATE (ctype))
-       weaken_vtables = CLASSTYPE_IMPLICIT_INSTANTIATION (ctype);
-      else
-       weaken_vtables = !CLASSTYPE_KEY_METHOD (ctype)
-         || DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (ctype));
-    }
-  else
-    weaken_vtables = false;
 
   /* The ABI requires that we emit all of the vtables if we emit any
      of them.  */
   for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
     {
-      /* Write it out.  */
-      import_export_vtable (vtbl, ctype, 1);
+      /* Mark entities references from the virtual table as used.  */
       mark_vtable_entries (vtbl);
 
-      /* If we know that DECL is needed, mark it as such for the varpool.  */
-      if (needed)
-       cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
-
       if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
        {
          /* It had better be all done at compile-time.  */
@@ -1616,36 +1599,8 @@ maybe_emit_vtables (tree ctype)
            abort ();
        }
 
-      if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
-       {
-         /* Mark the VAR_DECL node representing the vtable itself as a
-            "gratuitous" one, thereby forcing dwarfout.c to ignore it.
-            It is rather important that such things be ignored because
-            any effort to actually generate DWARF for them will run
-            into trouble when/if we encounter code like:
-
-               #pragma interface
-               struct S { virtual void member (); };
-
-             because the artificial declaration of the vtable itself (as
-             manufactured by the g++ front end) will say that the vtable
-             is a static member of `S' but only *after* the debug output
-             for the definition of `S' has already been output.  This causes
-             grief because the DWARF entry for the definition of the vtable
-             will try to refer back to an earlier *declaration* of the
-             vtable as a static member of `S' and there won't be one.
-             We might be able to arrange to have the "vtable static member"
-             attached to the member list for `S' before the debug info for
-             `S' get written (which would solve the problem) but that would
-             require more intrusive changes to the g++ front end.  */
-
-         DECL_IGNORED_P (vtbl) = 1;
-       }
-
-      /* Always make vtables weak.  Or at least almost always; see above. */
-      if (weaken_vtables)
-       comdat_linkage (vtbl);
-
+      /* Write it out.  */
+      DECL_EXTERNAL (vtbl) = 0;
       rest_of_decl_compilation (vtbl, NULL, 1, 1);
 
       /* Because we're only doing syntax-checking, we'll never end up
@@ -1661,38 +1616,194 @@ maybe_emit_vtables (tree ctype)
   return true;
 }
 
-/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
-   inline function or template instantiation at end-of-file.  */
+/* DECL is a FUNCTION_DECL or VAR_DECL.  If the object file linkage
+   for DECL has not already been determined, do so now by setting
+   DECL_EXTERNAL, DECL_COMDAT and other related flags.  Until this
+   function is called entities with vague linkage whose definitions
+   are available must have TREE_PUBLIC set.
+
+   If this function decides to place DECL in COMDAT, it will set
+   appropriate flags -- but will not clear DECL_EXTERNAL.  It is up to
+   the caller to decide whether or not to clear DECL_EXTERNAL.  Some
+   callers defer that decision until it is clear that DECL is actually
+   required.  */
 
 void
 import_export_decl (tree decl)
 {
+  int emit_p;
+  bool comdat_p;
+  bool import_p;
+
   if (DECL_INTERFACE_KNOWN (decl))
     return;
 
-  if (DECL_TEMPLATE_INSTANTIATION (decl)
-      || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
-    {
-      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"
index c5b14460b94b8f79688677595e5ea5da981fa073..00adb7239c50b7d0a9c2c24a728ea7196b325db3 100644 (file)
@@ -361,6 +361,17 @@ cxx_init (void)
 
   interface_unknown = 1;
 
+  /* The fact that G++ uses COMDAT for many entities (inline
+     functions, template instantiations, virtual tables, etc.) mean
+     that it is fundamentally unreliable to try to make decisions
+     about whether or not to output a particular entity until the end
+     of the compilation.  However, the inliner requires that functions
+     be provided to the back end if they are to be inlined.
+     Therefore, we always use unit-at-a-time mode; in that mode, we
+     can provide entities to the back end and it will decide what to
+     emit based on what is actually needed.  */
+  flag_unit_at_a_time = 1;
+
   if (c_common_init () == false)
     {
       pop_srcloc();
@@ -369,7 +380,7 @@ cxx_init (void)
 
   init_cp_pragma ();
 
-  init_repo (main_input_filename);
+  init_repo ();
 
   pop_srcloc();
   return true;
index 07fbacf266a42d5f7594bab95c8aba213e029559..d741d3d3cd1e3b719d21cda2a62b020e1467dded 100644 (file)
@@ -700,9 +700,6 @@ synthesize_method (tree fndecl)
   bool need_body = true;
   tree stmt;
 
-  if (at_eof)
-    import_export_decl (fndecl);
-
   /* If we've been asked to synthesize a clone, just synthesize the
      cloned function instead.  Doing so will automatically fill in the
      body for the clone.  */
@@ -1014,7 +1011,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
   grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
               TYPE_UNQUALIFIED);
   grok_special_member_properties (fn);
-  TREE_PUBLIC (fn) = !decl_function_context (TYPE_MAIN_DECL (type));
+  set_linkage_according_to_type (type, fn);
   rest_of_decl_compilation (fn, /*asmspec=*/NULL,
                            toplevel_bindings_p (), at_eof);
   DECL_IN_AGGR_P (fn) = 1;
index 000d6cc4c27981f63bd81830918171cd549781ed..b94270eabd65cfe30ad8f4813912290276553fa3 100644 (file)
@@ -89,9 +89,7 @@ maybe_clone_body (tree fn)
   /* We know that any clones immediately follow FN in the TYPE_METHODS
      list.  */
   push_to_top_level ();
-  for (clone = TREE_CHAIN (fn);
-       clone && DECL_CLONED_FUNCTION_P (clone);
-       clone = TREE_CHAIN (clone))
+  FOR_EACH_CLONE (clone, fn)
     {
       tree parm;
       tree clone_parm;
index def63108bd4cf8230aa88f4b6f8a7961455cfe86..0ecbda0fa1566acc4b59f46a39f6a13fee5a7506 100644 (file)
@@ -5693,10 +5693,7 @@ instantiate_class_template (tree type)
 
   unreverse_member_declarations (type);
   finish_struct_1 (type);
-
-  /* Clear this now so repo_template_used is happy.  */
   TYPE_BEING_DEFINED (type) = 0;
-  repo_template_used (type);
 
   /* Now that the class is complete, instantiate default arguments for
      any member functions.  We don't do this earlier because the
@@ -5715,7 +5712,11 @@ instantiate_class_template (tree type)
   pop_deferring_access_checks ();
   pop_tinst_level ();
 
-  if (TYPE_CONTAINS_VPTR_P (type))
+  /* The vtable for a template class can be emitted in any translation
+     unit in which the class is instantiated.  When there is no key
+     method, however, finish_struct_1 will already have added TYPE to
+     the keyed_classes list.  */
+  if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type))
     keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
 
   return type;
@@ -6235,7 +6236,10 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
        TREE_STATIC (r) = 0;
        TREE_PUBLIC (r) = TREE_PUBLIC (t);
        DECL_EXTERNAL (r) = 1;
-       DECL_INTERFACE_KNOWN (r) = 0;
+       /* If this is an instantiation of a function with internal
+          linkage, we already know what object file linkage will be
+          assigned to the instantiation.  */
+       DECL_INTERFACE_KNOWN (r) = !TREE_PUBLIC (r);
        DECL_DEFER_OUTPUT (r) = 0;
        TREE_CHAIN (r) = NULL_TREE;
        DECL_PENDING_INLINE_INFO (r) = 0;
@@ -8564,7 +8568,7 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
             shall not be used to declare an entity with linkage.
             This implies that names with no linkage cannot be used as
             template arguments.  */
-         tree nt = no_linkage_check (t);
+         tree nt = no_linkage_check (t, /*relaxed_p=*/false);
 
          if (nt)
            {
@@ -8628,9 +8632,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
        return error_mark_node;
 
       /* Look for the clone.  */
-      for (clone = TREE_CHAIN (spec);
-          clone && DECL_CLONED_FUNCTION_P (clone);
-          clone = TREE_CHAIN (clone))
+      FOR_EACH_CLONE (clone, spec)
        if (DECL_NAME (clone) == DECL_NAME (tmpl))
          return clone;
       /* We should always have found the clone by now.  */
@@ -10076,9 +10078,20 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
     }
 }
 \f
+/* Note that DECL can be defined in this translation unit, if
+   required.  */
+
+static void
+mark_definable (tree decl)
+{
+  tree clone;
+  DECL_NOT_REALLY_EXTERN (decl) = 1;
+  FOR_EACH_CLONE (clone, decl)
+    DECL_NOT_REALLY_EXTERN (clone) = 1;
+}
+
 /* Called if RESULT is explicitly instantiated, or is a member of an
-   explicitly instantiated class, or if using -frepo and the
-   instantiation of RESULT has been assigned to this file.  */
+   explicitly instantiated class.  */
 
 void
 mark_decl_instantiated (tree result, int extern_p)
@@ -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.  */
index a9a5b35c293b51de6c71e720c180823545485dd6..b3edf4875fc0e08e87bd91b8a367a7d7a6afe885 100644 (file)
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "diagnostic.h"
 
-static tree repo_get_id (tree);
 static char *extract_string (char **);
 static const char *get_base_filename (const char *);
 static void open_repo_file (const char *);
@@ -45,162 +44,13 @@ static char *afgets (FILE *);
 static void reopen_repo_file_for_write (void);
 
 static GTY(()) tree pending_repo;
-static GTY(()) tree original_repo;
 static char *repo_name;
 static FILE *repo_file;
 
 static const char *old_args, *old_dir, *old_main;
 
 static struct obstack temporary_obstack;
-
-#define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
-#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
-
-#if 0
-/* Record the flags used to compile this translation unit.  */
-
-void
-repo_compile_flags (int argc, char **argv)
-{
-}
-
-/* If this template has not been seen before, add a note to the repository
-   saying where the declaration was.  This may be used to find the
-   definition at link time.  */
-
-void
-repo_template_declared (tree t)
-{}
-
-/* Note where the definition of a template lives so that instantiations can
-   be generated later.  */
-
-void
-repo_template_defined (tree t)
-{}
-
-/* Note where the definition of a class lives to that template
-   instantiations can use it.  */
-
-void
-repo_class_defined (tree t)
-{}
-#endif
-
-static tree
-repo_get_id (tree t)
-{
-  if (TYPE_P (t))
-    {
-      tree vtable;
-
-      /* If we're not done setting up the class, we may not have set up
-        the vtable, so going ahead would give the wrong answer.
-         See g++.pt/instantiate4.C.  */
-      if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
-       abort ();
-
-      vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
-
-      t = vtable;
-      if (t == NULL_TREE)
-       return t;
-    }
-  return DECL_ASSEMBLER_NAME (t);
-}
-
-/* Note that a template has been used.  If we can see the definition, offer
-   to emit it.  */
-
-void
-repo_template_used (tree t)
-{
-  tree id;
-
-  if (! flag_use_repository)
-    return;
-
-  id = repo_get_id (t);
-  if (id == NULL_TREE)
-    return;
-  
-  if (TYPE_P (t))
-    {
-      if (IDENTIFIER_REPO_CHOSEN (id))
-       mark_class_instantiated (t, 0);
-    }
-  else if (DECL_P (t))
-    {
-      if (IDENTIFIER_REPO_CHOSEN (id))
-       /* It doesn't make sense to instantiate a clone, so we
-          instantiate the cloned function instead.  Note that this
-          approach will not work correctly if collect2 assigns
-          different clones to different files -- but it shouldn't.  */
-       mark_decl_instantiated (DECL_CLONED_FUNCTION_P (t)
-                               ? DECL_CLONED_FUNCTION (t) : t, 
-                               0);
-    }
-  else
-    abort ();
-
-  if (! IDENTIFIER_REPO_USED (id))
-    {
-      IDENTIFIER_REPO_USED (id) = 1;
-      pending_repo = tree_cons (NULL_TREE, id, pending_repo);
-    }
-}
-
-#if 0
-/* Note that the vtable for a class has been used, and offer to emit it.  */
-
-static void
-repo_vtable_used (tree t)
-{
-  if (! flag_use_repository)
-    return;
-
-  pending_repo = tree_cons (NULL_TREE, t, pending_repo);
-}
-
-/* Note that an inline with external linkage has been used, and offer to
-   emit it.  */
-
-void
-repo_inline_used (tree fn)
-{
-  if (! flag_use_repository)
-    return;
-
-  /* Member functions of polymorphic classes go with their vtables.  */
-  if (DECL_FUNCTION_MEMBER_P (fn) 
-      && TYPE_POLYMORPHIC_P (DECL_CONTEXT (fn)))
-    {
-      repo_vtable_used (DECL_CONTEXT (fn));
-      return;
-    }
-
-  pending_repo = tree_cons (NULL_TREE, fn, pending_repo);
-}
-
-/* Note that a particular typeinfo node has been used, and offer to
-   emit it.  */
-
-void
-repo_tinfo_used (tree ti)
-{
-}
-#endif
-
-void
-repo_template_instantiated (tree t, bool extern_p)
-{
-  if (! extern_p)
-    {
-      tree id = repo_get_id (t);
-      if (id)
-       IDENTIFIER_REPO_CHOSEN (id) = 1;
-    }
-}
+static bool temporary_obstack_initialized_p;
 
 /* Parse a reasonable subset of shell quoting syntax.  */
 
@@ -298,16 +148,22 @@ afgets (FILE *stream)
 }
 
 void
-init_repo (const char *filename)
+init_repo (void)
 {
   char *buf;
 
   if (! flag_use_repository)
     return;
 
-  gcc_obstack_init (&temporary_obstack);
+  /* When a PCH file is loaded, the entire identifier table is
+     replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
+     So, we have to reread the repository file.  */
+  lang_post_pch_load = init_repo;
+
+  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"
index c6c9fc6acc44af98354acbcc99c2b5ba83e5f428..83e24c4e21c28aec70e87eaf17464ea5a3f72bb1 100644 (file)
@@ -89,18 +89,15 @@ static int qualifier_flags (tree);
 static bool target_incomplete_p (tree);
 static tree tinfo_base_init (tree, tree);
 static tree generic_initializer (tree, tree);
-static tree ptr_initializer (tree, tree, bool *);
-static tree ptm_initializer (tree, tree, bool *);
 static tree dfs_class_hint_mark (tree, void *);
 static tree dfs_class_hint_unmark (tree, void *);
 static int class_hint_flags (tree);
 static tree class_initializer (tree, tree, tree);
 static tree create_pseudo_type_info (const char *, int, ...);
-static tree get_pseudo_ti_init (tree, tree, bool *);
+static tree get_pseudo_ti_init (tree, tree);
 static tree get_pseudo_ti_desc (tree);
 static void create_tinfo_types (void);
 static bool typeinfo_in_lib_p (tree);
-static bool unemitted_tinfo_decl_p (tree);
 
 static int doing_runtime = 0;
 \f
@@ -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;
 }
index f6f71759478b5d17813d03b7625ba74e62046210..152d75ca1f0f9c22c36dcd7a72f7018e40904433 100644 (file)
@@ -2892,18 +2892,6 @@ expand_body (tree fn)
 
   extract_interface_info ();
 
-  /* If this function is marked with the constructor attribute, add it
-     to the list of functions to be called along with constructors
-     from static duration objects.  */
-  if (DECL_STATIC_CONSTRUCTOR (fn))
-    static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
-
-  /* If this function is marked with the destructor attribute, add it
-     to the list of functions to be called along with destructors from
-     static duration objects.  */
-  if (DECL_STATIC_DESTRUCTOR (fn))
-    static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
-
   if (DECL_CLONED_FUNCTION_P (fn))
     {
       /* If this is a clone, go through the other clones now and mark
@@ -2957,15 +2945,39 @@ expand_or_defer_fn (tree fn)
       return;
     }
 
+  /* If this function is marked with the constructor attribute, add it
+     to the list of functions to be called along with constructors
+     from static duration objects.  */
+  if (DECL_STATIC_CONSTRUCTOR (fn))
+    static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
+
+  /* If this function is marked with the destructor attribute, add it
+     to the list of functions to be called along with destructors from
+     static duration objects.  */
+  if (DECL_STATIC_DESTRUCTOR (fn))
+    static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
+
+  /* We make a decision about linkage for these functions at the end
+     of the compilation.  Until that point, we do not want the back
+     end to output them -- but we do want it to see the bodies of
+     these fucntions so that it can inline them as appropriate.  */
+  if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
+    {
+      if (!at_eof)
+       {
+         DECL_EXTERNAL (fn) = 1;
+         DECL_NOT_REALLY_EXTERN (fn) = 1;
+         note_vague_linkage_fn (fn);
+       }
+      else
+       import_export_decl (fn);
+    }
+
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)
     return;
 
-  /* Compute the appropriate object-file linkage for inline functions.  */
-  if (DECL_DECLARED_INLINE_P (fn))
-    import_export_decl (fn);
-
   function_depth++;
 
   /* Expand or defer, at the whim of the compilation unit manager.  */
index 79070f0629afaf8badec9853164b49af9f3b84d0..6a626e9470d21c497b336021117d7a4b213b2759 100644 (file)
@@ -1062,10 +1062,11 @@ find_tree (tree t, tree x)
 }
 
 /* Check if the type T depends on a type with no linkage and if so, return
-   it.  */
+   it.  If RELAXED_P then do not consider a class type declared within
+   a TREE_PUBLIC function to have no linkage.  */
 
 tree
-no_linkage_check (tree t)
+no_linkage_check (tree t, bool relaxed_p)
 {
   tree r;
 
@@ -1076,6 +1077,8 @@ no_linkage_check (tree t)
 
   switch (TREE_CODE (t))
     {
+      tree fn;
+
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
        goto ptrmem;
@@ -1085,25 +1088,28 @@ no_linkage_check (tree t)
        return NULL_TREE;
       /* Fall through.  */
     case ENUMERAL_TYPE:
-      if (decl_function_context (TYPE_MAIN_DECL (t))
-         || TYPE_ANONYMOUS_P (t))
+      if (TYPE_ANONYMOUS_P (t))
+       return t;
+      fn = decl_function_context (TYPE_MAIN_DECL (t));
+      if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
        return t;
       return NULL_TREE;
 
     case ARRAY_TYPE:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      return no_linkage_check (TREE_TYPE (t));
+      return no_linkage_check (TREE_TYPE (t), relaxed_p);
 
     case OFFSET_TYPE:
     ptrmem:
-      r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t));
+      r = no_linkage_check (TYPE_PTRMEM_POINTED_TO_TYPE (t),
+                           relaxed_p);
       if (r)
        return r;
-      return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t));
+      return no_linkage_check (TYPE_PTRMEM_CLASS_TYPE (t), relaxed_p);
 
     case METHOD_TYPE:
-      r = no_linkage_check (TYPE_METHOD_BASETYPE (t));
+      r = no_linkage_check (TYPE_METHOD_BASETYPE (t), relaxed_p);
       if (r)
        return r;
       /* Fall through.  */
@@ -1114,11 +1120,11 @@ no_linkage_check (tree t)
             parm && parm != void_list_node;
             parm = TREE_CHAIN (parm))
          {
-           r = no_linkage_check (TREE_VALUE (parm));
+           r = no_linkage_check (TREE_VALUE (parm), relaxed_p);
            if (r)
              return r;
          }
-       return no_linkage_check (TREE_TYPE (t));
+       return no_linkage_check (TREE_TYPE (t), relaxed_p);
       }
 
     default:
index c82cbe55ddc030185f4160b34c13e475e71bf7b6..5dc06fc7beb8100848e3028f24190591f7cd11cb 100644 (file)
@@ -1,3 +1,20 @@
+2004-07-29  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/inline1.C: New test.
+       * g++.dg/abi/local1-a.cc: Likewise.
+       * g++.dg/abi/local1.C: Likewise.
+       * g++.dg/abi/mangle11.C: Tweak location of warnings.
+       * g++.dg/abi/mangle12.C: Likewise.
+       * g++.dg/abi/mangle17.C: Likewise.
+       * g++.dg/abi/mangle20-2.C: Likewise.
+       * g++.dg/opt/interface1.C: Likewise.
+       * g++.dg/opt/interface1.h: Likewise.
+       * g++.dg/opt/interface1-a.cc: New test.
+       * g++.dg/parse/repo1.C: New test.
+       * g++.dg/template/repo1.C: Likewise.
+       * g++.dg/warn/Winline-1.C: Likewise.
+       * lib/gcc-dg.exp (gcc-dg-test-1): Fix -frepo handling.
+
 2004-07-29  Diego Novillo  <dnovillo@redhat.com>
 
        * gcc.dg/tree-ssa/20040729-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/abi/inline1.C b/gcc/testsuite/g++.dg/abi/inline1.C
new file mode 100644 (file)
index 0000000..97082aa
--- /dev/null
@@ -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 (file)
index 0000000..638479e
--- /dev/null
@@ -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 (file)
index 0000000..518193c
--- /dev/null
@@ -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;
+}
index a049a9566713e25a1b67bd422b431c9fa0a988bd..6d09b51a6a11e1c0580af99bab22a645e7178b57 100644 (file)
@@ -1,10 +1,10 @@
 // { dg-options "-Wabi -fabi-version=1" }
 
 template <typename Q>
-void f (typename Q::X) {}
+void f (typename Q::X) {} // { dg-warning "mangle" }
 
 struct S {
   typedef int X;
 };
 
-template void f<S> (int); // { dg-warning "mangle" }
+template void f<S> (int);
index 406a13b3f79f44ff6d9588738122f0ac92fc4ac7..a3bd9ff6fa721da19e4f21837f758c14152fa09c 100644 (file)
@@ -1,11 +1,11 @@
 // { dg-options "-Wabi -fabi-version=1" }
 
 template <template <typename> class Q>
-void f (typename Q<int>::X) {}
+void f (typename Q<int>::X) {} // { dg-warning "mangle" }
 
 template <typename Q>
 struct S {
   typedef int X;
 };
 
-template void f<S> (int); // { dg-warning "mangle" }
+template void f<S> (int); 
index 994da88edcaa36c9adbba6c562a9ee380856b0a6..134b976a271519a3a57f6d62f6cbaf90ddafeb1e 100644 (file)
@@ -4,8 +4,8 @@ enum E { e = 3 };
 
 template <int I> struct S {};
 
-template <int I> void f (S<I + e + int (3.7)>) {}
-template void f<7>(S<7 + e + int (3.7)>);  // { dg-warning "mangle" }
+template <int I> void f (S<I + e + int (3.7)>) {} // { dg-warning "mangle" }
+template void f<7>(S<7 + e + int (3.7)>);  
 
-template <int I> void g (S<I + e + int (3.7)>) {}
-template void g<7>(S<7 + e + int (3.7)>); // { dg-warning "mangle" }
+template <int I> void g (S<I + e + int (3.7)>) {} // { dg-warning "mangle" }
+template void g<7>(S<7 + e + int (3.7)>); 
index bf3d189bf0cf9c744e8376f134f5e2310599400f..38ac52371abfc68f5f76284ecadbb89eed374e9d 100644 (file)
@@ -7,10 +7,10 @@
 // PR 9043
 // mangled array types in templates
 
-template <int I> void f(int (*)[2]) {}
+template <int I> void f(int (*)[2]) {} // { dg-warning "mangled name" }
 template <int I> void g(int (*)[I+2]) {}
 
-template void f<1>(int (*)[2]);  // { dg-warning "mangled name" }
+template void f<1>(int (*)[2]);  
 //  { dg-final { scan-assembler "\n_?_Z1fILi1EEvPALi2E_i\[: \t\n\]" } }
 template void g<1>(int (*)[3]);
 //  { dg-final { scan-assembler "\n_?_Z1gILi1EEvPAplT_Li2E_i\[: \t\n\]" } }
diff --git a/gcc/testsuite/g++.dg/opt/interface1-a.cc b/gcc/testsuite/g++.dg/opt/interface1-a.cc
new file mode 100644 (file)
index 0000000..5955852
--- /dev/null
@@ -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 (file)
index 0000000..850fe38
--- /dev/null
@@ -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 (file)
index 0000000..125f4b5
--- /dev/null
@@ -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 (file)
index 0000000..fa9a140
--- /dev/null
@@ -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 (file)
index 0000000..3650247
--- /dev/null
@@ -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 () {}
+
index f9ee4658315524dd39201691e6be6bc8c56ebc5a..e1a7e832a30a934f974955f6348e423e1734be2d 100644 (file)
@@ -1,10 +1,10 @@
-// { dg-options "-Winline -O2 -fno-unit-at-a-time" }
+// { dg-options "-Winline -O2" }
 
-static inline int foo(int x); // { dg-warning "" }
+static inline int foo(int x);
 
 int main()
 {
-  return(foo(17)); // { dg-warning "" }
+  return(foo(17));
 }
 
 inline int foo(int x) {  return(x);  }
index 803d609068f3d51b4500e8c31dfca428481c2447..7080df8267b5f864767fd57c64bea4847d1b0fba 100644 (file)
@@ -119,8 +119,10 @@ proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } {
     if { $do_what == "repo" } {
        set object_file "$output_file"
        set output_file "[file rootname [file tail $prog]].exe"
-       concat comp_output \
-              [$target_compile "$object_file" "$output_file" "executable" $options]
+       set comp_output \
+           [ concat $comp_output \
+                 [$target_compile "$object_file" "$output_file" \
+                      "executable" $options] ]
     }
 
     return [list $comp_output $output_file]
index 6406615b5e3ec8a5d06caa665cf757f4fb365114..2c5da908394ae57041bbeabf156e1c598f661009 100644 (file)
@@ -470,6 +470,12 @@ recompile_files (void)
       obstack_grow (&temporary_obstack, "; ", 2);
       obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
       obstack_1grow (&temporary_obstack, ' ');
+      if (!f->args)
+       {
+         error ("repository file `%s' does not contain command-line "
+                "arguments", f->key);
+         return 0;
+       }
       obstack_grow (&temporary_obstack, f->args, strlen (f->args));
       obstack_1grow (&temporary_obstack, ' ');
       command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
@@ -645,6 +651,9 @@ scan_linker_output (const char *fname)
 
       if (sym && sym->tweaked)
        {
+         error ("`%s' was assigned to `%s', but was not defined "
+                "during recompilation, or vice versa", 
+                sym->key, sym->file->key);
          fclose (stream);
          return 0;
        }