Merge debug-early branch into mainline.
authorAldy Hernandez <aldyh@redhat.com>
Fri, 5 Jun 2015 18:44:53 +0000 (18:44 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Fri, 5 Jun 2015 18:44:53 +0000 (18:44 +0000)
* dwarf2out.c: Remove deferred_locations*.
(dwarf2_debug_hooks): Add early_finish hook.
Remove global_decl hook.
Add early_global_decl and late_global_decl hook.
New global early_dwarf.
New structure set_early_dwarf.
(output_die): Indicate whether a DIE was generated early
when generating assembly with -dA.
(struct limbo_die_struct): Document created_for field.
Remove file_table_last_lookup.
(remove_AT): Return TRUE if successful.
(remove_child_TAG): Clear die_parent.
(reparent_child): New function abstracted from...
(splice_child_die): ...here.
(new_die): ICE if a DIE ends up in limbo too late.
(check_die): New.
(defer_location): Remove.
(add_subscript_info): Reuse DW_TAG_subrange_type if available.
(fill_variable_array_bounds): New.
(decl_start_label): Call fill_variable_array_bounds.
(gen_formal_parameter_die): Rewrite to reuse previously generated
DIEs.
(gen_subprogram_die): Same.
(gen_variable_die): Same.
(gen_const_die): Same.
(gen_label_die): Same.
(gen_lexical_block_die): Same.
(decl_will_get_specification_p): New.
(local_function_static): New.
(gen_struct_or_union_type_die): Fill in variable-length fields.
(gen_typedef_die): Fill in variable-length typedefs.
(gen_tagged_type_die): Gracefully return on error_mark_node.
Handle re-entrancy.
(gen_type_die_with_usage): Handle variable-length types.
Remove duplicate code for ARRAY_TYPE case.
(process_scope_var): Only process imported modules during early
dwarf.
(dwarf2out_early_global_decl): New.
(dwarf2out_late_global_decl): Rename from dwarf2out_global_decl.
(dwarf2out_type_decl): Set early_dwarf while calling
dwarf2out_decl.
(dwarf2out_decl): Verify that we did not recreate a previously
generated DIE.
Do not return on DECL_EXTERNALs in VAR_DECLs.
Abstract some code to local_function_static.
(lookup_filename): Remove use of file_table_last_lookup.
Gracefully exit on missing file_name.
(dwarf2out_finish): Verify limbo list.
Remove deferred_locations_list use.
Move deferred_asm_name and limbo flushing to...
(dwarf2out_early_finish): ...here.  New.
(dwarf2out_c_finalize): Remove set of deferred_location_list,
deferred_asm_name, and file_table_last_lookup.
* cgraph.h (referred_to_p): Add default argument.
* cgraphunit.c (referred_to_p): Add and handle include_self
argument.
(analyze_functions): Add first_time argument.
Call check_global_declaration for all symbols.
Call late_global_decl for nodes for moribund nodes.
(finalize_compilation_unit): Add new argument to
analyze_functions.
Call early_global_decl for functions.
Call early_finish debug hook.
* dbxout.c (dbxout_early_global_decl): New.
(dbxout_late_global_decl): New.  Adapted from dbxout_global_decl.
(dbx_debug_hooks): Add new hooks.
(xcoff_debug_hooks): Same.
* debug.c (do_nothing_debug_hooks): Add early_finish field.
Add early and late debug hooks.
Remove global_decl hook.
* debug.h (struct gcc_debug_hooks): Add early_finish,
early_global_decl, and late_global_decl fields.
Remove global_decl field.
Document gcc_debug_hooks.
* gengtype.c (output_typename): Remove.
* godump.c (go_early_global_decl): New.
(go_late_global_decl): New.
(go_global_decl): Remove.
(dump_go_spec_init): Remove global_decl.  Add
{early,late}_global_decl.
* langhooks-def.h (LANG_HOOKS_WRITE_GLOBALS): Remove.
(LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS): New.
* langhooks.c (lhd_warn_unused_global_decl): Adjust comment.
(write_global_declarations): Remove.
(global_decl_processing): New.
* langhooks.h (struct lang_hooks_for_decls): Remove
final_write_globals field.
Add post_compilation_parsing_cleanups field.
* passes.c (rest_of_decl_compilation): Call early_global_decl.
* sdbout.c: Add early and late_global_decl hooks.  Remove
sdbout_global_decl hook.
Add early_finish field for sdb_debug_hooks.
(sdbout_global_decl): Remove.
(sdbout_early_global_decl): New.
(sdbout_late_global_decl): New.
* timevar.def (TV_PHASE_LATE_PARSING_CLEANUPS): New.
* toplev.c (check_global_declaration): Rename from
check_global_declaration_1.
Adapt to use symtab infrastructure.
(check_global_declarations): Remove.
(emit_debug_global_declarations): Remove.
(compile_file): Remove call to final_write_globals langhook.
Run the actual compilation process.
Perform any post compilation parser cleanups.
Generate late debug info.
* toplev.h (check_global_declaration): New.
(check_global_declaration_1): Remove.
(check_global_declarations): Remove.
(write_global_declarations): Remove.
(emit_debug_global_declarations): Remove.
(global_decl_processing): New.
* tree-core.h (struct tree_block): Add DIE field.
* tree.h (BLOCK_DIE): New.
* vmsdbgout.c (vmsdbgout_global_decl): Remove function and its use
throughout.
(vmsdbgout_early_global_decl): New.
(vmsdbgout_late_global_decl): New.
Add early_finish debug hook field to vmsdbg_debug_hooks.
Remove vmsdbgout_decl to vmsdbgout_function_decl.
Add early and late_global_decl debug hooks.

From-SVN: r224161

70 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/gigi.h
gcc/ada/gcc-interface/misc.c
gcc/ada/gcc-interface/utils.c
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/c-opts.c
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/c/c-objc-common.c
gcc/c/c-objc-common.h
gcc/c/c-tree.h
gcc/cgraph.h
gcc/cgraphunit.c
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-objcp-common.h
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/name-lookup.c
gcc/dbxout.c
gcc/debug.c
gcc/debug.h
gcc/dwarf2out.c
gcc/fortran/ChangeLog
gcc/fortran/f95-lang.c
gcc/fortran/trans-decl.c
gcc/gengtype.c
gcc/go/ChangeLog
gcc/go/go-gcc.cc
gcc/go/go-lang.c
gcc/godump.c
gcc/java/ChangeLog
gcc/java/class.c
gcc/java/decl.c
gcc/java/java-tree.h
gcc/java/jcf-parse.c
gcc/java/lang.c
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h
gcc/lto/ChangeLog
gcc/lto/lto-lang.c
gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/objc/objc-gnu-runtime-abi-01.c
gcc/passes.c
gcc/sdbout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr57101.C
gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
gcc/testsuite/g++.dg/debug/dwarf2/dwarf4-typedef.C
gcc/testsuite/g++.dg/ext/visibility/anon7.C
gcc/testsuite/g++.dg/ipa/pr63587-2.C
gcc/testsuite/g++.dg/lto/pr65549_0.C
gcc/testsuite/g++.dg/opt/dump1.C
gcc/testsuite/g++.dg/opt/pr59622-3.C
gcc/testsuite/g++.dg/opt/pr59622.C
gcc/testsuite/g++.dg/torture/pr46383.C
gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-8.c
gcc/testsuite/gfortran.dg/intent_out_8.f90
gcc/testsuite/gfortran.dg/warn_target_lifetime_3.f90
gcc/timevar.def
gcc/toplev.c
gcc/toplev.h
gcc/tree-switch-conversion.c
gcc/vmsdbgout.c

index cb1339a2886edaada9a43f7d1943cc5f3741c769..69cb8f9d1cc9f493d99adcbee7eed461c0318502 100644 (file)
@@ -1,3 +1,126 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * dwarf2out.c: Remove deferred_locations*.
+       (dwarf2_debug_hooks): Add early_finish hook.
+       Remove global_decl hook.
+       Add early_global_decl and late_global_decl hook.
+       New global early_dwarf.
+       New structure set_early_dwarf.
+       (output_die): Indicate whether a DIE was generated early
+       when generating assembly with -dA.
+       (struct limbo_die_struct): Document created_for field.
+       Remove file_table_last_lookup.
+       (remove_AT): Return TRUE if successful.
+       (remove_child_TAG): Clear die_parent.
+       (reparent_child): New function abstracted from...
+       (splice_child_die): ...here.
+       (new_die): ICE if a DIE ends up in limbo too late.
+       (check_die): New.
+       (defer_location): Remove.
+       (add_subscript_info): Reuse DW_TAG_subrange_type if available.
+       (fill_variable_array_bounds): New.
+       (decl_start_label): Call fill_variable_array_bounds.
+       (gen_formal_parameter_die): Rewrite to reuse previously generated
+       DIEs.
+       (gen_subprogram_die): Same.
+       (gen_variable_die): Same.
+       (gen_const_die): Same.
+       (gen_label_die): Same.
+       (gen_lexical_block_die): Same.
+       (decl_will_get_specification_p): New.
+       (local_function_static): New.
+       (gen_struct_or_union_type_die): Fill in variable-length fields.
+       (gen_typedef_die): Fill in variable-length typedefs.
+       (gen_tagged_type_die): Gracefully return on error_mark_node.
+       Handle re-entrancy.
+       (gen_type_die_with_usage): Handle variable-length types.
+       Remove duplicate code for ARRAY_TYPE case.
+       (process_scope_var): Only process imported modules during early
+       dwarf.
+       (dwarf2out_early_global_decl): New.
+       (dwarf2out_late_global_decl): Rename from dwarf2out_global_decl.
+       (dwarf2out_type_decl): Set early_dwarf while calling
+       dwarf2out_decl.
+       (dwarf2out_decl): Verify that we did not recreate a previously
+       generated DIE.
+       Do not return on DECL_EXTERNALs in VAR_DECLs.
+       Abstract some code to local_function_static.
+       (lookup_filename): Remove use of file_table_last_lookup.
+       Gracefully exit on missing file_name.
+       (dwarf2out_finish): Verify limbo list.
+       Remove deferred_locations_list use.
+       Move deferred_asm_name and limbo flushing to...
+       (dwarf2out_early_finish): ...here.  New.
+       (dwarf2out_c_finalize): Remove set of deferred_location_list,
+       deferred_asm_name, and file_table_last_lookup.
+       * cgraph.h (referred_to_p): Add default argument.
+       * cgraphunit.c (referred_to_p): Add and handle include_self
+       argument.
+       (analyze_functions): Add first_time argument.
+       Call check_global_declaration for all symbols.
+       Call late_global_decl for nodes for moribund nodes.
+       (finalize_compilation_unit): Add new argument to
+       analyze_functions.
+       Call early_global_decl for functions.
+       Call early_finish debug hook.
+       * dbxout.c (dbxout_early_global_decl): New.
+       (dbxout_late_global_decl): New.  Adapted from dbxout_global_decl.
+       (dbx_debug_hooks): Add new hooks.
+       (xcoff_debug_hooks): Same.
+       * debug.c (do_nothing_debug_hooks): Add early_finish field.
+       Add early and late debug hooks.
+       Remove global_decl hook.
+       * debug.h (struct gcc_debug_hooks): Add early_finish,
+       early_global_decl, and late_global_decl fields.
+       Remove global_decl field.
+       Document gcc_debug_hooks.
+       * gengtype.c (output_typename): Remove.
+       * godump.c (go_early_global_decl): New.
+       (go_late_global_decl): New.
+       (go_global_decl): Remove.
+       (dump_go_spec_init): Remove global_decl.  Add
+       {early,late}_global_decl.
+       * langhooks-def.h (LANG_HOOKS_WRITE_GLOBALS): Remove.
+       (LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS): New.
+       * langhooks.c (lhd_warn_unused_global_decl): Adjust comment.
+       (write_global_declarations): Remove.
+       (global_decl_processing): New.
+       * langhooks.h (struct lang_hooks_for_decls): Remove
+       final_write_globals field.
+       Add post_compilation_parsing_cleanups field.
+       * passes.c (rest_of_decl_compilation): Call early_global_decl.
+       * sdbout.c: Add early and late_global_decl hooks.  Remove
+       sdbout_global_decl hook.
+       Add early_finish field for sdb_debug_hooks.
+       (sdbout_global_decl): Remove.
+       (sdbout_early_global_decl): New.
+       (sdbout_late_global_decl): New.
+       * timevar.def (TV_PHASE_LATE_PARSING_CLEANUPS): New.
+       * toplev.c (check_global_declaration): Rename from
+       check_global_declaration_1.
+       Adapt to use symtab infrastructure.
+       (check_global_declarations): Remove.
+       (emit_debug_global_declarations): Remove.
+       (compile_file): Remove call to final_write_globals langhook.
+       Run the actual compilation process.
+       Perform any post compilation parser cleanups.
+       Generate late debug info.
+       * toplev.h (check_global_declaration): New.
+       (check_global_declaration_1): Remove.
+       (check_global_declarations): Remove.
+       (write_global_declarations): Remove.
+       (emit_debug_global_declarations): Remove.
+       (global_decl_processing): New.
+       * tree-core.h (struct tree_block): Add DIE field.
+       * tree.h (BLOCK_DIE): New.
+       * vmsdbgout.c (vmsdbgout_global_decl): Remove function and its use
+       throughout.
+       (vmsdbgout_early_global_decl): New.
+       (vmsdbgout_late_global_decl): New.
+       Add early_finish debug hook field to vmsdbg_debug_hooks.
+       Remove vmsdbgout_decl to vmsdbgout_function_decl.
+       Add early and late_global_decl debug hooks.
+
 2015-06-05  Julian Brown  <julian@codesourcery.com>
            Sandra Loosemore  <sandra@codesourcery.com>
 
index c4c0e0c4e939eb5425ee4417b37282f023508cce..e58d7af9b3ff0c94c9af540dcc0fafee0cca4cd0 100644 (file)
@@ -1,3 +1,17 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * gcc-interface/gigi.h (note_types_used_by_globals): Rename from
+       gnat_write_global_declarations.
+       * gcc-interface/misc.c (gnat_parse_file): Call
+       note_types_used_by_globals.
+       Remove LANG_HOOKS_WRITE_GLOBALS.
+       * gcc-interface/utils.c: Rename global_decls to type_decls.
+       (gnat_write_global_declarations): Rename
+       to note_types_used_by_globals.
+       Remove call to finalize_compilation_unit.
+       Remove debug_hooks->global_decl() call for globals.
+       (gnat_pushdecls): Only insert into type_decls if TYPE_DECL.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * gcc-interface/cuintp.c: Adjust includes for restructured coretypes.h.
index f1ff6fc4f0caf8f4920733e3c099cdf20d5aaa5b..42e2cfb55be782a608767d7aeefc533fec94440f 100644 (file)
@@ -5185,6 +5185,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
       && !Present (Alias (gnat_entity))
       && !(Present (Renamed_Object (gnat_entity)) && saved))
     {
+      /* ?? DECL_ARTIFICIAL, and possibly DECL_IGNORED_P below, should
+        be set before calling rest_of_decl_compilation above (through
+        create_var_decl_1).  This is because rest_of_decl_compilation
+        calls the debugging backend and will create a DIE without
+        DW_AT_artificial.
+
+        This is currently causing gnat.dg/specs/debug1.ads to FAIL.  */
       if (!Comes_From_Source (gnat_entity))
        DECL_ARTIFICIAL (gnu_decl) = 1;
 
index 91d9f9cfb581ae5a35b8f96e6db8e1c6f5c1e71e..b85f3512d40b138233492b51f428ecce57cbf721 100644 (file)
@@ -531,8 +531,9 @@ extern tree gnat_type_for_size (unsigned precision, int unsignedp);
    an unsigned type; otherwise a signed type is returned.  */
 extern tree gnat_type_for_mode (machine_mode mode, int unsignedp);
 
-/* Emit debug info for all global variable declarations.  */
-extern void gnat_write_global_declarations (void);
+/* Keep track of types used at the global level and emit debug info
+   for all global types.  */
+extern void note_types_used_by_globals (void);
 
 /* Return the unsigned version of a TYPE_NODE, a scalar type.  */
 extern tree gnat_unsigned_type (tree type_node);
index 4c2e949b2209cb06995ceded5ccbb8f5135d760d..2eef7df63a7d23fc1407f852706ef427c71b30e1 100644 (file)
@@ -117,6 +117,8 @@ gnat_parse_file (void)
 
   /* Call the front end.  */
   _ada_gnat1drv ();
+
+  note_types_used_by_globals ();
 }
 
 /* Return language mask for option processing.  */
@@ -969,8 +971,6 @@ gnat_init_ts (void)
 #define LANG_HOOKS_GETDECLS            lhd_return_null_tree_v
 #undef  LANG_HOOKS_PUSHDECL
 #define LANG_HOOKS_PUSHDECL            gnat_return_tree
-#undef  LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS       gnat_write_global_declarations
 #undef  LANG_HOOKS_GET_ALIAS_SET
 #define LANG_HOOKS_GET_ALIAS_SET       gnat_get_alias_set
 #undef  LANG_HOOKS_PRINT_DECL
index f3d44e9c6737dc22dffb1ae5a83290b4fea7102e..307a84104844348d0de644cab54068e773a05cdf 100644 (file)
@@ -224,8 +224,8 @@ static GTY((deletable)) struct gnat_binding_level *free_binding_level;
 /* The context to be used for global declarations.  */
 static GTY(()) tree global_context;
 
-/* An array of global declarations.  */
-static GTY(()) vec<tree, va_gc> *global_decls;
+/* An array of global type declarations.  */
+static GTY(()) vec<tree, va_gc> *type_decls;
 
 /* An array of builtin function declarations.  */
 static GTY(()) vec<tree, va_gc> *builtin_decls;
@@ -756,7 +756,10 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
            vec_safe_push (builtin_decls, decl);
        }
       else if (global_bindings_p ())
-       vec_safe_push (global_decls, decl);
+       {
+         if (TREE_CODE (decl) == TYPE_DECL)
+           vec_safe_push (type_decls, decl);
+       }
       else
        {
          DECL_CHAIN (decl) = BLOCK_VARS (current_binding_level->block);
@@ -5183,8 +5186,11 @@ smaller_form_type_p (tree type, tree orig_type)
 
 static GTY (()) tree dummy_global;
 
+/* Keep track of types used at the global level and emit debug info
+   for all global types.  */
+
 void
-gnat_write_global_declarations (void)
+note_types_used_by_globals (void)
 {
   unsigned int i;
   tree iter;
@@ -5214,26 +5220,12 @@ gnat_write_global_declarations (void)
     }
 
   /* Output debug information for all global type declarations first.  This
-     ensures that global types whose compilation hasn't been finalized yet,
+     ensures that global types whose compilation haven't been finalized yet,
      for example pointers to Taft amendment types, have their compilation
      finalized in the right context.  */
-  FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter)
-    if (TREE_CODE (iter) == TYPE_DECL && !DECL_IGNORED_P (iter))
+  FOR_EACH_VEC_SAFE_ELT (type_decls, i, iter)
+    if (!DECL_IGNORED_P (iter))
       debug_hooks->type_decl (iter, false);
-
-  /* Proceed to optimize and emit assembly. */
-  symtab->finalize_compilation_unit ();
-
-  /* After cgraph has had a chance to emit everything that's going to
-     be emitted, output debug information for the rest of globals.  */
-  if (!seen_error ())
-    {
-      timevar_push (TV_SYMOUT);
-      FOR_EACH_VEC_SAFE_ELT (global_decls, i, iter)
-       if (TREE_CODE (iter) != TYPE_DECL && !DECL_IGNORED_P (iter))
-         debug_hooks->global_decl (iter);
-      timevar_pop (TV_SYMOUT);
-    }
 }
 
 /* ************************************************************************
index 702eb48c30ce98f2ead1811ec2fca76f33e46526..6de6af54e07aa4886ad12c5e6ec67b6c60d4ba34 100644 (file)
@@ -1,3 +1,8 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * c-common.h (c_parse_final_cleanups): New prototype.
+       * c-opts.c (c_common_parse_file): Call c_parse_final_cleanups.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * array-notation-common.c: Adjust includes for restructured coretypes.h.
index eaab97faf9fa40682e1672fb7b106556c004546f..af86e2687758fd870ddc3d35d70b336918f1fa49 100644 (file)
@@ -887,6 +887,8 @@ extern HOST_WIDE_INT c_common_to_target_charset (HOST_WIDE_INT);
 /* This is the basic parsing function.  */
 extern void c_parse_file (void);
 
+extern void c_parse_final_cleanups (void);
+
 extern void warn_for_omitted_condop (location_t, tree);
 
 /* These macros provide convenient access to the various _STMT nodes.  */
index 8f8e22b98641f942d4f57dd5195cf79e662e3065..971f5ebdd6af9a3b4cd358ea24fa8b16460b4316 100644 (file)
@@ -1087,6 +1087,8 @@ c_common_parse_file (void)
       if (!this_input_filename)
        break;
     }
+
+  c_parse_final_cleanups ();
 }
 
 /* Returns the appropriate dump file for PHASE to dump with FLAGS.  */
index b933e5bc00342288cffff738f64f80d11dde5830..d37a3ab09f1e160338be95323b0f38dd9e798cea 100644 (file)
@@ -1,3 +1,17 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * c-decl.c (finish_struct): Save C_TYPE_INCOMPLETE_VARS and
+       immediately clobber it.
+       (c_write_global_declarations_1): Remove call to
+       check_global_declaration_1.
+       (c_write_global_declarations_2): Remove.
+       (c_write_final_cleanups): Rename from c_write_global_declarations.
+       Remove call to finalize_compilation_unit.
+       Remove calls to debugging hooks.
+       * c-objc-common.c: Adjust comment for c_warn_unused_global_decl.
+       * c-objc-common.h: Remove LANG_HOOKS_WRITE_GLOBALS.
+       * c-tree.h: Remove c_write_global_declarations.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * c-array-notation.c: Adjust includes for restructured coretypes.h.
index 8a0be2857a63e44438a9cb6d8d53384fe931d32b..77d1de9adbb073e37bc16b71f723f614c74b9408 100644 (file)
@@ -7837,10 +7837,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
     }
 
   /* If this structure or union completes the type of any previous
-     variable declaration, lay it out and output its rtl.  */
-  for (x = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
-       x;
-       x = TREE_CHAIN (x))
+     variable declaration, lay it out and output its rtl.
+
+     Note: C_TYPE_INCOMPLETE_VARS overloads TYPE_VFIELD which is used
+     in dwarf2out via rest_of_decl_compilation below and means
+     something totally different.  Since we will be clearing
+     C_TYPE_INCOMPLETE_VARS shortly after we iterate through them,
+     clear it ahead of time and avoid problems in dwarf2out.  Ideally,
+     C_TYPE_INCOMPLETE_VARS should use some language specific
+     node.  */
+  tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
+  C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
+  for (x = incomplete_vars; x; x = TREE_CHAIN (x))
     {
       tree decl = TREE_VALUE (x);
       if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
@@ -7853,7 +7861,6 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
          rest_of_decl_compilation (decl, toplevel, 0);
        }
     }
-  C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
 
   /* Update type location to the one of the definition, instead of e.g.
      a forward declaration.  */
@@ -10679,9 +10686,8 @@ finish_declspecs (struct c_declspecs *specs)
   return specs;
 }
 
-/* A subroutine of c_write_global_declarations.  Perform final processing
-   on one file scope's declarations (or the external scope's declarations),
-   GLOBALS.  */
+/* Perform final processing on one file scope's declarations (or the
+   external scope's declarations), GLOBALS.  */
 
 static void
 c_write_global_declarations_1 (tree globals)
@@ -10694,7 +10700,7 @@ c_write_global_declarations_1 (tree globals)
     {
       /* Check for used but undefined static functions using the C
         standard's definition of "used", and set TREE_NO_WARNING so
-        that check_global_declarations doesn't repeat the check.  */
+        that check_global_declaration doesn't repeat the check.  */
       if (TREE_CODE (decl) == FUNCTION_DECL
          && DECL_INITIAL (decl) == 0
          && DECL_EXTERNAL (decl)
@@ -10715,21 +10721,6 @@ c_write_global_declarations_1 (tree globals)
        reconsider |= wrapup_global_declaration_2 (decl);
     }
   while (reconsider);
-
-  for (decl = globals; decl; decl = DECL_CHAIN (decl))
-    check_global_declaration_1 (decl);
-}
-
-/* A subroutine of c_write_global_declarations Emit debug information for each
-   of the declarations in GLOBALS.  */
-
-static void
-c_write_global_declarations_2 (tree globals)
-{
-  tree decl;
-
-  for (decl = globals; decl ; decl = DECL_CHAIN (decl))
-    debug_hooks->global_decl (decl);
 }
 
 /* Callback to collect a source_ref from a DECL.  */
@@ -10779,8 +10770,11 @@ for_each_global_decl (void (*callback) (tree decl))
     callback (decl);
 }
 
+/* Perform any final parser cleanups and generate initial debugging
+   information.  */
+
 void
-c_write_global_declarations (void)
+c_parse_final_cleanups (void)
 {
   tree t;
   unsigned i;
@@ -10789,6 +10783,7 @@ c_write_global_declarations (void)
   if (pch_file)
     return;
 
+  timevar_stop (TV_PHASE_PARSING);
   timevar_start (TV_PHASE_DEFERRED);
 
   /* Do the Objective-C stuff.  This is where all the Objective-C
@@ -10827,34 +10822,15 @@ c_write_global_declarations (void)
     }
 
   /* Process all file scopes in this compilation, and the external_scope,
-     through wrapup_global_declarations and check_global_declarations.  */
+     through wrapup_global_declarations.  */
   FOR_EACH_VEC_ELT (*all_translation_units, i, t)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
   timevar_stop (TV_PHASE_DEFERRED);
-  timevar_start (TV_PHASE_OPT_GEN);
-
-  /* We're done parsing; proceed to optimize and emit assembly.
-     FIXME: shouldn't be the front end's responsibility to call this.  */
-  symtab->finalize_compilation_unit ();
-
-  timevar_stop (TV_PHASE_OPT_GEN);
-  timevar_start (TV_PHASE_DBGINFO);
-
-  /* After cgraph has had a chance to emit everything that's going to
-     be emitted, output debug information for globals.  */
-  if (!seen_error ())
-    {
-      timevar_push (TV_SYMOUT);
-      FOR_EACH_VEC_ELT (*all_translation_units, i, t)
-       c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
-      c_write_global_declarations_2 (BLOCK_VARS (ext_block));
-      timevar_pop (TV_SYMOUT);
-    }
+  timevar_start (TV_PHASE_PARSING);
 
   ext_block = NULL;
-  timevar_stop (TV_PHASE_DBGINFO);
 }
 
 /* Register reserved keyword WORD as qualifier for address space AS.  */
index d77e9c23d6eabfc52e834852c77d3d70d6fde5b3..68ba65f2e0374598a76d6dee94192d68061f089f 100644 (file)
@@ -49,7 +49,7 @@ c_missing_noreturn_ok_p (tree decl)
   return flag_hosted && MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
 }
 
-/* Called from check_global_declarations.  */
+/* Called from check_global_declaration.  */
 
 bool
 c_warn_unused_global_decl (const_tree decl)
index 84243c8dd7d0d193a275957413fe73b1e1e42ad8..50c9f54998c44f725d527eb3e7f479de2ca0b71f 100644 (file)
@@ -92,8 +92,6 @@ along with GCC; see the file COPYING3.  If not see
 
 #undef LANG_HOOKS_GETDECLS
 #define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
 
 /* Hooks for tree gimplification.  */
 #undef LANG_HOOKS_GIMPLIFY_EXPR
index 7a7266500b1782d63462c276579c35bf90bfd8fb..28b58c636e46cefef9f5b430149b02d8ee88ce22 100644 (file)
@@ -695,7 +695,6 @@ typedef void c_binding_oracle_function (enum c_oracle_request, tree identifier);
 extern c_binding_oracle_function *c_binding_oracle;
 
 extern void c_finish_incomplete_decl (tree);
-extern void c_write_global_declarations (void);
 extern tree c_omp_reduction_id (enum tree_code, tree);
 extern tree c_omp_reduction_decl (tree);
 extern tree c_omp_reduction_lookup (tree, tree);
index 108cc801c6eb05ffccf3b1e938d7ec79e4b4f03b..55864a279485e23c0c6d3f9bb1e647b77b97c63d 100644 (file)
@@ -314,7 +314,7 @@ public:
   bool needed_p (void);
 
   /* Return true when there are references to the node.  */
-  bool referred_to_p (void);
+  bool referred_to_p (bool include_self = true);
 
   /* Return true if NODE can be discarded by linker from the binary.  */
   inline bool
index 29b653d1e111dff877afea14766433758ec194f5..722c4f4d0634d1c18ebd2de91f89d6c9ac61e0d1 100644 (file)
@@ -403,10 +403,11 @@ cgraph_node::reset (void)
   remove_all_references ();
 }
 
-/* Return true when there are references to the node.  */
+/* Return true when there are references to the node.  INCLUDE_SELF is
+   true if a self reference counts as a reference.  */
 
 bool
-symtab_node::referred_to_p (void)
+symtab_node::referred_to_p (bool include_self)
 {
   ipa_ref *ref = NULL;
 
@@ -416,7 +417,13 @@ symtab_node::referred_to_p (void)
   /* For functions check also calls.  */
   cgraph_node *cn = dyn_cast <cgraph_node *> (this);
   if (cn && cn->callers)
-    return true;
+    {
+      if (include_self)
+       return true;
+      for (cgraph_edge *e = cn->callers; e; e = e->next_caller)
+       if (e->caller != this)
+         return true;
+    }
   return false;
 }
 
@@ -924,8 +931,12 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
 static cgraph_node *first_analyzed;
 static varpool_node *first_analyzed_var;
 
+/* FIRST_TIME is set to TRUE for the first time we are called for a
+   translation unit from finalize_compilation_unit() or false
+   otherwise.  */
+
 static void
-analyze_functions (void)
+analyze_functions (bool first_time)
 {
   /* Keep track of already processed nodes when called multiple times for
      intermodule optimization.  */
@@ -1097,6 +1108,13 @@ analyze_functions (void)
       symtab_node::dump_table (symtab->dump_file);
     }
 
+  if (first_time)
+    {
+      symtab_node *snode;
+      FOR_EACH_SYMBOL (snode)
+       check_global_declaration (snode->decl);
+    }
+
   if (symtab->dump_file)
     fprintf (symtab->dump_file, "\nRemoving unused symbols:");
 
@@ -1109,6 +1127,19 @@ analyze_functions (void)
        {
          if (symtab->dump_file)
            fprintf (symtab->dump_file, " %s", node->name ());
+
+         /* See if the debugger can use anything before the DECL
+            passes away.  Perhaps it can notice a DECL that is now a
+            constant and can tag the early DIE with an appropriate
+            attribute.
+
+            Otherwise, this is the last chance the debug_hooks have
+            at looking at optimized away DECLs, since
+            late_global_decl will subsequently be called from the
+            contents of the now pruned symbol table.  */
+         if (!decl_function_context (node->decl))
+           (*debug_hooks->late_global_decl) (node->decl);
+
          node->remove ();
          continue;
        }
@@ -2445,13 +2476,23 @@ symbol_table::finalize_compilation_unit (void)
 
   /* Gimplify and lower all functions, compute reachability and
      remove unreachable nodes.  */
-  analyze_functions ();
+  analyze_functions (/*first_time=*/true);
 
   /* Mark alias targets necessary and emit diagnostics.  */
   handle_alias_pairs ();
 
   /* Gimplify and lower thunks.  */
-  analyze_functions ();
+  analyze_functions (/*first_time=*/false);
+
+  /* Emit early debug for reachable functions, and by consequence,
+     locally scoped symbols.  */
+  struct cgraph_node *cnode;
+  FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode)
+    (*debug_hooks->early_global_decl) (cnode->decl);
+
+  /* Clean up anything that needs cleaning up after initial debug
+     generation.  */
+  (*debug_hooks->early_finish) ();
 
   /* Finally drive the pass manager.  */
   compile ();
index e845b9f17ce4170c3e6617c253591dab680699a8..bb59bcc70fc43dc6a20380d6548f673251321c40 100644 (file)
@@ -1,3 +1,36 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * cp-objcp-common.c: Adjust comment for
+       cxx_warn_unused_global_decl.
+       * cp-objcp-common.h (LANG_HOOKS_WRITE_GLOBALS): Remove
+       (LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS): New.
+       * cp-tree.h (note_mangling_alias): Protoize.
+       (cp_write_global_declarations): Remove.
+       (cxx_post_compilation_parsing_cleanups): Protoize.
+       * decl.c (wrapup_globals_for_namespace): Remove use of DATA
+       argument.
+       * decl2.c (mangling_aliases): New global.
+       (build_java_method_aliases): New.  Adapted from
+       collect_candidates_for_java_method_aliases.
+       (collect_candidates_for_java_method_aliases): Remove.
+       (build_java_method_aliases): Remove.
+       (generate_mangling_aliases): New.
+       (note_mangling_alias): New.  Moved from mangle_decl.
+       (locus_at_end_of_parsing): New global.
+       (c_parse_final_cleanups): Rename from
+       cp_write_global_declarations.
+       Use locus_at_end_of_parsing.
+       Call generate_mangling_aliases.
+       Rename call to collect_candidates_for_java_method_aliases into
+       build_java_method_aliases.
+       Remove call to finalize_compilation_unit.
+       Move vtable handling into cxx_post_compilation_parsing_cleanups.
+       Do not call check_global_declarations or
+       emit_debug_global_declarations.
+       (cxx_post_compilation_parsing_cleanups): New.
+       * mangle.c (mangle_decl): Move code to note_mangling_alias.
+       * name-lookup.c (do_namespace_alias): Call early_global_decl.
+
 2015-06-05  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/52595
index 8f40ce402063db99b566b57faee2337196ccb0dd..4c193a1dfd2d6dc52093269f772f9d3829b96063 100644 (file)
@@ -57,7 +57,7 @@ cxx_get_alias_set (tree t)
   return c_common_get_alias_set (t);
 }
 
-/* Called from check_global_declarations.  */
+/* Called from check_global_declaration.  */
 
 bool
 cxx_warn_unused_global_decl (const_tree decl)
index 8a36e7f28fc9c40b9aab49751b67bc1ec0b1d6db..c8572a7f4713ec46eb2b9155503681f063fc60f8 100644 (file)
@@ -84,8 +84,8 @@ extern void cp_common_init_ts (void);
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION        cxx_print_error_function
 #undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS cp_write_global_declarations
+#undef LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS
+#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS cxx_post_compilation_parsing_cleanups
 #undef  LANG_HOOKS_BUILTIN_FUNCTION
 #define LANG_HOOKS_BUILTIN_FUNCTION cxx_builtin_function
 #undef  LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
index 26b6cb667dc4875d1a19ef826d1500261e7c70ad..fb1702cb1502dad64044d9db91bd4d8300ef3972 100644 (file)
@@ -5469,7 +5469,7 @@ extern tree cp_reconstruct_complex_type           (tree, tree);
 extern bool attributes_naming_typedef_ok       (tree);
 extern void cplus_decl_attributes              (tree *, tree, int);
 extern void finish_anon_union                  (tree);
-extern void cp_write_global_declarations       (void);
+extern void cxx_post_compilation_parsing_cleanups (void);
 extern tree coerce_new_type                    (tree);
 extern tree coerce_delete_type                 (tree);
 extern void comdat_linkage                     (tree);
index e63098f07677e066c8398dafd8ad5119cd98f2e0..2bddce22d62f2b44b826e4d65f872b705edaeec6 100644 (file)
@@ -888,30 +888,19 @@ walk_namespaces (walk_namespaces_fn f, void* data)
   return walk_namespaces_r (global_namespace, f, data);
 }
 
-/* Call wrapup_globals_declarations for the globals in NAMESPACE.  If
-   DATA is non-NULL, this is the last time we will call
-   wrapup_global_declarations for this NAMESPACE.  */
+/* Call wrapup_globals_declarations for the globals in NAMESPACE.  */
 
 int
-wrapup_globals_for_namespace (tree name_space, void* data)
+wrapup_globals_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
 {
   cp_binding_level *level = NAMESPACE_LEVEL (name_space);
   vec<tree, va_gc> *statics = level->static_decls;
   tree *vec = statics->address ();
   int len = statics->length ();
-  int last_time = (data != 0);
-
-  if (last_time)
-    {
-      check_global_declarations (vec, len);
-      emit_debug_global_declarations (vec, len);
-      return 0;
-    }
 
   /* Write out any globals that need to be output.  */
   return wrapup_global_declarations (vec, len);
 }
-
 \f
 /* In C++, you don't have to write `struct S' to refer to `S'; you
    can just use `S'.  We accomplish this by creating a TYPE_DECL as
index a6a628da2d41739e663ed7bb9becea3516238bd0..c1b568b2c6478380ac790b992fa762d5e77da48e 100644 (file)
@@ -4389,6 +4389,8 @@ dump_tu (void)
     }
 }
 
+static location_t locus_at_end_of_parsing;
+
 /* Check the deallocation functions for CODE to see if we want to warn that
    only one was defined.  */
 
@@ -4436,17 +4438,16 @@ maybe_warn_sized_delete ()
    first, since that way we only need to reverse the decls once.  */
 
 void
-cp_write_global_declarations (void)
+c_parse_final_cleanups (void)
 {
   tree vars;
   bool reconsider;
   size_t i;
-  location_t locus;
   unsigned ssdf_count = 0;
   int retries = 0;
   tree decl;
 
-  locus = input_location;
+  locus_at_end_of_parsing = input_location;
   at_eof = 1;
 
   /* Bad parse errors.  Just forget about it.  */
@@ -4463,6 +4464,9 @@ cp_write_global_declarations (void)
       return;
     }
 
+  timevar_stop (TV_PHASE_PARSING);
+  timevar_start (TV_PHASE_DEFERRED);
+
   symtab->process_same_body_aliases ();
 
   /* Handle -fdump-ada-spec[-slim] */
@@ -4478,8 +4482,6 @@ cp_write_global_declarations (void)
 
   /* FIXME - huh?  was  input_line -= 1;*/
 
-  timevar_start (TV_PHASE_DEFERRED);
-
   /* We now have to write out all the stuff we put off writing out.
      These include:
 
@@ -4575,7 +4577,7 @@ cp_write_global_declarations (void)
 
          /* Set the line and file, so that it is obviously not from
             the source file.  */
-         input_location = locus;
+         input_location = locus_at_end_of_parsing;
          ssdf_body = start_static_storage_duration_function (ssdf_count);
 
          /* Make sure the back end knows about all the variables.  */
@@ -4601,7 +4603,7 @@ cp_write_global_declarations (void)
 
          /* Finish up the static storage duration function for this
             round.  */
-         input_location = locus;
+         input_location = locus_at_end_of_parsing;
          finish_static_storage_duration_function (ssdf_body);
 
          /* All those initializations and finalizations might cause
@@ -4609,7 +4611,7 @@ cp_write_global_declarations (void)
             instantiations, etc.  */
          reconsider = true;
          ssdf_count++;
-         /* ??? was:  locus.line++; */
+         /* ??? was:  locus_at_end_of_parsing.line++; */
        }
 
       /* Now do the same for thread_local variables.  */
@@ -4752,7 +4754,7 @@ cp_write_global_declarations (void)
                                (template_for_substitution (decl)))))
        {
          warning (0, "inline function %q+D used but never defined", decl);
-         /* Avoid a duplicate warning from check_global_declaration_1.  */
+         /* Avoid a duplicate warning from check_global_declaration.  */
          TREE_NO_WARNING (decl) = 1;
        }
     }
@@ -4779,12 +4781,13 @@ cp_write_global_declarations (void)
   if (priority_info_map)
     splay_tree_foreach (priority_info_map,
                        generate_ctor_and_dtor_functions_for_priority,
-                       /*data=*/&locus);
+                       /*data=*/&locus_at_end_of_parsing);
   else if (c_dialect_objc () && objc_static_init_needed_p ())
     /* If this is obj-c++ and we need a static init, call
        generate_ctor_or_dtor_function.  */
     generate_ctor_or_dtor_function (/*constructor_p=*/true,
-                                   DEFAULT_INIT_PRIORITY, &locus);
+                                   DEFAULT_INIT_PRIORITY,
+                                   &locus_at_end_of_parsing);
 
   /* We're done with the splay-tree now.  */
   if (priority_info_map)
@@ -4800,9 +4803,6 @@ cp_write_global_declarations (void)
   /* Generate Java hidden aliases.  */
   build_java_method_aliases ();
 
-  timevar_stop (TV_PHASE_DEFERRED);
-  timevar_start (TV_PHASE_OPT_GEN);
-
   if (flag_vtable_verify)
     {
       vtv_recover_class_info ();
@@ -4810,32 +4810,6 @@ cp_write_global_declarations (void)
       vtv_build_vtable_verify_fndecl ();
     }
 
-  symtab->finalize_compilation_unit ();
-
-  if (flag_vtable_verify)
-    {
-      /* Generate the special constructor initialization function that
-         calls __VLTRegisterPairs, and give it a very high
-         initialization priority.  This must be done after
-         finalize_compilation_unit so that we have accurate
-         information about which vtable will actually be emitted.  */
-      vtv_generate_init_routine ();
-    }
-
-  timevar_stop (TV_PHASE_OPT_GEN);
-  timevar_start (TV_PHASE_CHECK_DBGINFO);
-
-  /* Now, issue warnings about static, but not defined, functions,
-     etc., and emit debugging information.  */
-  walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
-  if (vec_safe_length (pending_statics) != 0)
-    {
-      check_global_declarations (pending_statics->address (),
-                                pending_statics->length ());
-      emit_debug_global_declarations (pending_statics->address (),
-                                     pending_statics->length ());
-    }
-
   perform_deferred_noexcept_checks ();
 
   finish_repo ();
@@ -4849,13 +4823,37 @@ cp_write_global_declarations (void)
       dump_tree_statistics ();
       dump_time_statistics ();
     }
-  input_location = locus;
+
+  timevar_stop (TV_PHASE_DEFERRED);
+  timevar_start (TV_PHASE_PARSING);
+}
+
+/* Perform any post compilation-proper cleanups for the C++ front-end.
+   This should really go away.  No front-end should need to do
+   anything past the compilation process.  */
+
+void
+cxx_post_compilation_parsing_cleanups (void)
+{
+  timevar_start (TV_PHASE_LATE_PARSING_CLEANUPS);
+
+  if (flag_vtable_verify)
+    {
+      /* Generate the special constructor initialization function that
+         calls __VLTRegisterPairs, and give it a very high
+         initialization priority.  This must be done after
+         finalize_compilation_unit so that we have accurate
+         information about which vtable will actually be emitted.  */
+      vtv_generate_init_routine ();
+    }
+
+  input_location = locus_at_end_of_parsing;
 
 #ifdef ENABLE_CHECKING
   validate_conversion_obstack ();
 #endif /* ENABLE_CHECKING */
 
-  timevar_stop (TV_PHASE_CHECK_DBGINFO);
+  timevar_stop (TV_PHASE_LATE_PARSING_CLEANUPS);
 }
 
 /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
index 62424e0b523ffe951db0bc05cb10d37e603e0be2..e4baac3b959f10d2cb76866c9dc73cc9c9477ed5 100644 (file)
@@ -3896,7 +3896,7 @@ do_namespace_alias (tree alias, tree name_space)
 
   /* Emit debug info for namespace alias.  */
   if (!building_stmt_list_p ())
-    (*debug_hooks->global_decl) (alias);
+    (*debug_hooks->early_global_decl) (alias);
 }
 
 /* Like pushdecl, only it places X in the current namespace,
index c873e85b6d17524199d7127524d30c29c0e6ab0f..138f5cfdf0e44d8aeb077d25a431ad6bae2675fe 100644 (file)
@@ -345,7 +345,8 @@ static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
 static void dbxout_common_name (tree, const char *, stab_code_type);
 static const char *dbxout_common_check (tree, int *);
-static void dbxout_global_decl (tree);
+static void dbxout_early_global_decl (tree);
+static void dbxout_late_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 static void debug_free_queue (void);
@@ -367,6 +368,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_init,
   dbxout_finish,
   debug_nothing_void,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   dbxout_start_source_file,
@@ -386,7 +388,8 @@ const struct gcc_debug_hooks dbx_debug_hooks =
 #endif
   debug_nothing_int,                    /* end_function */
   dbxout_function_decl,
-  dbxout_global_decl,                   /* global_decl */
+  dbxout_early_global_decl,             /* early_global_decl */
+  dbxout_late_global_decl,              /* late_global_decl */
   dbxout_type_decl,                     /* type_decl */
   debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
   debug_nothing_tree,                   /* deferred_inline_function */
@@ -407,6 +410,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   dbxout_init,
   dbxout_finish,
   debug_nothing_void,
+  debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
   dbxout_start_source_file,
@@ -422,7 +426,8 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   debug_nothing_tree,                   /* begin_function */
   xcoffout_end_function,
   debug_nothing_tree,                   /* function_decl */
-  dbxout_global_decl,                   /* global_decl */
+  dbxout_early_global_decl,             /* early_global_decl */
+  dbxout_late_global_decl,              /* late_global_decl */
   dbxout_type_decl,                     /* type_decl */
   debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
   debug_nothing_tree,                   /* deferred_inline_function */
@@ -1336,10 +1341,16 @@ dbxout_function_decl (tree decl)
 
 #endif /* DBX_DEBUGGING_INFO  */
 
+static void
+dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+{
+  /* NYI for non-dwarf.  */
+}
+
 /* Debug information for a global DECL.  Called from toplev.c after
    compilation proper has finished.  */
 static void
-dbxout_global_decl (tree decl)
+dbxout_late_global_decl (tree decl)
 {
   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
     {
index 121f3da9d1f41ce01f1269f271c9cc884349469a..ed468f7077949d322b5c345f0e295f9f1e623144 100644 (file)
@@ -33,6 +33,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
 {
   debug_nothing_charstar,
   debug_nothing_charstar,
+  debug_nothing_void,                  /* early_finish */
   debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
@@ -49,7 +50,8 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
   debug_nothing_tree,                   /* begin_function */
   debug_nothing_int,                    /* end_function */
   debug_nothing_tree,                   /* function_decl */
-  debug_nothing_tree,                   /* global_decl */
+  debug_nothing_tree,                   /* early_global_decl */
+  debug_nothing_tree,                   /* late_global_decl */
   debug_nothing_tree_int,               /* type_decl */
   debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
   debug_nothing_tree,                   /* deferred_inline_function */
index 276c887f62c9b376b5bc37ccb3605f1b707e13dc..e7e1334c1549b74344f8e98d729bdd6875b1c2bd 100644 (file)
@@ -30,6 +30,9 @@ struct gcc_debug_hooks
   /* Output debug symbols.  */
   void (* finish) (const char *main_filename);
 
+  /* Run cleanups necessary after early debug generation.  */
+  void (* early_finish) (void);
+
   /* Called from cgraph_optimize before starting to assemble
      functions/variables/toplevel asms.  */
   void (* assembly_start) (void);
@@ -89,12 +92,43 @@ struct gcc_debug_hooks
   /* Debug information for a function DECL.  This might include the
      function name (a symbol), its parameters, and the block that
      makes up the function's body, and the local variables of the
-     function.  */
+     function.
+
+     This is only called for FUNCTION_DECLs.  It is part of the late
+     debug pass and is called from rest_of_handle_final.
+
+     Location information is available at this point.
+
+     See the documentation for early_global_decl and late_global_decl
+     for other entry points into the debugging back-ends for DECLs.  */
   void (* function_decl) (tree decl);
 
-  /* Debug information for a global DECL.  Called from toplev.c after
-     compilation proper has finished.  */
-  void (* global_decl) (tree decl);
+  /* Debug information for a global DECL.  Called from the parser
+     after the parsing process has finished.
+
+     This gets called for both variables and functions.
+
+     Location information is not available at this point, but it is a
+     good probe point to get access to symbols before they get
+     optimized away.
+
+     This hook may be called on VAR_DECLs or FUNCTION_DECLs.  It is up
+     to the hook to use what it needs.  */
+  void (* early_global_decl) (tree decl);
+
+  /* Augment debug information generated by early_global_decl with
+     more complete debug info (if applicable).  Called from toplev.c
+     after the compilation proper has finished and cgraph information
+     is available.
+
+     This gets called for both variables and functions.
+
+     Location information is usually available at this point, unless
+     the hook is being called for a decl that has been optimized away.
+
+     This hook may be called on VAR_DECLs or FUNCTION_DECLs.  It is up
+     to the hook to use what it needs.  */
+  void (* late_global_decl) (tree decl);
 
   /* Debug information for a type DECL.  Called from toplev.c after
      compilation proper, also from various language front ends to
index 55364a266327b0fb4de091c493861c019687c6a3..2e3bee34abfc671feedb3a7fa16bda8669cb3c70 100644 (file)
@@ -1263,16 +1263,6 @@ struct GTY((for_user)) dwarf_file_data {
   int emitted_number;
 };
 
-typedef struct GTY(()) deferred_locations_struct
-{
-  tree variable;
-  dw_die_ref die;
-} deferred_locations;
-
-
-static GTY(()) vec<deferred_locations, va_gc> *deferred_locations_list;
-
-
 /* Describe an entry into the .debug_addr section.  */
 
 enum ate_kind {
@@ -2443,6 +2433,7 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
 
 static void dwarf2out_init (const char *);
 static void dwarf2out_finish (const char *);
+static void dwarf2out_early_finish (void);
 static void dwarf2out_assembly_start (void);
 static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
@@ -2452,7 +2443,8 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree);
+static void dwarf2out_early_global_decl (tree);
+static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
@@ -2469,6 +2461,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
+  dwarf2out_early_finish,
   dwarf2out_assembly_start,
   dwarf2out_define,
   dwarf2out_undef,
@@ -2490,7 +2483,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_begin_function,
   dwarf2out_end_function,      /* end_function */
   dwarf2out_function_decl,     /* function_decl */
-  dwarf2out_global_decl,
+  dwarf2out_early_global_decl,
+  dwarf2out_late_global_decl,
   dwarf2out_type_decl,         /* type_decl */
   dwarf2out_imported_module_or_decl,
   debug_nothing_tree,          /* deferred_inline_function */
@@ -2635,6 +2629,14 @@ typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct {
 }
 die_node;
 
+/* Set to TRUE while dwarf2out_early_global_decl is running.  */
+static bool early_dwarf;
+struct set_early_dwarf {
+  bool saved;
+  set_early_dwarf () : saved(early_dwarf) { early_dwarf = true; }
+  ~set_early_dwarf () { early_dwarf = saved; }
+};
+
 /* Evaluate 'expr' while 'c' is set to each child of DIE in order.  */
 #define FOR_EACH_CHILD(die, c, expr) do {      \
   c = die->die_child;                          \
@@ -2685,9 +2687,13 @@ typedef struct GTY(()) comdat_type_struct
 }
 comdat_type_node;
 
-/* The limbo die list structure.  */
+/* A list of DIEs for which we can't determine ancestry (parent_die
+   field) just yet.  Later in dwarf2out_finish we will fill in the
+   missing bits.  */
 typedef struct GTY(()) limbo_die_struct {
   dw_die_ref die;
+  /* The tree for which this DIE was created.  We use this to
+     determine ancestry later.  */
   tree created_for;
   struct limbo_die_struct *next;
 }
@@ -2934,7 +2940,7 @@ static GTY((length ("abbrev_die_table_allocated")))
 /* Number of elements currently allocated for abbrev_die_table.  */
 static GTY(()) unsigned abbrev_die_table_allocated;
 
-/* Number of elements in type_die_table currently in use.  */
+/* Number of elements in abbrev_die_table currently in use.  */
 static GTY(()) unsigned abbrev_die_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
@@ -3016,9 +3022,6 @@ static GTY(()) struct dwarf_file_data * last_emitted_file;
 /* Number of internal labels generated by gen_internal_sym().  */
 static GTY(()) int label_num;
 
-/* Cached result of previous call to lookup_filename.  */
-static GTY(()) struct dwarf_file_data * file_table_last_lookup;
-
 static GTY(()) vec<die_arg_entry, va_gc> *tmpl_value_parm_die_table;
 
 /* Instances of generic types for which we need to generate debug
@@ -3103,7 +3106,7 @@ static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
 static bool is_cxx (void);
 static bool is_fortran (void);
 static bool is_ada (void);
-static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static bool remove_AT (dw_die_ref, enum dwarf_attribute);
 static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
 static void add_child_die (dw_die_ref, dw_die_ref);
 static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
@@ -4743,16 +4746,17 @@ is_ada (void)
   return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
 }
 
-/* Remove the specified attribute if present.  */
+/* Remove the specified attribute if present.  Return TRUE if removal
+   was successful.  */
 
-static void
+static bool
 remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a;
   unsigned ix;
 
   if (! die)
-    return;
+    return false;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
@@ -4764,8 +4768,9 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
        /* vec::ordered_remove should help reduce the number of abbrevs
           that are needed.  */
        die->die_attr->ordered_remove (ix);
-       return;
+       return true;
       }
+  return false;
 }
 
 /* Remove CHILD from its parent.  PREV must have the property that
@@ -4839,6 +4844,7 @@ remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
     while (c->die_tag == tag)
       {
        remove_child_with_prev (c, prev);
+       c->die_parent = NULL;
        /* Might have removed every child.  */
        if (c == c->die_sib)
          return;
@@ -4868,6 +4874,21 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
   die->die_child = child_die;
 }
 
+/* Unassociate CHILD from its parent, and make its parent be
+   NEW_PARENT.  */
+
+static void
+reparent_child (dw_die_ref child, dw_die_ref new_parent)
+{
+  for (dw_die_ref p = child->die_parent->die_child; ; p = p->die_sib)
+    if (p->die_sib == child)
+      {
+       remove_child_with_prev (child, p);
+       break;
+      }
+  add_child_die (new_parent, child);
+}
+
 /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
    is the specification, to the end of PARENT's list of children.
    This is done by removing and re-adding it.  */
@@ -4875,8 +4896,6 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 static void
 splice_child_die (dw_die_ref parent, dw_die_ref child)
 {
-  dw_die_ref p;
-
   /* We want the declaration DIE from inside the class, not the
      specification DIE at toplevel.  */
   if (child->die_parent != parent)
@@ -4891,17 +4910,13 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
              || (child->die_parent
                  == get_AT_ref (parent, DW_AT_specification)));
 
-  for (p = child->die_parent->die_child; ; p = p->die_sib)
-    if (p->die_sib == child)
-      {
-       remove_child_with_prev (child, p);
-       break;
-      }
-
-  add_child_die (parent, child);
+  reparent_child (child, parent);
 }
 
-/* Return a pointer to a newly created DIE node.  */
+/* Create and return a new die with a parent of PARENT_DIE.  If
+   PARENT_DIE is NULL, the new DIE is placed in limbo and an
+   associated tree T must be supplied to determine parenthood
+   later.  */
 
 static inline dw_die_ref
 new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
@@ -4916,6 +4931,35 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
     {
       limbo_die_node *limbo_node;
 
+      /* No DIEs created after early dwarf should end up in limbo,
+        because the limbo list should not persist past LTO
+        streaming.  */
+      if (tag_value != DW_TAG_compile_unit
+         /* These are allowed because they're generated while
+            breaking out COMDAT units late.  */
+         && tag_value != DW_TAG_type_unit
+         && !early_dwarf
+         /* Allow nested functions to live in limbo because they will
+            only temporarily live there, as decls_for_scope will fix
+            them up.  */
+         && (TREE_CODE (t) != FUNCTION_DECL
+             || !decl_function_context (t))
+         /* Same as nested functions above but for types.  Types that
+            are local to a function will be fixed in
+            decls_for_scope.  */
+         && (!RECORD_OR_UNION_TYPE_P (t)
+             || !TYPE_CONTEXT (t)
+             || TREE_CODE (TYPE_CONTEXT (t)) != FUNCTION_DECL)
+         /* FIXME debug-early: Allow late limbo DIE creation for LTO,
+            especially in the ltrans stage, but once we implement LTO
+            dwarf streaming, we should remove this exception.  */
+         && !in_lto_p)
+       {
+         fprintf (stderr, "symbol ended up in limbo too late:");
+         debug_generic_stmt (t);
+         gcc_unreachable ();
+       }
+
       limbo_node = ggc_cleared_alloc<limbo_die_node> ();
       limbo_node->die = die;
       limbo_node->created_for = t;
@@ -5647,6 +5691,34 @@ debug_dwarf (void)
   print_indent = 0;
   print_die (comp_unit_die (), stderr);
 }
+
+/* Sanity checks on DIEs.  */
+
+static void
+check_die (dw_die_ref die)
+{
+  /* A debugging information entry that is a member of an abstract
+     instance tree [that has DW_AT_inline] should not contain any
+     attributes which describe aspects of the subroutine which vary
+     between distinct inlined expansions or distinct out-of-line
+     expansions.  */
+  unsigned ix;
+  dw_attr_ref a;
+  bool inline_found = false;
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    if (a->dw_attr == DW_AT_inline && a->dw_attr_val.v.val_unsigned)
+      inline_found = true;
+  if (inline_found)
+    {
+      /* Catch the most common mistakes.  */
+      FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+       gcc_assert (a->dw_attr != DW_AT_low_pc
+                   && a->dw_attr != DW_AT_high_pc
+                   && a->dw_attr != DW_AT_location
+                   && a->dw_attr != DW_AT_frame_base
+                   && a->dw_attr != DW_AT_GNU_all_call_sites);
+    }
+}
 \f
 /* Start a new compilation unit DIE for an include file.  OLD_UNIT is the CU
    for the enclosing include file, if any.  BINCL_DIE is the DW_TAG_GNU_BINCL
@@ -16101,17 +16173,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
   return tree_add_const_value_attribute_for_decl (die, decl);
 }
 
-/* Add VARIABLE and DIE into deferred locations list.  */
-
-static void
-defer_location (tree variable, dw_die_ref die)
-{
-  deferred_locations entry;
-  entry.variable = variable;
-  entry.die = die;
-  vec_safe_push (deferred_locations_list, entry);
-}
-
 /* Helper function for tree_add_const_value_attribute.  Natively encode
    initializer INIT into an array.  Return true if successful.  */
 
@@ -16793,14 +16854,17 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
    possibly nested array subscripts in a flat sequence if COLLAPSE_P is true.
    Note that the block of subscript information for an array type also
-   includes information about the element type of the given array type.  */
+   includes information about the element type of the given array type.
+
+   This function reuses previously set type and bound information if
+   available.  */
 
 static void
 add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 {
   unsigned dimension_number;
   tree lower, upper;
-  dw_die_ref subrange_die;
+  dw_die_ref child = type_die->die_child;
 
   for (dimension_number = 0;
        TREE_CODE (type) == ARRAY_TYPE && (dimension_number == 0 || collapse_p);
@@ -16814,7 +16878,37 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
         here.  */
-      subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
+      /* Find and reuse a previously generated DW_TAG_subrange_type if
+        available.
+
+         For multi-dimensional arrays, as we iterate through the
+         various dimensions in the enclosing for loop above, we also
+         iterate through the DIE children and pick at each
+         DW_TAG_subrange_type previously generated (if available).
+         Each child DW_TAG_subrange_type DIE describes the range of
+         the current dimension.  At this point we should have as many
+         DW_TAG_subrange_type's as we have dimensions in the
+         array.  */
+      dw_die_ref subrange_die = NULL;
+      if (child)
+       while (1)
+         {
+           child = child->die_sib;
+           if (child->die_tag == DW_TAG_subrange_type)
+             subrange_die = child;
+           if (child == type_die->die_child)
+             {
+               /* If we wrapped around, stop looking next time.  */
+               child = NULL;
+               break;
+             }
+           if (child->die_tag == DW_TAG_subrange_type)
+             break;
+         }
+      if (!subrange_die)
+       subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
       if (domain)
        {
          /* We have an array type with specified bounds.  */
@@ -16822,7 +16916,8 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
          upper = TYPE_MAX_VALUE (domain);
 
          /* Define the index type.  */
-         if (TREE_TYPE (domain))
+         if (TREE_TYPE (domain)
+             && !get_AT (subrange_die, DW_AT_type))
            {
              /* ??? This is probably an Ada unnamed subrange type.  Ignore the
                 TREE_TYPE field.  We can't emit debug info for this
@@ -16844,8 +16939,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
             to produce useful results, go ahead and output the lower
             bound solo, and hope the debugger can cope.  */
 
-         add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
-         if (upper)
+         if (!get_AT (subrange_die, DW_AT_lower_bound))
+           add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
+         if (upper && !get_AT (subrange_die, DW_AT_upper_bound))
            add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
        }
 
@@ -17472,6 +17568,25 @@ decl_start_label (tree decl)
 }
 #endif
 \f
+/* For variable-length arrays that have been previously generated, but
+   may be incomplete due to missing subscript info, fill the subscript
+   info.  Return TRUE if this is one of those cases.  */
+static bool
+fill_variable_array_bounds (tree type)
+{
+  if (TREE_ASM_WRITTEN (type)
+      && TREE_CODE (type) == ARRAY_TYPE
+      && variably_modified_type_p (type, NULL))
+    {
+      dw_die_ref array_die = lookup_type_die (type);
+      if (!array_die)
+       return false;
+      add_subscript_info (array_die, type, !is_ada ());
+      return true;
+    }
+  return false;
+}
+
 /* These routines generate the internal representation of the DIE's for
    the compilation unit.  Debugging information is collected by walking
    the declaration trees passed in from dwarf2out_decl().  */
@@ -17479,7 +17594,6 @@ decl_start_label (tree decl)
 static void
 gen_array_type_die (tree type, dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
   dw_die_ref array_die;
 
   /* GNU compilers represent multidimensional array types as sequences of one
@@ -17493,6 +17607,11 @@ gen_array_type_die (tree type, dw_die_ref context_die)
      flexibilty wrt arrays of variable size.  */
 
   bool collapse_nested_arrays = !is_ada ();
+
+  if (fill_variable_array_bounds (type))
+    return;
+
+  dw_die_ref scope_die = scope_die_for (type, context_die);
   tree element_type;
 
   /* Emit DW_TAG_string_type for Fortran character types (with kind 1 only, as
@@ -17848,8 +17967,71 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
 {
   tree node_or_origin = node ? node : origin;
   tree ultimate_origin;
-  dw_die_ref parm_die
-    = new_die (DW_TAG_formal_parameter, context_die, node);
+  dw_die_ref parm_die = NULL;
+  
+  if (TREE_CODE_CLASS (TREE_CODE (node_or_origin)) == tcc_declaration)
+    {
+      parm_die = lookup_decl_die (node);
+
+      /* If the contexts differ, we may not be talking about the same
+        thing.  */
+      if (parm_die && parm_die->die_parent != context_die)
+       {
+         if (!DECL_ABSTRACT_P (node))
+           {
+             /* This can happen when creating an inlined instance, in
+                which case we need to create a new DIE that will get
+                annotated with DW_AT_abstract_origin.  */
+             parm_die = NULL;
+           }
+         else
+           {
+             /* FIXME: Reuse DIE even with a differing context.
+
+                This happens when called through
+                dwarf2out_abstract_function for formal parameter
+                packs.  The issue is that we're calling
+                dwarf2out_abstract_function to build debug info for
+                the abstract instance of a function for which we have
+                already generated a DIE in
+                dwarf2out_early_global_decl.
+
+                Once we remove dwarf2out_abstract_function, this
+                gcc_assert should be a gcc_unreachable.  */
+             gcc_assert (parm_die->die_parent->die_tag
+                         == DW_TAG_GNU_formal_parameter_pack);
+           }
+       }
+
+      if (parm_die && parm_die->die_parent == NULL)
+       {
+         /* Check that parm_die already has the right attributes that
+            we would have added below.  If any attributes are
+            missing, fall through to add them.  */
+         if (! DECL_ABSTRACT_P (node_or_origin)
+             && !get_AT (parm_die, DW_AT_location)
+             && !get_AT (parm_die, DW_AT_const_value))
+           /* We are missing  location info, and are about to add it.  */
+           ;
+         else
+           {
+             add_child_die (context_die, parm_die);
+             return parm_die;
+           }
+       }
+    }
+
+  /* If we have a previously generated DIE, use it, unless this is an
+     concrete instance (origin != NULL), in which case we need a new
+     DIE with a corresponding DW_AT_abstract_origin.  */
+  bool reusing_die;
+  if (parm_die && origin == NULL)
+    reusing_die = true;
+  else
+    {
+      parm_die = new_die (DW_TAG_formal_parameter, context_die, node);
+      reusing_die = false;
+    }
 
   switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
     {
@@ -17857,6 +18039,10 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
       ultimate_origin = decl_ultimate_origin (node_or_origin);
       if (node || ultimate_origin)
        origin = ultimate_origin;
+
+      if (reusing_die)
+       goto add_location;
+
       if (origin != NULL)
        add_abstract_origin_attribute (parm_die, origin);
       else if (emit_name_p)
@@ -17876,6 +18062,7 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
                                decl_quals (node_or_origin),
                                context_die);
        }
+    add_location:
       if (origin == NULL && DECL_ARTIFICIAL (node))
        add_AT_flag (parm_die, DW_AT_artificial, 1);
 
@@ -18207,7 +18394,16 @@ set_decl_abstract_flags (tree decl, vec<tree> &abstract_vec)
 }
 
 /* Generate the DWARF2 info for the "abstract" instance of a function which we
-   may later generate inlined and/or out-of-line instances of.  */
+   may later generate inlined and/or out-of-line instances of.
+
+   FIXME: In the early-dwarf world, this function, and most of the
+          DECL_ABSTRACT code should be obsoleted.  The early DIE _is_
+          the abstract instance.  All we would need to do is annotate
+          the early DIE with the appropriate DW_AT_inline in late
+          dwarf (perhaps in gen_inlined_subroutine_die).
+
+         However, we can't do this yet, because LTO streaming of DIEs
+         has not been implemented yet.  */
 
 static void
 dwarf2out_abstract_function (tree decl)
@@ -18389,26 +18585,94 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref subr_die;
-  tree outer_scope;
   dw_die_ref old_die = lookup_decl_die (decl);
+
+  /* This function gets called multiple times for different stages of
+     the debug process.  For example, for func() in this code:
+
+       namespace S
+       {
+         void func() { ... }
+       }
+
+     ...we get called 4 times.  Twice in early debug and twice in
+     late debug:
+
+     Early debug
+     -----------
+
+       1. Once while generating func() within the namespace.  This is
+          the declaration.  The declaration bit below is set, as the
+          context is the namespace.
+
+         A new DIE will be generated with DW_AT_declaration set.
+
+       2. Once for func() itself.  This is the specification.  The
+          declaration bit below is clear as the context is the CU.
+
+         We will use the cached DIE from (1) to create a new DIE with
+         DW_AT_specification pointing to the declaration in (1).
+
+     Late debug via rest_of_handle_final()
+     -------------------------------------
+
+       3. Once generating func() within the namespace.  This is also the
+          declaration, as in (1), but this time we will early exit below
+          as we have a cached DIE and a declaration needs no additional
+          annotations (no locations), as the source declaration line
+          info is enough.
+
+       4. Once for func() itself.  As in (2), this is the specification,
+          but this time we will re-use the cached DIE, and just annotate
+          it with the location information that should now be available.
+
+     For something without namespaces, but with abstract instances, we
+     are also called a multiple times:
+
+        class Base
+       {
+       public:
+         Base ();        // constructor declaration (1)
+       };
+
+       Base::Base () { } // constructor specification (2)
+
+    Early debug
+    -----------
+
+       1. Once for the Base() constructor by virtue of it being a
+          member of the Base class.  This is done via
+          rest_of_type_compilation.
+
+         This is a declaration, so a new DIE will be created with
+         DW_AT_declaration.
+
+       2. Once for the Base() constructor definition, but this time
+          while generating the abstract instance of the base
+          constructor (__base_ctor) which is being generated via early
+          debug of reachable functions.
+
+         Even though we have a cached version of the declaration (1),
+         we will create a DW_AT_specification of the declaration DIE
+         in (1).
+
+       3. Once for the __base_ctor itself, but this time, we generate
+          an DW_AT_abstract_origin version of the DW_AT_specification in
+         (2).
+
+    Late debug via rest_of_handle_final
+    -----------------------------------
+
+       4. One final time for the __base_ctor (which will have a cached
+          DIE with DW_AT_abstract_origin created in (3).  This time,
+          we will just annotate the location information now
+          available.
+  */
   int declaration = (current_function_decl != decl
                     || class_or_namespace_scope_p (context_die));
 
   premark_used_types (DECL_STRUCT_FUNCTION (decl));
 
-  /* It is possible to have both DECL_ABSTRACT_P and DECLARATION be true if we
-     started to generate the abstract instance of an inline, decided to output
-     its containing class, and proceeded to emit the declaration of the inline
-     from the member list for the class.  If so, DECLARATION takes priority;
-     we'll get back to the abstract instance when done with the class.  */
-
-  /* The class-scope declaration DIE must be the primary DIE.  */
-  if (origin && declaration && class_or_namespace_scope_p (context_die))
-    {
-      origin = NULL;
-      gcc_assert (!old_die);
-    }
-
   /* Now that the C++ front end lazily declares artificial member fns, we
      might need to retrofit the declaration into its class.  */
   if (!declaration && !origin && !old_die
@@ -18417,6 +18681,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       && debug_info_level > DINFO_LEVEL_TERSE)
     old_die = force_decl_die (decl);
 
+  /* An inlined instance, tag a new DIE with DW_AT_abstract_origin.  */
   if (origin != NULL)
     {
       gcc_assert (!declaration || local_scope_p (context_die));
@@ -18426,19 +18691,32 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (old_die && old_die->die_parent == NULL)
        add_child_die (context_die, old_die);
 
-      subr_die = new_die (DW_TAG_subprogram, context_die, decl);
-      add_abstract_origin_attribute (subr_die, origin);
-      /*  This is where the actual code for a cloned function is.
-         Let's emit linkage name attribute for it.  This helps
-         debuggers to e.g, set breakpoints into
-         constructors/destructors when the user asks "break
-         K::K".  */
-      add_linkage_name (subr_die, decl);
+      if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin))
+       {
+         /* If we have a DW_AT_abstract_origin we have a working
+            cached version.  */
+         subr_die = old_die;
+       }
+      else
+       {
+         subr_die = new_die (DW_TAG_subprogram, context_die, decl);
+         add_abstract_origin_attribute (subr_die, origin);
+         /*  This is where the actual code for a cloned function is.
+             Let's emit linkage name attribute for it.  This helps
+             debuggers to e.g, set breakpoints into
+             constructors/destructors when the user asks "break
+             K::K".  */
+         add_linkage_name (subr_die, decl);
+       }
     }
+  /* A cached copy, possibly from early dwarf generation.  Reuse as
+     much as possible.  */
   else if (old_die)
     {
-      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
-      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      /* A declaration that has been previously dumped needs no
+        additional information.  */
+      if (declaration)
+       return;
 
       if (!get_AT_flag (old_die, DW_AT_declaration)
          /* We can have a normal definition following an inline one in the
@@ -18448,7 +18726,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          /* Detect and ignore this case, where we are trying to output
             something we have already output.  */
-         return;
+         if (get_AT (old_die, DW_AT_low_pc)
+             || get_AT (old_die, DW_AT_ranges))
+           return;
+
+         /* If we have no location information, this must be a
+            partially generated DIE from early dwarf generation.
+            Fall through and generate it.  */
        }
 
       /* If the definition comes from the same place as the declaration,
@@ -18458,23 +18742,43 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
         instances of inlines, since the spec requires the out-of-line copy
         to have the same parent.  For local class methods, this doesn't
         apply; we just use the old DIE.  */
-      if ((is_cu_die (old_die->die_parent) || context_die == NULL)
-         && (DECL_ARTIFICIAL (decl)
-             || (get_AT_file (old_die, DW_AT_decl_file) == file_index
-                 && (get_AT_unsigned (old_die, DW_AT_decl_line)
-                     == (unsigned) s.line))))
+      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      if ((is_cu_die (old_die->die_parent)
+          /* This condition fixes the inconsistency/ICE with the
+             following Fortran test (or some derivative thereof) while
+             building libgfortran:
+
+                module some_m
+                contains
+                   logical function funky (FLAG)
+                     funky = .true.
+                  end function
+                end module
+          */
+          || old_die->die_parent->die_tag == DW_TAG_module
+          || context_die == NULL)
+          && (DECL_ARTIFICIAL (decl)
+              || (get_AT_file (old_die, DW_AT_decl_file) == file_index
+                  && (get_AT_unsigned (old_die, DW_AT_decl_line)
+                      == (unsigned) s.line))))
        {
          subr_die = old_die;
 
-         /* Clear out the declaration attribute and the formal parameters.
-            Do not remove all children, because it is possible that this
-            declaration die was forced using force_decl_die(). In such
-            cases die that forced declaration die (e.g. TAG_imported_module)
-            is one of the children that we do not want to remove.  */
-         remove_AT (subr_die, DW_AT_declaration);
-         remove_AT (subr_die, DW_AT_object_pointer);
-         remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+         /* Clear out the declaration attribute, but leave the
+            parameters so they can be augmented with location
+            information later.  Unless this was a declaration, in
+            which case, wipe out the nameless parameters and recreate
+            them further down.  */
+         if (remove_AT (subr_die, DW_AT_declaration))
+           {
+
+             remove_AT (subr_die, DW_AT_object_pointer);
+             remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+           }
        }
+      /* Make a specification pointing to the previously built
+        declaration.  */
       else
        {
          subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18496,6 +18800,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
            }
        }
     }
+  /* Create a fresh DIE for anything else.  */
   else
     {
       subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18522,6 +18827,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       add_accessibility_attribute (subr_die, decl);
     }
 
+  /* Unless we have an existing non-declaration DIE, equate the new
+     DIE.  */
+  if (!old_die || is_declaration_die (old_die))
+    equate_decl_number_to_die (decl, subr_die);
+
   if (declaration)
     {
       if (!old_die || !get_AT (old_die, DW_AT_inline))
@@ -18539,17 +18849,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
          if (lang_hooks.decls.function_decl_deleted_p (decl)
              && (! dwarf_strict))
            add_AT_flag (subr_die, DW_AT_GNU_deleted, 1);
-
-         /* The first time we see a member function, it is in the context of
-            the class to which it belongs.  We make sure of this by emitting
-            the class first.  The next time is the definition, which is
-            handled above.  The two may come from the same source text.
-
-            Note that force_decl_die() forces function declaration die. It is
-            later reused to represent definition.  */
-         equate_decl_number_to_die (decl, subr_die);
        }
     }
+  /* Tag abstract instances with DW_AT_inline.  */
   else if (DECL_ABSTRACT_P (decl))
     {
       if (DECL_DECLARED_INLINE_P (decl))
@@ -18570,18 +18872,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_DECLARED_INLINE_P (decl)
          && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
        add_AT_flag (subr_die, DW_AT_artificial, 1);
-
-      equate_decl_number_to_die (decl, subr_die);
     }
-  else if (!DECL_EXTERNAL (decl))
+  /* For non DECL_EXTERNALs, if range information is available, fill
+     the DIE with it.  */
+  else if (!DECL_EXTERNAL (decl) && !early_dwarf)
     {
       HOST_WIDE_INT cfa_fb_offset;
-      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      if (!old_die || !get_AT (old_die, DW_AT_inline))
-       equate_decl_number_to_die (decl, subr_die);
+      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      gcc_checking_assert (fun);
       if (!flag_reorder_blocks_and_partition)
        {
          dw_fde_ref fde = fun->fde;
@@ -18735,12 +19034,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
 
       if (fun->static_chain_decl)
-       add_AT_location_description (subr_die, DW_AT_static_link,
-                loc_list_from_tree (fun->static_chain_decl, 2, NULL));
+       add_AT_location_description
+         (subr_die, DW_AT_static_link,
+          loc_list_from_tree (fun->static_chain_decl, 2, NULL));
     }
 
   /* Generate child dies for template paramaters.  */
-  if (debug_info_level > DINFO_LEVEL_TERSE)
+  if (early_dwarf && debug_info_level > DINFO_LEVEL_TERSE)
     gen_generic_params_dies (decl);
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -18764,7 +19064,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
     {
       /* Generate DIEs to represent all known formal parameters.  */
       tree parm = DECL_ARGUMENTS (decl);
-      tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl);
+      tree generic_decl = early_dwarf
+       ? lang_hooks.decls.get_generic_function_decl (decl) : NULL;
       tree generic_decl_parm = generic_decl
                                ? DECL_ARGUMENTS (generic_decl)
                                : NULL;
@@ -18829,11 +19130,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        gen_unspecified_parameters_die (decl, subr_die);
     }
 
+  if (subr_die != old_die)
+    /* Add the calling convention attribute if requested.  */
+    add_calling_convention_attribute (subr_die, decl);
+
   /* Output Dwarf info for all of the stuff within the body of the function
-     (if it has one - it may be just a declaration).  */
-  outer_scope = DECL_INITIAL (decl);
+     (if it has one - it may be just a declaration).
 
-  /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
+     OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
      a function.  This BLOCK actually represents the outermost binding contour
      for the function, i.e. the contour in which the function's formal
      parameters and labels get declared. Curiously, it appears that the front
@@ -18847,6 +19151,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
      a BLOCK node representing the function's outermost pair of curly braces,
      and any blocks used for the base and member initializers of a C++
      constructor function.  */
+  tree outer_scope = DECL_INITIAL (decl);
   if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
     {
       int call_site_note_count = 0;
@@ -18856,6 +19161,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_NAME (DECL_RESULT (decl)))
        gen_decl_die (DECL_RESULT (decl), NULL, subr_die);
 
+      /* The first time through decls_for_scope we will generate the
+        DIEs for the locals.  The second time, we fill in the
+        location info.  */
       decls_for_scope (outer_scope, subr_die);
 
       if (call_arg_locations && !dwarf_strict)
@@ -19007,10 +19315,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       call_site_count = -1;
       tail_call_site_count = -1;
     }
-
-  if (subr_die != old_die)
-    /* Add the calling convention attribute if requested.  */
-    add_calling_convention_attribute (subr_die, decl);
 }
 
 /* Returns a hash value for X (which really is a die_struct).  */
@@ -19030,6 +19334,33 @@ block_die_hasher::equal (die_struct *x, die_struct *y)
   return x->decl_id == y->decl_id && x->die_parent == y->die_parent;
 }
 
+/* Return TRUE if DECL, which may have been previously generated as
+   OLD_DIE, is a candidate for a DW_AT_specification.  DECLARATION is
+   true if decl (or its origin) is either an extern declaration or a
+   class/namespace scoped declaration.
+
+   The declare_in_namespace support causes us to get two DIEs for one
+   variable, both of which are declarations.  We want to avoid
+   considering one to be a specification, so we must test for
+   DECLARATION and DW_AT_declaration.  */
+static inline bool
+decl_will_get_specification_p (dw_die_ref old_die, tree decl, bool declaration)
+{
+  return (old_die && TREE_STATIC (decl) && !declaration
+         && get_AT_flag (old_die, DW_AT_declaration) == 1);
+}
+
+/* Return true if DECL is a local static.  */
+
+static inline bool
+local_function_static (tree decl)
+{
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  return TREE_STATIC (decl)
+    && DECL_CONTEXT (decl)
+    && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL;
+}
+
 /* Generate a DIE to represent a declared data object.
    Either DECL or ORIGIN must be non-null.  */
 
@@ -19042,7 +19373,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   tree ultimate_origin;
   dw_die_ref var_die;
   dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
-  dw_die_ref origin_die;
+  dw_die_ref origin_die = NULL;
   bool declaration = (DECL_EXTERNAL (decl_or_origin)
                      || class_or_namespace_scope_p (context_die));
   bool specialization_p = false;
@@ -19157,12 +19488,38 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       return;
     }
 
-  /* If the compiler emitted a definition for the DECL declaration
-     and if we already emitted a DIE for it, don't emit a second
-     DIE for it again. Allow re-declarations of DECLs that are
-     inside functions, though.  */
-  if (old_die && declaration && !local_scope_p (context_die))
-    return;
+  if (old_die)
+    {
+      if (declaration)
+       {
+         /* A declaration that has been previously dumped, needs no
+            further annotations, since it doesn't need location on
+            the second pass.  */
+         return;
+       }
+      else if (decl_will_get_specification_p (old_die, decl, declaration)
+              && !get_AT (old_die, DW_AT_specification))
+       {
+         /* Fall-thru so we can make a new variable die along with a
+            DW_AT_specification.  */
+       }
+      else if (origin && old_die->die_parent != context_die)
+       {
+         /* If we will be creating an inlined instance, we need a
+            new DIE that will get annotated with
+            DW_AT_abstract_origin.  Clear things so we can get a
+            new DIE.  */
+         gcc_assert (!DECL_ABSTRACT_P (decl));
+         old_die = NULL;
+       }
+      else
+       {
+         /* If a DIE was dumped early, it still needs location info.
+            Skip to where we fill the location bits.  */
+         var_die = old_die;
+         goto gen_variable_die_location;
+       }
+    }
 
   /* For static data members, the declaration in the class is supposed
      to have DW_TAG_member tag; the specification should still be
@@ -19172,7 +19529,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   else
     var_die = new_die (DW_TAG_variable, context_die, decl);
 
-  origin_die = NULL;
   if (origin != NULL)
     origin_die = add_abstract_origin_attribute (var_die, origin);
 
@@ -19183,14 +19539,8 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
      copy decls and set the DECL_ABSTRACT_P flag on them instead of
      sharing them.
 
-     ??? Duplicated blocks have been rewritten to use .debug_ranges.
-
-     ??? The declare_in_namespace support causes us to get two DIEs for one
-     variable, both of which are declarations.  We want to avoid considering
-     one to be a specification, so we must test that this DIE is not a
-     declaration.  */
-  else if (old_die && TREE_STATIC (decl) && ! declaration
-          && get_AT_flag (old_die, DW_AT_declaration) == 1)
+     ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
+  else if (decl_will_get_specification_p (old_die, decl, declaration))
     {
       /* This is a definition of a C++ class level static.  */
       add_AT_specification (var_die, old_die);
@@ -19244,9 +19594,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (declaration)
     add_AT_flag (var_die, DW_AT_declaration, 1);
 
-  if (decl && (DECL_ABSTRACT_P (decl) || declaration || old_die == NULL))
+  if (decl && (DECL_ABSTRACT_P (decl)
+              || !old_die || is_declaration_die (old_die)))
     equate_decl_number_to_die (decl, var_die);
 
+ gen_variable_die_location:
   if (! declaration
       && (! DECL_ABSTRACT_P (decl_or_origin)
          /* Local static vars are shared between all clones/inlines,
@@ -19259,13 +19611,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
         to add it again.  */
       && (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
     {
-      if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
-          && !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
-       defer_location (decl_or_origin, var_die);
+      if (early_dwarf)
+       add_pubname (decl_or_origin, var_die);
       else
-        add_location_or_const_value_attribute (var_die, decl_or_origin,
+       add_location_or_const_value_attribute (var_die, decl_or_origin,
                                               decl == NULL, DW_AT_location);
-      add_pubname (decl_or_origin, var_die);
     }
   else
     tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
@@ -19279,7 +19629,12 @@ gen_const_die (tree decl, dw_die_ref context_die)
   dw_die_ref const_die;
   tree type = TREE_TYPE (decl);
 
+  const_die = lookup_decl_die (decl);
+  if (const_die)
+    return;
+
   const_die = new_die (DW_TAG_constant, context_die, decl);
+  equate_decl_number_to_die (decl, const_die);
   add_name_and_src_coords_attributes (const_die, decl);
   add_type_attribute (const_die, type, TYPE_QUAL_CONST, context_die);
   if (TREE_PUBLIC (decl))
@@ -19295,14 +19650,20 @@ static void
 gen_label_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
-  dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
+  dw_die_ref lbl_die = lookup_decl_die (decl);
   rtx insn;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  if (origin != NULL)
-    add_abstract_origin_attribute (lbl_die, origin);
-  else
-    add_name_and_src_coords_attributes (lbl_die, decl);
+  if (!lbl_die)
+    {
+      lbl_die = new_die (DW_TAG_label, context_die, decl);
+      equate_decl_number_to_die (decl, lbl_die);
+
+      if (origin != NULL)
+       add_abstract_origin_attribute (lbl_die, origin);
+      else
+       add_name_and_src_coords_attributes (lbl_die, decl);
+    }
 
   if (DECL_ABSTRACT_P (decl))
     equate_decl_number_to_die (decl, lbl_die);
@@ -19456,13 +19817,56 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
 static void
 gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 {
-  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+  dw_die_ref old_die = BLOCK_DIE (stmt);
+  dw_die_ref stmt_die;
+  if (!old_die)
+    {
+      stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+      BLOCK_DIE (stmt) = stmt_die;
+    }
+
+  if (BLOCK_ABSTRACT (stmt))
+    {
+      if (old_die)
+       {
+#ifdef ENABLE_CHECKING
+         /* This must have been generated early and it won't even
+            need location information since it's a DW_AT_inline
+            function.  */
+         for (dw_die_ref c = context_die; c; c = c->die_parent)
+           if (c->die_tag == DW_TAG_inlined_subroutine
+               || c->die_tag == DW_TAG_subprogram)
+             {
+               gcc_assert (get_AT (c, DW_AT_inline));
+               break;
+             }
+#endif
+         return;
+       }
+    }
+  else if (BLOCK_ABSTRACT_ORIGIN (stmt))
+    {
+      /* If this is an inlined instance, create a new lexical die for
+        anything below to attach DW_AT_abstract_origin to.  */
+      if (old_die)
+       {
+         stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+         BLOCK_DIE (stmt) = stmt_die;
+         old_die = NULL;
+       }
+    }
 
-  if (call_arg_locations)
-    BLOCK_DIE (stmt) = stmt_die;
+  if (old_die)
+    stmt_die = old_die;
 
-  if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
-    add_high_low_attributes (stmt, stmt_die);
+  if (!early_dwarf)
+    {
+      /* A non abstract block whose blocks have already been reordered
+        should have the instruction range for this block.  If so, set the
+        high/low attributes.  */
+      if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
+       add_high_low_attributes (stmt, stmt_die);
+    }
 
   decls_for_scope (stmt, stmt_die);
 }
@@ -19957,6 +20361,18 @@ static void
 gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
                                enum debug_info_usage usage)
 {
+  /* Fill in the bound of variable-length fields in late dwarf if
+     still incomplete.  */
+  if (TREE_ASM_WRITTEN (type)
+      && variably_modified_type_p (type, NULL)
+      && !early_dwarf)
+    {
+      tree member;
+      for (member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
+       fill_variable_array_bounds (TREE_TYPE (member));
+      return;
+    }
+
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref scope_die = 0;
   int nested = 0;
@@ -20076,7 +20492,11 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
   tree origin;
 
   if (TREE_ASM_WRITTEN (decl))
-    return;
+    {
+      if (DECL_ORIGINAL_TYPE (decl))
+       fill_variable_array_bounds (DECL_ORIGINAL_TYPE (decl));
+      return;
+    }
 
   TREE_ASM_WRITTEN (decl) = 1;
   type_die = new_die (DW_TAG_typedef, context_die, decl);
@@ -20092,6 +20512,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = DECL_ORIGINAL_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          gcc_assert (type != TREE_TYPE (decl));
          equate_type_number_to_die (TREE_TYPE (decl), type_die);
        }
@@ -20099,6 +20522,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = TREE_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          if (is_naming_typedef_decl (TYPE_NAME (type)))
            {
              /* Here, we are in the case of decl being a typedef naming
@@ -20159,13 +20585,15 @@ gen_tagged_type_die (tree type,
       || !is_tagged_type (type))
     return;
 
+  if (TREE_ASM_WRITTEN (type))
+    need_pop = 0;
   /* If this is a nested type whose containing class hasn't been written
      out yet, writing it out will cover this one, too.  This does not apply
      to instantiations of member class templates; they need to be added to
      the containing class as they are generated.  FIXME: This hurts the
      idea of combining type decls from multiple TUs, since we can't predict
      what set of template instantiations we'll get.  */
-  if (TYPE_CONTEXT (type)
+  else if (TYPE_CONTEXT (type)
       && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
       && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
     {
@@ -20297,7 +20725,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     }
 
   if (TREE_ASM_WRITTEN (type))
-    return;
+    {
+      /* Variable-length types may be incomplete even if
+        TREE_ASM_WRITTEN.  For such types, fall through to
+        gen_array_type_die() and possibly fill in
+        DW_AT_{upper,lower}_bound attributes.  */
+      if ((TREE_CODE (type) != ARRAY_TYPE
+          && TREE_CODE (type) != RECORD_TYPE
+          && TREE_CODE (type) != UNION_TYPE
+          && TREE_CODE (type) != QUAL_UNION_TYPE)
+         || !variably_modified_type_p (type, NULL))
+       return;
+    }
 
   switch (TREE_CODE (type))
     {
@@ -20349,9 +20788,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     case ARRAY_TYPE:
-      gen_array_type_die (type, context_die);
-      break;
-
     case VECTOR_TYPE:
       gen_array_type_die (type, context_die);
       break;
@@ -20522,8 +20958,11 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
   if (die != NULL && die->die_parent == NULL)
     add_child_die (context_die, die);
   else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
-    dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
-                                        stmt, context_die);
+    {
+      if (early_dwarf)
+       dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
+                                            stmt, context_die);
+    }
   else
     gen_decl_die (decl, origin, context_die);
 }
@@ -20759,7 +21198,9 @@ setup_namespace_context (tree thing, dw_die_ref context_die)
    type) within its namespace, if appropriate.
 
    For compatibility with older debuggers, namespace DIEs only contain
-   declarations; all definitions are emitted at CU scope.  */
+   declarations; all definitions are emitted at CU scope, with
+   DW_AT_specification pointing to the declaration (like with class
+   members).  */
 
 static dw_die_ref
 declare_in_namespace (tree thing, dw_die_ref context_die)
@@ -21076,16 +21517,65 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from toplev.c after
-   compilation proper has finished.  */
+/* Output initial debug information for global DECL.  Called at the
+   end of the parsing process.
+
+   This is the initial debug generation process.  As such, the DIEs
+   generated may be incomplete.  A later debug generation pass
+   (dwarf2out_late_global_decl) will augment the information generated
+   in this pass (e.g., with complete location info).  */
+
+static void
+dwarf2out_early_global_decl (tree decl)
+{
+  set_early_dwarf s;
+
+  /* gen_decl_die() will set DECL_ABSTRACT because
+     cgraph_function_possibly_inlined_p() returns true.  This is in
+     turn will cause DW_AT_inline attributes to be set.
+
+     This happens because at early dwarf generation, there is no
+     cgraph information, causing cgraph_function_possibly_inlined_p()
+     to return true.  Trick cgraph_function_possibly_inlined_p()
+     while we generate dwarf early.  */
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
+
+  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
+     other DECLs and they can point to template types or other things
+     that dwarf2out can't handle when done via dwarf2out_decl.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != PARM_DECL)
+    {
+      tree save_fndecl = current_function_decl;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         /* No cfun means the symbol has no body, so there's nothing
+            to emit.  */
+         if (!DECL_STRUCT_FUNCTION (decl))
+           goto early_decl_exit;
+
+         current_function_decl = decl;
+       }
+      dwarf2out_decl (decl);
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       current_function_decl = save_fndecl;
+    }
+ early_decl_exit:
+  symtab->global_info_ready = save;
+}
+
+/* Output debug information for global decl DECL.  Called from
+   toplev.c after compilation proper has finished.  */
 
 static void
-dwarf2out_global_decl (tree decl)
+dwarf2out_late_global_decl (tree decl)
 {
-  /* Output DWARF2 information for file-scope tentative data object
-     declarations, file-scope (extern) function declarations (which
-     had no corresponding body) and file-scope tagged type declarations
-     and definitions which have not yet been forced out.  */
+  /* Output any global decls we missed or fill-in any location
+     information we were unable to determine on the first pass.
+
+     Skip over functions because they were handled by the
+     debug_hooks->function_decl() call in rest_of_handle_final.  */
   if ((TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
       && !POINTER_BOUNDS_P (decl))
     dwarf2out_decl (decl);
@@ -21097,7 +21587,10 @@ static void
 dwarf2out_type_decl (tree decl, int local)
 {
   if (!local)
-    dwarf2out_decl (decl);
+    {
+      set_early_dwarf s;
+      dwarf2out_decl (decl);
+    }
 }
 
 /* Output debug information for imported module or decl DECL.
@@ -21205,6 +21698,8 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   gcc_assert (decl);
 
+  set_early_dwarf s;
+
   /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
      We need decl DIE for reference and scope die. First, get DIE for the decl
      itself.  */
@@ -21231,7 +21726,6 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   /* OK, now we have DIEs for decl as well as scope. Emit imported die.  */
   dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
-
 }
 
 /* Output debug information for namelists.   */
@@ -21271,7 +21765,7 @@ gen_namelist_decl (tree name, dw_die_ref scope_die, tree item_decls)
 }
 
 
-/* Write the debugging output for DECL.  */
+/* Write the debugging output for DECL and return the DIE.  */
 
 static void
 dwarf2out_decl (tree decl)
@@ -21330,21 +21824,8 @@ dwarf2out_decl (tree decl)
       break;
 
     case VAR_DECL:
-      /* Ignore this VAR_DECL if it refers to a file-scope extern data object
-        declaration and if the declaration was never even referenced from
-        within this entire compilation unit.  We suppress these DIEs in
-        order to save space in the .debug section (by eliminating entries
-        which are probably useless).  Note that we must not suppress
-        block-local extern declarations (whether used or not) because that
-        would screw-up the debugger's name lookup mechanism and cause it to
-        miss things which really ought to be in scope at a given point.  */
-      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
-       return;
-
       /* For local statics lookup proper context die.  */
-      if (TREE_STATIC (decl)
-         && DECL_CONTEXT (decl)
-         && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+      if (local_function_static (decl))
        context_die = lookup_decl_die (DECL_CONTEXT (decl));
 
       /* If we are in terse mode, don't generate any DIEs to represent any
@@ -21399,6 +21880,10 @@ dwarf2out_decl (tree decl)
     }
 
   gen_decl_die (decl, NULL, context_die);
+
+  dw_die_ref die = lookup_decl_die (decl);
+  if (die)
+    check_die (die);
 }
 
 /* Write the debugging output for DECL.  */
@@ -21485,23 +21970,16 @@ dwarf_file_hasher::hash (dwarf_file_data *p)
    section) and references to those files numbers (in the .debug_srcinfo
    and.debug_macinfo sections).  If the filename given as an argument is not
    found in our current list, add it to the list and assign it the next
-   available unique index number.  In order to speed up searches, we remember
-   the index of the filename was looked up last.  This handles the majority of
-   all searches.  */
+   available unique index number.  */
 
 static struct dwarf_file_data *
 lookup_filename (const char *file_name)
 {
   struct dwarf_file_data * created;
 
-  /* Check to see if the file name that was searched on the previous
-     call matches this file name.  If so, return the index.  */
-  if (file_table_last_lookup
-      && (file_name == file_table_last_lookup->filename
-         || filename_cmp (file_table_last_lookup->filename, file_name) == 0))
-    return file_table_last_lookup;
+  if (!file_name)
+    return NULL;
 
-  /* Didn't match the previous lookup, search the table.  */
   dwarf_file_data **slot
     = file_table->find_slot_with_hash (file_name, htab_hash_string (file_name),
                                       INSERT);
@@ -24550,11 +25028,12 @@ optimize_location_lists (dw_die_ref die)
 static void
 dwarf2out_finish (const char *filename)
 {
-  limbo_die_node *node, *next_node;
   comdat_type_node *ctnode;
-  unsigned int i;
   dw_die_ref main_comp_unit_die;
 
+  /* Flush out any latecomers to the limbo party.  */
+  dwarf2out_early_finish ();
+
   /* PCH might result in DW_AT_producer string being restored from the
      header compilation, so always fill it with empty string initially
      and overwrite only here.  */
@@ -24584,65 +25063,6 @@ dwarf2out_finish (const char *filename)
        add_comp_dir_attribute (comp_unit_die ());
     }
 
-  if (deferred_locations_list)
-    for (i = 0; i < deferred_locations_list->length (); i++)
-      {
-       add_location_or_const_value_attribute (
-           (*deferred_locations_list)[i].die,
-           (*deferred_locations_list)[i].variable,
-           false,
-           DW_AT_location);
-      }
-
-  /* Traverse the limbo die list, and add parent/child links.  The only
-     dies without parents that should be here are concrete instances of
-     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
-     For concrete instances, we can get the parent die from the abstract
-     instance.  */
-  for (node = limbo_die_list; node; node = next_node)
-    {
-      dw_die_ref die = node->die;
-      next_node = node->next;
-
-      if (die->die_parent == NULL)
-       {
-         dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
-
-         if (origin && origin->die_parent)
-           add_child_die (origin->die_parent, die);
-         else if (is_cu_die (die))
-           ;
-         else if (seen_error ())
-           /* It's OK to be confused by errors in the input.  */
-           add_child_die (comp_unit_die (), die);
-         else
-           {
-             /* In certain situations, the lexical block containing a
-                nested function can be optimized away, which results
-                in the nested function die being orphaned.  Likewise
-                with the return type of that nested function.  Force
-                this to be a child of the containing function.
-
-                It may happen that even the containing function got fully
-                inlined and optimized out.  In that case we are lost and
-                assign the empty child.  This should not be big issue as
-                the function is likely unreachable too.  */
-             gcc_assert (node->created_for);
-
-             if (DECL_P (node->created_for))
-               origin = get_context_die (DECL_CONTEXT (node->created_for));
-             else if (TYPE_P (node->created_for))
-               origin = scope_die_for (node->created_for, comp_unit_die ());
-             else
-               origin = comp_unit_die ();
-
-             add_child_die (origin, die);
-           }
-       }
-    }
-
-  limbo_die_list = NULL;
-
 #if ENABLE_ASSERT_CHECKING
   {
     dw_die_ref die = comp_unit_die (), c;
@@ -24652,23 +25072,6 @@ dwarf2out_finish (const char *filename)
   resolve_addr (comp_unit_die ());
   move_marked_base_types ();
 
-  for (node = deferred_asm_name; node; node = node->next)
-    {
-      tree decl = node->created_for;
-      /* When generating LTO bytecode we can not generate new assembler
-         names at this point and all important decls got theirs via
-        free-lang-data.  */
-      if (((!flag_generate_lto && !flag_generate_offload)
-          || DECL_ASSEMBLER_NAME_SET_P (decl))
-         && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-       {
-         add_linkage_attr (node->die, decl);
-         move_linkage_attr (node->die);
-       }
-    }
-
-  deferred_asm_name = NULL;
-
   /* Walk through the list of incomplete types again, trying once more to
      emit full debugging info for them.  */
   retry_incomplete_types ();
@@ -24707,6 +25110,7 @@ dwarf2out_finish (const char *filename)
   /* Traverse the DIE's and add add sibling attributes to those DIE's
      that have children.  */
   add_sibling_attributes (comp_unit_die ());
+  limbo_die_node *node;
   for (node = limbo_die_list; node; node = node->next)
     add_sibling_attributes (node->die);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -24968,6 +25372,83 @@ dwarf2out_finish (const char *filename)
     output_indirect_strings ();
 }
 
+/* Perform any cleanups needed after the early debug generation pass
+   has run.  */
+
+static void
+dwarf2out_early_finish (void)
+{
+  limbo_die_node *node, *next_node;
+
+  /* Add DW_AT_linkage_name for all deferred DIEs.  */
+  for (node = deferred_asm_name; node; node = node->next)
+    {
+      tree decl = node->created_for;
+      if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
+         /* A missing DECL_ASSEMBLER_NAME can be a constant DIE that
+            ended up in in deferred_asm_name before we knew it was
+            constant and never written to disk.  */
+         && DECL_ASSEMBLER_NAME (decl))
+       {
+         add_linkage_attr (node->die, decl);
+         move_linkage_attr (node->die);
+       }
+    }
+  deferred_asm_name = NULL;
+
+  /* Traverse the limbo die list, and add parent/child links.  The only
+     dies without parents that should be here are concrete instances of
+     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
+     For concrete instances, we can get the parent die from the abstract
+     instance.
+
+     The point here is to flush out the limbo list so that it is empty
+     and we don't need to stream it for LTO.  */
+  for (node = limbo_die_list; node; node = next_node)
+    {
+      dw_die_ref die = node->die;
+      next_node = node->next;
+
+      if (die->die_parent == NULL)
+       {
+         dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
+
+         if (origin && origin->die_parent)
+           add_child_die (origin->die_parent, die);
+         else if (is_cu_die (die))
+           ;
+         else if (seen_error ())
+           /* It's OK to be confused by errors in the input.  */
+           add_child_die (comp_unit_die (), die);
+         else
+           {
+             /* In certain situations, the lexical block containing a
+                nested function can be optimized away, which results
+                in the nested function die being orphaned.  Likewise
+                with the return type of that nested function.  Force
+                this to be a child of the containing function.
+
+                It may happen that even the containing function got fully
+                inlined and optimized out.  In that case we are lost and
+                assign the empty child.  This should not be big issue as
+                the function is likely unreachable too.  */
+             gcc_assert (node->created_for);
+
+             if (DECL_P (node->created_for))
+               origin = get_context_die (DECL_CONTEXT (node->created_for));
+             else if (TYPE_P (node->created_for))
+               origin = scope_die_for (node->created_for, comp_unit_die ());
+             else
+               origin = comp_unit_die ();
+
+             add_child_die (origin, die);
+           }
+       }
+    }
+
+  limbo_die_list = NULL;
+}
+
 /* Reset all state within dwarf2out.c so that we can rerun the compiler
    within the same process.  For use by toplev::finalize.  */
 
@@ -25006,13 +25487,10 @@ dwarf2out_c_finalize (void)
   cold_text_section = NULL;
   current_unit_personality = NULL;
 
-  deferred_locations_list = NULL;
-
   next_die_offset = 0;
   single_comp_unit_die = NULL;
   comdat_type_list = NULL;
   limbo_die_list = NULL;
-  deferred_asm_name = NULL;
   file_table = NULL;
   decl_die_table = NULL;
   common_block_die_table = NULL;
@@ -25045,7 +25523,6 @@ dwarf2out_c_finalize (void)
   poc_label_num = 0;
   last_emitted_file = NULL;
   label_num = 0;
-  file_table_last_lookup = NULL;
   tmpl_value_parm_die_table = NULL;
   generic_type_instances = NULL;
   frame_pointer_fb_offset = 0;
index 2bf67171c0728712399872cfc5cbec7f36d9e317..c4958ee1d5fc7fb53c85a5e4a3c78f0753317c04 100644 (file)
@@ -1,3 +1,13 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * f95-lang.c (gfc_write_global_declarations): Remove.
+       (LANG_HOOKS_WRITE_GLOBALS): Remove.
+       (gfc_write_global_declarations): Move code from here to...
+       (gfc_be_parse_file): ...here.
+       Call global_decl_processing.
+       * trans-decl.c (gfc_emit_parameter_debug_info): Rename global_decl
+       to early_global_decl.
+
 2015-06-05  Russell Whitesides  <russelldub@gmail.com>
            Steven G. Kargl  <kargl@gcc.gnu.org>
 
index fbfc72d2417c443e3f76c129cdc1b7083b60a7ae..f439427aca3175f3d960c5b3f0fc239bd69b4808 100644 (file)
@@ -94,7 +94,6 @@ static bool global_bindings_p (void);
 /* Each front end provides its own.  */
 static bool gfc_init (void);
 static void gfc_finish (void);
-static void gfc_write_global_declarations (void);
 static void gfc_be_parse_file (void);
 static alias_set_type gfc_get_alias_set (tree);
 static void gfc_init_ts (void);
@@ -121,7 +120,6 @@ static const struct attribute_spec gfc_attribute_table[] =
 #undef LANG_HOOKS_NAME
 #undef LANG_HOOKS_INIT
 #undef LANG_HOOKS_FINISH
-#undef LANG_HOOKS_WRITE_GLOBALS
 #undef LANG_HOOKS_OPTION_LANG_MASK
 #undef LANG_HOOKS_INIT_OPTIONS_STRUCT
 #undef LANG_HOOKS_INIT_OPTIONS
@@ -155,7 +153,6 @@ static const struct attribute_spec gfc_attribute_table[] =
 #define LANG_HOOKS_NAME                 "GNU Fortran"
 #define LANG_HOOKS_INIT                 gfc_init
 #define LANG_HOOKS_FINISH               gfc_finish
-#define LANG_HOOKS_WRITE_GLOBALS       gfc_write_global_declarations
 #define LANG_HOOKS_OPTION_LANG_MASK    gfc_option_lang_mask
 #define LANG_HOOKS_INIT_OPTIONS_STRUCT  gfc_init_options_struct
 #define LANG_HOOKS_INIT_OPTIONS         gfc_init_options
@@ -226,9 +223,21 @@ gfc_be_parse_file (void)
   while (!global_bindings_p ())
     poplevel (0, 0);
 
+  /* Finalize all of the globals.
+
+     Emulated tls lowering needs to see all TLS variables before we
+     call finalize_compilation_unit.  The C/C++ front ends manage this
+     by calling decl_rest_of_compilation on each global and static
+     variable as they are seen.  The Fortran front end waits until
+     here.  */
+  for (tree decl = getdecls (); decl ; decl = DECL_CHAIN (decl))
+    rest_of_decl_compilation (decl, true, true);
+
   /* Switch to the default tree diagnostics here, because there may be
      diagnostics before gfc_finish().  */
   gfc_diagnostics_finish ();
+
+  global_decl_processing ();
 }
 
 
@@ -272,32 +281,6 @@ gfc_finish (void)
   return;
 }
 
-/* ??? This is something of a hack.
-
-   Emulated tls lowering needs to see all TLS variables before we call
-   finalize_compilation_unit.  The C/C++ front ends manage this
-   by calling decl_rest_of_compilation on each global and static variable
-   as they are seen.  The Fortran front end waits until this hook.
-
-   A Correct solution is for finalize_compilation_unit not to be
-   called during the WRITE_GLOBALS langhook, and have that hook only do what
-   its name suggests and write out globals.  But the C++ and Java front ends
-   have (unspecified) problems with aliases that gets in the way.  It has
-   been suggested that these problems would be solved by completing the
-   conversion to cgraph-based aliases.  */
-
-static void
-gfc_write_global_declarations (void)
-{
-  tree decl;
-
-  /* Finalize all of the globals.  */
-  for (decl = getdecls(); decl ; decl = DECL_CHAIN (decl))
-    rest_of_decl_compilation (decl, true, true);
-
-  write_global_declarations ();
-}
-
 /* These functions and variables deal with binding contours.  We only
    need these functions for the list of PARM_DECLs, but we leave the
    functions more general; these are a simplified version of the
index a92e4d86baaed80cd0513b00573ebe7319dad9fd..65bd37d748c09740cdfc78acba26fa7b796e82e3 100644 (file)
@@ -4828,7 +4828,7 @@ gfc_emit_parameter_debug_info (gfc_symbol *sym)
                                              TREE_TYPE (decl),
                                              sym->attr.dimension,
                                              false, false);
-  debug_hooks->global_decl (decl);
+  debug_hooks->early_global_decl (decl);
 }
 
 
index 5d219c37e27e87c8fd08843e18c1ab05aae5c93e..eda1db7f10fcaf54d52aada3069386ffc0d80f20 100644 (file)
@@ -4720,33 +4720,6 @@ write_roots (pair_p variables, bool emit_pch)
    this funcion will have to be adjusted to be more like
    output_mangled_typename.  */
 
-static void
-output_typename (outf_p of, const_type_p t)
-{
-  switch (t->kind)
-    {
-    case TYPE_STRING:
-      oprintf (of, "str");
-      break;
-    case TYPE_SCALAR:
-      oprintf (of, "scalar");
-      break;
-    case TYPE_POINTER:
-      output_typename (of, t->u.p);
-      break;
-    case TYPE_STRUCT:
-    case TYPE_USER_STRUCT:
-    case TYPE_UNION:
-    case TYPE_LANG_STRUCT:
-      oprintf (of, "%s", t->u.s.tag);
-      break;
-    case TYPE_NONE:
-    case TYPE_UNDEFINED:
-    case TYPE_ARRAY:
-      gcc_unreachable ();
-    }
-}
-
 #define INDENT 2
 
 /* Dumps the value of typekind KIND.  */
index da13f9493c3679e9a1c08b08ff95da8ec7954342..f996de2a3e5a7df6a52b3b6e9a24c972269cf518 100644 (file)
@@ -1,3 +1,12 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * go-gcc.cc (write_global_definitions): Remove call to
+       finalize_compilation_unit.
+       Remove Go specific debug generation.
+       * go-lang.c (go_langhook_parse_file): Call go_write_globals.
+       (go_langhook_write_globals): Remove.
+       Remove LANG_HOOKS_WRITE_GLOBALS everywhere.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * go-backend.c: Adjust includes for restructured coretypes.h.
index 77e1a2ec9eb6dc0baef2ef056aae7433d9b7503e..65f4181fde902b207cffbff0aa74e229897ccdb9 100644 (file)
@@ -3020,7 +3020,8 @@ Gcc_backend::lookup_builtin(const std::string& name)
 }
 
 // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
-// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
+// FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
+// emit early debugging information.
 
 void
 Gcc_backend::write_global_definitions(
@@ -3093,11 +3094,6 @@ Gcc_backend::write_global_definitions(
 
   wrapup_global_declarations(defs, i);
 
-  symtab->finalize_compilation_unit();
-
-  check_global_declarations(defs, i);
-  emit_debug_global_declarations(defs, i);
-
   delete[] defs;
 }
 
index 523131536e6480f048d4046eb92f8879604fb949..28db40aa401ef57832ef28d74eac1cbd5368ed3b 100644 (file)
@@ -307,6 +307,9 @@ go_langhook_parse_file (void)
 {
   go_parse_input_files (in_fnames, num_in_fnames, flag_syntax_only,
                        go_require_return_statement);
+
+  /* Final processing of globals and early debug info generation.  */
+  go_write_globals ();
 }
 
 static tree
@@ -452,14 +455,6 @@ go_langhook_getdecls (void)
   return NULL;
 }
 
-/* Write out globals.  */
-
-static void
-go_langhook_write_globals (void)
-{
-  go_write_globals ();
-}
-
 /* Go specific gimplification.  We need to gimplify
    CALL_EXPR_STATIC_CHAIN, because the gimplifier doesn't handle
    it.  */
@@ -557,7 +552,6 @@ go_localize_identifier (const char *ident)
 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
 #undef LANG_HOOKS_PUSHDECL
 #undef LANG_HOOKS_GETDECLS
-#undef LANG_HOOKS_WRITE_GLOBALS
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #undef LANG_HOOKS_EH_PERSONALITY
 
@@ -574,7 +568,6 @@ go_localize_identifier (const char *ident)
 #define LANG_HOOKS_GLOBAL_BINDINGS_P   go_langhook_global_bindings_p
 #define LANG_HOOKS_PUSHDECL            go_langhook_pushdecl
 #define LANG_HOOKS_GETDECLS            go_langhook_getdecls
-#define LANG_HOOKS_WRITE_GLOBALS       go_langhook_write_globals
 #define LANG_HOOKS_GIMPLIFY_EXPR       go_langhook_gimplify_expr
 #define LANG_HOOKS_EH_PERSONALITY      go_langhook_eh_personality
 
index b3eceff196e84e01945039522e547a3104948088..da39d1fb0e96bbe1bbd55bae9775898bd5fd3209 100644 (file)
@@ -511,13 +511,19 @@ go_function_decl (tree decl)
   go_decl (decl);
 }
 
+static void
+go_early_global_decl (tree decl)
+{
+  go_decl (decl);
+  real_debug_hooks->early_global_decl (decl);
+}
+
 /* A global variable decl.  */
 
 static void
-go_global_decl (tree decl)
+go_late_global_decl (tree decl)
 {
-  real_debug_hooks->global_decl (decl);
-  go_decl (decl);
+  real_debug_hooks->late_global_decl (decl);
 }
 
 /* A type declaration.  */
@@ -1457,7 +1463,8 @@ dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
   go_debug_hooks.define = go_define;
   go_debug_hooks.undef = go_undef;
   go_debug_hooks.function_decl = go_function_decl;
-  go_debug_hooks.global_decl = go_global_decl;
+  go_debug_hooks.early_global_decl = go_early_global_decl;
+  go_debug_hooks.late_global_decl = go_late_global_decl;
   go_debug_hooks.type_decl = go_type_decl;
 
   macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
index fd9e2b1dda7f3f5db839367eaf009d9c2f09de21..ebd3f178f4a7485610b203a65efc217868f25330 100644 (file)
@@ -1,3 +1,15 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * class.c: Remove pending_static_fields.
+       (add_field): Remove use of pending_static_fields.
+       (java_write_globals): Remove.
+       * decl.c (java_mark_class_local): Remove use of
+       pending_static_fields.
+       * java-tree.h: Remove pending_static_fields and
+       java_write_globals.
+       * jcf-parse.c (java_parse_file): Call global_decl_processing.
+       * lang.c (LANG_HOOKS_WRITE_GLOBALS): Remove.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * boehm.c: Adjust includes for restructured coretypes.h.
index 54aea3c4be0378309b930220de20c18c320653fe..1d66c7250cd14e7cf71d9ba085c96cce0aa4d6a3 100644 (file)
@@ -120,10 +120,6 @@ static GTY(()) vec<tree, va_gc> *registered_class;
    currently being compiled.  */
 static GTY(()) tree this_classdollar;
 
-/* A list of static class fields.  This is to emit proper debug
-   info for them.  */
-vec<tree, va_gc> *pending_static_fields;
-
 /* Return the node that most closely represents the class whose name
    is IDENT.  Start the search from NODE (followed by its siblings).
    Return NULL if an appropriate node does not exist.  */
@@ -892,8 +888,6 @@ add_field (tree klass, tree name, tree field_type, int flags)
       /* Considered external unless we are compiling it into this
         object file.  */
       DECL_EXTERNAL (field) = (is_compiled_class (klass) != 2);
-      if (!DECL_EXTERNAL (field))
-       vec_safe_push (pending_static_fields, field);
     }
 
   return field;
@@ -3270,17 +3264,4 @@ in_same_package (tree name1, tree name2)
   return (pkg1 == pkg2);
 }
 
-/* lang_hooks.decls.final_write_globals: perform final processing on
-   global variables.  */
-
-void
-java_write_globals (void)
-{
-  tree *vec = vec_safe_address (pending_static_fields);
-  int len = vec_safe_length (pending_static_fields);
-  write_global_declarations ();
-  emit_debug_global_declarations (vec, len);
-  vec_free (pending_static_fields);
-}
-
 #include "gt-java-class.h"
index 8a2c66d15697014a16298b2b84746d5743ddf4e5..de75eb6d94e536f15a82bca370a6554478652d6e 100644 (file)
@@ -1967,11 +1967,7 @@ java_mark_class_local (tree klass)
 
   for (t = TYPE_FIELDS (klass); t ; t = DECL_CHAIN (t))
     if (FIELD_STATIC (t))
-      {
-       if (DECL_EXTERNAL (t))
-         vec_safe_push (pending_static_fields, t);
-       java_mark_decl_local (t);
-      }
+      java_mark_decl_local (t);
 
   for (t = TYPE_METHODS (klass); t ; t = DECL_CHAIN (t))
     if (!METHOD_ABSTRACT (t))
index 22c97893868a1ce5cf3de4229bd6e3ef1579d5f7..58a60b8c3a5d1a718c2df89c99f39ec54b992438 100644 (file)
@@ -1194,10 +1194,6 @@ extern void rewrite_reflection_indexes (void *);
 
 int cxx_keyword_p (const char *name, int length);
 
-extern GTY(()) vec<tree, va_gc> *pending_static_fields;
-
-extern void java_write_globals (void);   
-
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 
 /* Access flags etc for a method (a FUNCTION_DECL): */
index 038f7f8b8ac1ea8fd42fa037dcffbcfdaad69c7c..ba216a1672b70fd47c5c4880277b12791eb41868 100644 (file)
@@ -1996,6 +1996,9 @@ java_parse_file (void)
   /* Arrange for any necessary initialization to happen.  */
   java_emit_static_constructor ();
   gcc_assert (global_bindings_p ());
+
+  /* Do final processing on globals.  */
+  global_decl_processing ();
 }
 
 
index 8caa28ea723e5f455b1255c15b32941dd4940947..84b1680d5a82e27099175e774f8e9f60e58462b5 100644 (file)
@@ -146,8 +146,6 @@ struct GTY(()) language_function {
 #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name
 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
 #define LANG_HOOKS_PRINT_ERROR_FUNCTION        java_print_error_function
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS java_write_globals
 
 #undef LANG_HOOKS_TYPE_FOR_MODE
 #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode
index 303b4b60ee87657dcd83903525d80d3d56efdfd9..18ac84d9df3ed513ca3332ce504c679fdc32ca7c 100644 (file)
@@ -205,7 +205,7 @@ extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_tree_false
 #define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_tree_false
 #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
-#define LANG_HOOKS_WRITE_GLOBALS write_global_declarations
+#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
 #define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
 #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_const_tree_false
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing
@@ -230,7 +230,7 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
   LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
   LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
-  LANG_HOOKS_WRITE_GLOBALS, \
+  LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \
   LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
   LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \
   LANG_HOOKS_OMP_PREDETERMINED_SHARING, \
index a6824d375c8b9215b27804d7f422c29e423ddc83..a1fe9955370ede0f80d7a63d89c87f32dc22ceb2 100644 (file)
@@ -136,12 +136,12 @@ lhd_print_tree_nothing (FILE * ARG_UNUSED (file),
 {
 }
 
-/* Called from check_global_declarations.  */
+/* Called from check_global_declaration.  */
 
 bool
 lhd_warn_unused_global_decl (const_tree decl)
 {
-  /* This is what used to exist in check_global_declarations.  Probably
+  /* This is what used to exist in check_global_declaration.  Probably
      not many of these actually apply to non-C languages.  */
 
   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
@@ -308,14 +308,17 @@ lhd_decl_ok_for_sibcall (const_tree decl ATTRIBUTE_UNUSED)
   return true;
 }
 
-/* lang_hooks.decls.final_write_globals: perform final processing on
-   global variables.  */
+/* Generic global declaration processing.  This is meant to be called
+   by the front-ends at the end of parsing.  C/C++ do their own thing,
+   but other front-ends may call this.  */
+
 void
-write_global_declarations (void)
+global_decl_processing (void)
 {
   tree globals, decl, *vec;
   int len, i;
 
+  timevar_stop (TV_PHASE_PARSING);
   timevar_start (TV_PHASE_DEFERRED);
   /* Really define vars that have had only a tentative definition.
      Really output inline functions that must actually be callable
@@ -332,20 +335,9 @@ write_global_declarations (void)
     vec[len - i - 1] = decl;
 
   wrapup_global_declarations (vec, len);
-  check_global_declarations (vec, len);
   timevar_stop (TV_PHASE_DEFERRED);
 
-  timevar_start (TV_PHASE_OPT_GEN);
-  /* This lang hook is dual-purposed, and also finalizes the
-     compilation unit.  */
-  symtab->finalize_compilation_unit ();
-  timevar_stop (TV_PHASE_OPT_GEN);
-
-  timevar_start (TV_PHASE_DBGINFO);
-  emit_debug_global_declarations (vec, len);
-  timevar_stop (TV_PHASE_DBGINFO);
-
-  /* Clean up.  */
+  timevar_start (TV_PHASE_PARSING);
   free (vec);
 }
 
index 4039e8f737edf3d679411f2105d8fb6c3318d94d..d8d01fa3b87b59f85927a3bf246e948b0d8c8f3b 100644 (file)
@@ -184,9 +184,11 @@ struct lang_hooks_for_decls
      We will already have checked that it has static binding.  */
   bool (*warn_unused_global) (const_tree);
 
-  /* Obtain a list of globals and do final output on them at end
-     of compilation */
-  void (*final_write_globals) (void);
+  /* Perform any post compilation-proper parser cleanups and
+     processing.  This is currently only needed for the C++ parser,
+     which hopefully can be cleaned up so this hook is no longer
+     necessary.  */
+  void (*post_compilation_parsing_cleanups) (void);
 
   /* True if this decl may be called via a sibcall.  */
   bool (*ok_for_sibcall) (const_tree);
index 384421189695cb9cdaa47584e2df062e8ee3c3bd..5ba6a4f9de9c7a4e5d6cecd392e125917cb9694c 100644 (file)
@@ -1,3 +1,8 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * lto-lang.c (lto_write_globals): Remove.
+       (LANG_HOOKS_WRITE_GLOBALS): Same.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * lto-lang.c: Adjust includes for restructured coretypes.h.
index 5f20df5a386de884db360912774edf187e12e95f..e1d6b7f2bf966ca0ce82d0c1756db344c04cb229 100644 (file)
@@ -1113,19 +1113,6 @@ lto_getdecls (void)
   return NULL_TREE;
 }
 
-static void
-lto_write_globals (void)
-{
-  if (flag_wpa)
-    return;
-
-  /* Output debug info for global variables.  */  
-  varpool_node *vnode;
-  FOR_EACH_DEFINED_VARIABLE (vnode)
-    if (!decl_function_context (vnode->decl))
-      debug_hooks->global_decl (vnode->decl);
-}
-
 static tree
 lto_builtin_function (tree decl)
 {
@@ -1331,8 +1318,6 @@ static void lto_init_ts (void)
 #define LANG_HOOKS_PUSHDECL lto_pushdecl
 #undef LANG_HOOKS_GETDECLS
 #define LANG_HOOKS_GETDECLS lto_getdecls
-#undef LANG_HOOKS_WRITE_GLOBALS
-#define LANG_HOOKS_WRITE_GLOBALS lto_write_globals
 #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lto_register_builtin_type
 #undef LANG_HOOKS_BUILTIN_FUNCTION
index 4936900ecc07a34b27048e857f1b4a53936181e3..03327a52703767f569c0b859a76cfb1078e06e43 100644 (file)
@@ -1,3 +1,9 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * objc-act.c (objc_write_global_declarations): Adjust comment.
+       * objc-gnu-runtime-abi-01.c (build_selector_table_decl): Set
+       TREE_USED bit.
+
 2015-06-04  Andrew MacLeod  <amacleod@redhat.com>
 
        * objc-act.c: Adjust includes for restructured coretypes.h.
index 1d343ebce1f36493abe240aabba1ec40cb033b4b..f42f67993c81fc1733af81632d5090ba28edcb91 100644 (file)
@@ -435,8 +435,7 @@ objc_init (void)
   return true;
 }
 
-/* This is called automatically (at the very end of compilation) by
-   c_write_global_declarations and cp_write_global_declarations.  */
+/* This is called at the end of parsing by the C/C++ parsers.  */
 void
 objc_write_global_declarations (void)
 {
index 7352c21837bf66a2baf8dca4503e7674509e2f3e..6986645d60dc003201abe83d244a29498e5be7e9 100644 (file)
@@ -497,6 +497,8 @@ build_selector_table_decl (void)
   temp = build_array_type (objc_selector_template, NULL_TREE);
 
   UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
+  /* Squash `defined but not used' warning check_global_declaration.  */
+  TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
   OBJCMETA (UOBJC_SELECTOR_TABLE_decl, objc_meta, meta_base);
 }
 
index 1ba56bdc617bae2d1f426b4216e94a82d64c52d1..720e6471e7408175f7308f374b9b4db4f350a395 100644 (file)
@@ -288,6 +288,56 @@ rest_of_decl_compilation (tree decl,
   else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
           && TREE_STATIC (decl))
     varpool_node::get_create (decl);
+
+  /* Generate early debug for global variables.  Any local variables will
+     be handled by either handling reachable functions from
+     finalize_compilation_unit (and by consequence, locally scoped
+     symbols), or by rest_of_type_compilation below.
+
+     Also, pick up function prototypes, which will be mostly ignored
+     by the different early_global_decl() hooks, but will at least be
+     used by Go's hijack of the debug_hooks to implement
+     -fdump-go-spec.  */
+  if (!in_lto_p
+      && (TREE_CODE (decl) != FUNCTION_DECL
+         /* This will pick up function prototypes with no bodies,
+            which are not visible in finalize_compilation_unit()
+            while iterating with FOR_EACH_*_FUNCTION through the
+            symbol table.  */
+         || !DECL_SAVED_TREE (decl))
+
+      /* We need to check both decl_function_context and
+        current_function_decl here to make sure local extern
+        declarations end up with the correct context.
+
+        For local extern declarations, decl_function_context is
+        empty, but current_function_decl is set to the function where
+        the extern was declared .  Without the check for
+        !current_function_decl below, the local extern ends up
+        incorrectly with a top-level context.
+
+        For example:
+
+        namespace S
+        {
+          int
+          f()
+          {
+            {
+              int i = 42;
+              {
+                extern int i; // Local extern declaration.
+                return i;
+              }
+            }
+          }
+        }
+      */
+      && !decl_function_context (decl)
+      && !current_function_decl
+
+      && !decl_type_context (decl))
+    (*debug_hooks->early_global_decl) (decl);
 }
 
 /* Called after finishing a record, union or enumeral type.  */
index 575113422ba75c4145437acd588c7a0ff0986576..15d0805e230e5490d6c4eeb8390c448ba397236e 100644 (file)
@@ -125,7 +125,8 @@ static void sdbout_begin_block              (unsigned int, unsigned int);
 static void sdbout_end_block           (unsigned int, unsigned int);
 static void sdbout_source_line         (unsigned int, const char *, int, bool);
 static void sdbout_end_epilogue                (unsigned int, const char *);
-static void sdbout_global_decl         (tree);
+static void sdbout_early_global_decl   (tree);
+static void sdbout_late_global_decl    (tree);
 static void sdbout_begin_prologue      (unsigned int, const char *);
 static void sdbout_end_prologue                (unsigned int, const char *);
 static void sdbout_begin_function      (tree);
@@ -148,7 +149,6 @@ static void sdbout_field_types              (tree);
 static void sdbout_one_type            (tree);
 static void sdbout_parms               (tree);
 static void sdbout_reg_parms           (tree);
-static void sdbout_global_decl         (tree);
 
 /* Random macros describing parts of SDB data.  */
 
@@ -285,6 +285,7 @@ const struct gcc_debug_hooks sdb_debug_hooks =
 {
   sdbout_init,                          /* init */
   sdbout_finish,                        /* finish */
+  debug_nothing_void,                   /* early_finish */
   debug_nothing_void,                   /* assembly_start */
   debug_nothing_int_charstar,           /* define */
   debug_nothing_int_charstar,           /* undef */
@@ -301,7 +302,8 @@ const struct gcc_debug_hooks sdb_debug_hooks =
   sdbout_begin_function,                /* begin_function */
   sdbout_end_function,                  /* end_function */
   debug_nothing_tree,                   /* function_decl */
-  sdbout_global_decl,                   /* global_decl */
+  sdbout_early_global_decl,             /* early_global_decl */
+  sdbout_late_global_decl,              /* late_global_decl */
   sdbout_symbol,                        /* type_decl */
   debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
   debug_nothing_tree,                   /* deferred_inline_function */
@@ -1427,11 +1429,20 @@ sdbout_reg_parms (tree parms)
       }
 }
 
-/* Output debug information for a global DECL.  Called from toplev.c
-   after compilation proper has finished.  */
+/* Output early debug information for a global DECL.  Called from
+   rest_of_decl_compilation during parsing.  */
 
 static void
-sdbout_global_decl (tree decl)
+sdbout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+{
+  /* NYI for non-dwarf.  */
+}
+
+/* Output late debug information for a global DECL after location
+   information is available.  */
+
+static void
+sdbout_late_global_decl (tree decl)
 {
   if (TREE_CODE (decl) == VAR_DECL
       && !DECL_EXTERNAL (decl)
index e96238344096bd08b04c2f31492876baf36f5941..334d4091be8d7fc2bfb8116e8d5787222e05f32d 100644 (file)
@@ -1,3 +1,20 @@
+2015-06-05  Aldy Hernandez  <aldyh@redhat.com>
+
+       * g++.dg/cpp0x/pr57101.C: Add warning.
+       * g++.dg/debug/dwarf2/dwarf4-typedef.C: Same.
+       * g++.dg/ext/visibility/anon7.C: Same.
+       * g++.dg/ipa/pr63587-2.C: Same.
+       * g++.dg/opt/dump1.C: Same.
+       * g++.dg/opt/pr59622-3.C: Same.
+       * g++.dg/opt/pr59622.C: Same.
+       * g++.dg/torture/pr46383.C: Same.
+       * gcc.dg/dfp/pragma-float-const-decimal64-8.c: Same.
+       * g++.dg/debug/dwarf2/auto1.C: Adjust for early dwarf.
+       * g++.dg/lto/pr65549_0.C: Add { } to used but never defined
+       functions.
+       * gfortran.dg/intent_out_8.f90: Same.
+       * gfortran.dg/warn_target_lifetime_3.f90: Same.
+
 2015-06-05  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/66377
index c0fc966272cc1e21de1f46f5e22bcc9ce8ed3b88..1db444e22ef43a4f442ece52722d250e4e07aa6c 100644 (file)
@@ -160,7 +160,7 @@ namespace std
     typedef _Alloc allocator_type;
     template < typename _Key_compare > struct _Rb_tree_impl
     {
-      _Rb_tree_impl (_Key_compare, _Node_allocator);
+      _Rb_tree_impl (_Key_compare, _Node_allocator); // { dg-warning "used but never defined" }
     };
     _Rb_tree_impl < _Compare > _M_impl;
   _Rb_tree (_Compare __comp, allocator_type __a):
index e38334bd23bbefd3bcd690253ed43f5314a57cac..c04e923d8b6eb5db34970f695bbb2c39f9a45053 100644 (file)
 // .uleb128 0x5    # (DIE (0x4c) DW_TAG_unspecified_type)
 // .long   .LASF6  # DW_AT_name: "auto"
 //...
+// .uleb128 0x9    # (DIE (0x87) DW_TAG_base_type)
+// .ascii "int\0"  # DW_AT_name
+//...
 // .uleb128 0x7    # (DIE (0x57) DW_TAG_subprogram)
 // .long   0x33    # DW_AT_specification
 // .long   0x87    # DW_AT_type
-//...
-// .uleb128 0x9    # (DIE (0x87) DW_TAG_base_type)
-// .ascii "int\0"  # DW_AT_name
 
-// { dg-final { scan-assembler "a1.*(0x\[0-9a-f]+)\[^\n\r]*DW_AT_type.*\\1. DW_TAG_unspecified_type.*DW_AT_specification\[\n\r]{1,2}\[^\n\r]*(0x\[0-9a-f]+)\[^\n\r]*DW_AT_type.*\\2. DW_TAG_base_type" } }
+// { dg-final { scan-assembler "a1.*(0x\[0-9a-f]+)\[^\n\r]*DW_AT_type.*\\1. DW_TAG_unspecified_type.*(0x\[0-9a-f]+). DW_TAG_base_type.*DW_AT_specification\[\n\r]{1,2}\[^\n\r]*\\2\[^\n\r]*DW_AT_type" } }
 
 struct A
 {
index 89a6bb44e10beb40464e122e80bc1dc7e45a44ff..cd1a0afe8680999dc60fa7586f0d107f1782a086 100644 (file)
@@ -6,7 +6,7 @@
 namespace {
 
 struct A {
-  virtual ~A();
+  virtual ~A(); // { dg-warning "used but never defined" }
 };
 
 struct B : public A {
index 0c42ea866f9bcc09ceecb5d25a9ac60dcd505bc6..1aa239e922a044a5bb1e674b847a5fd6f1eca318 100644 (file)
@@ -4,7 +4,7 @@
 namespace
 {
   struct A {
-    static int bar ();
+    static int bar ();         // { dg-error "used but never defined" "" }
     static int i;              // { dg-error "used, but not defined" "" { xfail *-*-* } }
     static int j;
     static int k;
index f31c5bdee44623ac69843daa718c30c1d46d1b52..a15f17e7ca335a4433b1ae892d5a92c31b1df1de 100644 (file)
@@ -178,7 +178,7 @@ public:
   }
 };
 template <typename AttributeValueT>
-attribute_actor<AttributeValueT> attr (attribute_name);
+attribute_actor<AttributeValueT> attr (attribute_name); // { dg-warning "used but never defined" }
 terminal<>::type stream;
 template <typename LeftT, typename ImplT> class attribute_output_terminal
 {
index 4c6358dc7b90d049689da9556ba9655338f376b0..889cc994a58fdd30d9af6b8811bd062106a6ded2 100644 (file)
@@ -25,7 +25,7 @@ struct C<_Functor(_ArgTypes...)>
                            typename remove_reference<_Functor>::type>::value,
                        _Functor> {};
 template <typename _Tp> using result_of_t = typename C<_Tp>::type;
-template <typename> void forward();
+template <typename> void forward() { }
 template <typename _Tp> _Tp move(_Tp) {}
 namespace __cxx11 {
 class basic_string typedef string;
@@ -119,7 +119,7 @@ class H {
   template <typename Func> void schedule(Func func) {
     G __trans_tmp_1;
     struct task_with_ready_state {
-      task_with_ready_state(Func, G);
+      task_with_ready_state(Func, G) { };
     };
     std::make_unique<task_with_ready_state>(std::move(func), __trans_tmp_1);
     _promise->schedule(std::move(func));
index d263f18e99fd848abfe6e1b1fdeaa74b1d00fddf..f74d0247832d871c9b3ac8f458eb04af3dc69f36 100644 (file)
@@ -311,7 +311,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
     typename __add_ref<
                       typename tuple_element<__i, tuple<_Elements...>>::type
                     >::type
-    get(tuple<_Elements...>& __t) noexcept;
+    get(tuple<_Elements...>& __t) noexcept; // { dg-warning "used but never defined" }
   template<std::size_t... _Indexes>
     struct _Index_tuple
     {};
@@ -386,7 +386,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
     };
   template<typename _Callable, typename... _Args>
     typename _Bind_simple_helper<_Callable, _Args...>::__type
-    __bind_simple(_Callable&& __callable, _Args&&... __args)
+    __bind_simple(_Callable&& __callable, _Args&&... __args)  // { dg-warning "used but never defined" }
   ;
   union _Any_data
   ;
@@ -403,7 +403,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
       {
       protected:
  static _Functor*
- _M_get_pointer(const _Any_data& __source)
+ _M_get_pointer(const _Any_data& __source)  // { dg-warning "used but never defined" }
  ;
       };
   };
@@ -510,7 +510,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
         _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
  { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
       static pointer
-      allocate(_Alloc& __a, size_type __n)
+      allocate(_Alloc& __a, size_type __n)  // { dg-warning "used but never defined" }
       ;
       template<typename _Tp, typename... _Args>
  static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
index 0af86050c23a4111c48918e801dbbbbb33d4d686..94d66aafe6b3140ccc4fb4ddf3922cabc1ad5f57 100644 (file)
@@ -8,7 +8,7 @@ namespace
 {
   struct A
   {
-    virtual C foo ();
+    virtual C foo (); // { dg-warning "used but never defined" }
     C bar () { return foo (); }
   };
 }
index 1d8e9986c51f2d7a1bd40dcf26c5430b77d49b0e..f62cf41242d72445317fbd8f76d2914f670a768a 100644 (file)
@@ -6,7 +6,7 @@ namespace
 {
   struct A
   {
-    virtual int foo ();
+    virtual int foo (); // { dg-warning "used but never defined" }
     int bar () { return foo (); }
   };
 }
index 2b610394bdeb2faf4b3fa955cf0cf008969e7c84..e4810c5ada87040949cc7e49de46f4b3a7a57049 100644 (file)
@@ -69,9 +69,9 @@ template < class Tr, class Derived, class Element, class Previous, class Triangu
   Mesher_level(Previous_level& previous)
     : previous_level(previous)
   { }
-  Vertex_handle insert(Point p, Zone& z) ;
-  Zone conflicts_zone(const Point& p, Element e) ;
-  Element get_next_element() ;
+  Vertex_handle insert(Point p, Zone& z) ; // { dg-warning "used but never defined" }
+  Zone conflicts_zone(const Point& p, Element e) ; // { dg-warning "used but never defined" }
+  Element get_next_element() ; // { dg-warning "used but never defined" }
   template <class Mesh_visitor> void before_insertion(Element& e, const Point& p, Zone& zone, Mesh_visitor visitor) {
     visitor.before_insertion(e, p, zone);
   }
@@ -171,7 +171,7 @@ template <typename Tr> struct Triangulation_mesher_level_traits_3
       tr.is_infinite(f) ;
       new_facet<false>(f);
     }
-    template <bool remove_from_complex_if_not_in_restricted_Delaunay> void new_facet (const Facet& f) ;
+    template <bool remove_from_complex_if_not_in_restricted_Delaunay> void new_facet (const Facet& f) ; // { dg-warning "used but never defined" }
     void after_insertion_handle_opposite_facet (const Facet& f) {
       after_insertion_handle_incident_facet (f);
     }
index 39d38c1d8f0f95d843bc0582e0d4b804753f09eb..a54c9008b9f2de2f7287c83a0a9a57180700c0d9 100644 (file)
@@ -145,7 +145,7 @@ here:
 double
 f10 (void)
 {
-  void foo10 (void)
+  void foo10 (void) /* { dg-warning "defined but not used" } */
   {
     a = 1.0;
   }
index 674d8338bfaacc8e3677c0c4f8a1761a11a17df1..6360314dd2cce7db045636336ed3ca8a95114baa 100644 (file)
@@ -10,7 +10,7 @@ end type t
 
 contains
 
-  subroutine foo(x)
+  subroutine foo(x)             ! { dg-warning "defined but not used" }
     type(t), intent(out) :: x
   end subroutine
 
index 9113a885fa6b4f4b0e511815ee12dbd0201f77ae..6c8ea5b945834126a88b46704b2f3729ad6c1869 100644 (file)
@@ -10,7 +10,7 @@ subroutine test
   integer, target :: t
   p => t
 contains
-  subroutine sub()
+  subroutine sub()               ! { dg-warning "defined but not used" }
     if (p /= 0) return
   end subroutine
 end subroutine
@@ -22,7 +22,7 @@ contains
     integer, target :: t2
     p2 => t2 ! { dg-warning "Pointer at .1. in pointer assignment might outlive the pointer target" }
   contains
-    subroutine sub()
+    subroutine sub()             ! { dg-warning "defined but not used" }
       if (p2 /= 0) return
     end subroutine
   end subroutine
index cf8f37dd1e0bfb71232a72c5b51e7aa572fb1ae8..efac4b791ad19b0e558705f254b658fcb8671f96 100644 (file)
 
 /* The total execution time.  */
 DEFTIMEVAR (TV_TOTAL                 , "total time")
-/* The compiler phases.  These must be mutually exclusive.
-   Ideally, they would sum to near the total time.  */
+/* The compiler phases.
+
+   These must be mutually exclusive, and the NAME field must begin
+   with "phase".
+
+   Also, their sum must be within a millionth of the total time (see
+   validate_phases).  */
 DEFTIMEVAR (TV_PHASE_SETUP           , "phase setup")
 DEFTIMEVAR (TV_PHASE_PARSING         , "phase parsing")
 DEFTIMEVAR (TV_PHASE_DEFERRED        , "phase lang. deferred")
+DEFTIMEVAR (TV_PHASE_LATE_PARSING_CLEANUPS, "phase late parsing cleanups")
 DEFTIMEVAR (TV_PHASE_OPT_GEN         , "phase opt and generate")
 DEFTIMEVAR (TV_PHASE_DBGINFO         , "phase debug info")
 DEFTIMEVAR (TV_PHASE_CHECK_DBGINFO   , "phase check & debug info")
index f38fb32c0dbed9578601af66d73487ae58a367ea..fd2ac4e7f2ef12814d7f007fc0f160fab06a2b48 100644 (file)
@@ -492,15 +492,15 @@ wrapup_global_declarations (tree *vec, int len)
   return output_something;
 }
 
-/* A subroutine of check_global_declarations.  Issue appropriate warnings
-   for the global declaration DECL.  */
+/* Issue appropriate warnings for the global declaration DECL.  */
 
 void
-check_global_declaration_1 (tree decl)
+check_global_declaration (tree decl)
 {
   /* Warn about any function declared static but not defined.  We don't
      warn about variables, because many programs have static variables
      that exist only to get some text into the object file.  */
+  symtab_node *snode = symtab_node::get (decl);
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_INITIAL (decl) == 0
       && DECL_EXTERNAL (decl)
@@ -508,9 +508,9 @@ check_global_declaration_1 (tree decl)
       && ! TREE_NO_WARNING (decl)
       && ! TREE_PUBLIC (decl)
       && (warn_unused_function
-         || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+         || snode->referred_to_p (/*include_self=*/false)))
     {
-      if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+      if (snode->referred_to_p (/*include_self=*/false))
        pedwarn (input_location, 0, "%q+F used but never defined", decl);
       else
        warning (OPT_Wunused_function, "%q+F declared %<static%> but never defined", decl);
@@ -525,6 +525,10 @@ check_global_declaration_1 (tree decl)
        || (warn_unused_variable
           && TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
       && ! DECL_IN_SYSTEM_HEADER (decl)
+      && ! snode->referred_to_p (/*include_self=*/false)
+      /* This TREE_USED check is needed in addition to referred_to_p
+        above, because the `__unused__' attribute is not being
+        considered for referred_to_p.  */
       && ! TREE_USED (decl)
       /* The TREE_USED bit for file-scope decls is kept in the identifier,
         to handle multiple external decls in different scopes.  */
@@ -535,6 +539,10 @@ check_global_declaration_1 (tree decl)
       && ! TREE_THIS_VOLATILE (decl)
       /* Global register variables must be declared to reserve them.  */
       && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+      /* Global ctors and dtors are called by the runtime.  */
+      && (TREE_CODE (decl) != FUNCTION_DECL
+         || (!DECL_STATIC_CONSTRUCTOR (decl)
+             && !DECL_STATIC_DESTRUCTOR (decl)))
       /* Otherwise, ask the language.  */
       && lang_hooks.decls.warn_unused_global (decl))
     warning ((TREE_CODE (decl) == FUNCTION_DECL)
@@ -543,38 +551,6 @@ check_global_declaration_1 (tree decl)
             "%q+D defined but not used", decl);
 }
 
-/* Issue appropriate warnings for the global declarations in V (of
-   which there are LEN).  */
-
-void
-check_global_declarations (tree *v, int len)
-{
-  int i;
-
-  for (i = 0; i < len; i++)
-    check_global_declaration_1 (v[i]);
-}
-
-/* Emit debugging information for all global declarations in VEC.  */
-
-void
-emit_debug_global_declarations (tree *vec, int len)
-{
-  int i;
-
-  /* Avoid confusing the debug information machinery when there are errors.  */
-  if (seen_error ())
-    return;
-  /* No need for debug info in object files when producing slimLTO.  */
-  if (!in_lto_p && flag_lto && !flag_fat_lto_objects)
-    return;
-
-  timevar_push (TV_SYMOUT);
-  for (i = 0; i < len; i++)
-    debug_hooks->global_decl (vec[i]);
-  timevar_pop (TV_SYMOUT);
-}
-
 /* Compile an entire translation unit.  Write a file of assembly
    output and various debugging dumps.  */
 
@@ -584,8 +560,7 @@ compile_file (void)
   timevar_start (TV_PHASE_PARSING);
   timevar_push (TV_PARSE_GLOBAL);
 
-  /* Call the parser, which parses the entire file (calling
-     rest_of_compilation for each function).  */
+  /* Parse entire file and generate initial debug information.  */
   lang_hooks.parse_file ();
 
   timevar_pop (TV_PARSE_GLOBAL);
@@ -602,12 +577,33 @@ compile_file (void)
 
   ggc_protect_identifiers = false;
 
-  /* This must also call finalize_compilation_unit.  */
-  lang_hooks.decls.final_write_globals ();
+  /* Run the actual compilation process.  */
+  if (!in_lto_p)
+    {
+      timevar_start (TV_PHASE_OPT_GEN);
+      symtab->finalize_compilation_unit ();
+      timevar_stop (TV_PHASE_OPT_GEN);
+    }
+
+  /* Perform any post compilation-proper parser cleanups and
+     processing.  This is currently only needed for the C++ parser,
+     which can be hopefully cleaned up so this hook is no longer
+     necessary.  */
+  if (lang_hooks.decls.post_compilation_parsing_cleanups)
+    lang_hooks.decls.post_compilation_parsing_cleanups ();
 
   if (seen_error ())
     return;
 
+  /* After the parser has generated debugging information, augment
+     this information with any new location/etc information that may
+     have become available after the compilation proper.  */
+  timevar_start (TV_PHASE_DBGINFO);
+  symtab_node *node;
+  FOR_EACH_DEFINED_SYMBOL (node)
+    debug_hooks->late_global_decl (node->decl);
+  timevar_stop (TV_PHASE_DBGINFO);
+
   timevar_start (TV_PHASE_LATE_ASM);
 
   /* Compilation unit is finalized.  When producing non-fat LTO object, we are
index 9527f76ac6e92ec55e17925b22dcf96b4c5c9643..3bddcbb147b2b6ae74133c6271ae8fc43ff0d4eb 100644 (file)
@@ -59,10 +59,9 @@ extern void announce_function (tree);
 extern void wrapup_global_declaration_1 (tree);
 extern bool wrapup_global_declaration_2 (tree);
 extern bool wrapup_global_declarations (tree *, int);
-extern void check_global_declaration_1 (tree);
-extern void check_global_declarations (tree *, int);
-extern void emit_debug_global_declarations (tree *, int);
-extern void write_global_declarations (void);
+extern void check_global_declaration (tree);
+
+extern void global_decl_processing (void);
 
 extern void dump_memory_report (bool);
 extern void dump_profile_report (void);
index 98c45c27ffbc11a50b66964a283fd30c0514a01d..c92b3ea8bd8cbb70dca5165f3cf0d74964549eab 100644 (file)
@@ -1093,6 +1093,7 @@ build_one_array (gswitch *swtch, int num, tree arr_index_type,
       DECL_IGNORED_P (decl) = 1;
       TREE_CONSTANT (decl) = 1;
       TREE_READONLY (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
       varpool_node::finalize_decl (decl);
 
       fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE,
index 4b184c729bf709b87d415cc567227d00140a7996..252f40cff8cdbaf086ccf2890b904dbcb2ac658c 100644 (file)
@@ -171,7 +171,8 @@ static void vmsdbgout_begin_epilogue (unsigned int, const char *);
 static void vmsdbgout_end_epilogue (unsigned int, const char *);
 static void vmsdbgout_begin_function (tree);
 static void vmsdbgout_decl (tree);
-static void vmsdbgout_global_decl (tree);
+static void vmsdbgout_early_global_decl (tree);
+static void vmsdbgout_late_global_decl (tree);
 static void vmsdbgout_type_decl (tree, int);
 static void vmsdbgout_abstract_function (tree);
 
@@ -180,6 +181,7 @@ static void vmsdbgout_abstract_function (tree);
 const struct gcc_debug_hooks vmsdbg_debug_hooks
 = {vmsdbgout_init,
    vmsdbgout_finish,
+   debug_nothing_void,
    vmsdbgout_assembly_start,
    vmsdbgout_define,
    vmsdbgout_undef,
@@ -195,8 +197,9 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
    vmsdbgout_end_epilogue,
    vmsdbgout_begin_function,
    vmsdbgout_end_function,
-   vmsdbgout_decl,
-   vmsdbgout_global_decl,
+   vmsdbgout_function_decl,
+   vmsdbgout_early_global_decl,
+   vmsdbgout_late_global_decl,
    vmsdbgout_type_decl,                  /* type_decl */
    debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
    debug_nothing_tree,           /* deferred_inline_function */
@@ -1509,7 +1512,7 @@ vmsdbgout_undef (unsigned int lineno, const char *buffer)
 /* Not implemented in VMS Debug.  */
 
 static void
-vmsdbgout_decl (tree decl)
+vmsdbgout_function_decl (tree decl)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
     (*dwarf2_debug_hooks.function_decl) (decl);
@@ -1518,10 +1521,19 @@ vmsdbgout_decl (tree decl)
 /* Not implemented in VMS Debug.  */
 
 static void
-vmsdbgout_global_decl (tree decl)
+vmsdbgout_early_global_decl (tree decl)
 {
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
-    (*dwarf2_debug_hooks.global_decl) (decl);
+    (*dwarf2_debug_hooks.early_global_decl) (decl);
+}
+
+/* Not implemented in VMS Debug.  */
+
+static void
+vmsdbgout_late_global_decl (tree decl)
+{
+  if (write_symbols == VMS_AND_DWARF2_DEBUG)
+    (*dwarf2_debug_hooks.late_global_decl) (decl);
 }
 
 /* Not implemented in VMS Debug.  */