OSDN Git Service

* dwarf2out.c (add_bound_info): Don't crash if SAVE_EXPR_RTL is
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Feb 2001 13:03:10 +0000 (13:03 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Feb 2001 13:03:10 +0000 (13:03 +0000)
        NULL.
        (gen_subprogram_die): Don't abort on seeing a second definition if
        the previous one was abstract.  Don't replace an abstract instance
        in the lookup table.

        * dwarf2out.c (dwarf2out_abstract_function): Rename from
        gen_abstract_function.
        * dwarf2out.h: Declare it.
        * toplev.c (note_outlining_of_inline_function): New fn.
        * toplev.h: Declare it.
        * integrate.c (output_inline_function): Call it.
        * c-decl.c (duplicate_decls): Call it when redefining an extern
        inline.  Don't inline the new defn.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39763 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/dwarf2out.c
gcc/dwarf2out.h
gcc/integrate.c
gcc/toplev.c
gcc/toplev.h

index 6e3517b..35ecb4b 100644 (file)
@@ -1,5 +1,20 @@
 2001-02-16  Jason Merrill  <jason@redhat.com>
 
+       * dwarf2out.c (add_bound_info): Don't crash if SAVE_EXPR_RTL is
+       NULL.
+       (gen_subprogram_die): Don't abort on seeing a second definition if 
+       the previous one was abstract.  Don't replace an abstract instance
+       in the lookup table.
+
+       * dwarf2out.c (dwarf2out_abstract_function): Rename from
+       gen_abstract_function.
+       * dwarf2out.h: Declare it.
+       * toplev.c (note_outlining_of_inline_function): New fn.
+       * toplev.h: Declare it.
+       * integrate.c (output_inline_function): Call it.
+       * c-decl.c (duplicate_decls): Call it when redefining an extern
+       inline.  Don't inline the new defn.
+
        * tree.h (BLOCK_CHAIN): Use BLOCK_CHECK.
 
 2001-02-16  Gerald Pfeifer  <pfeifer@dbai.tuwien.ac.at>
index f0d229d..a2118fd 100644 (file)
@@ -1928,6 +1928,19 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   /* For functions, static overrides non-static.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
+      /* If we're redefining a function previously defined as extern
+        inline, make sure we emit debug info for the inline before we
+        throw it away, in case it was inlined into a function that hasn't
+        been written out yet.  */
+      if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+       {
+         note_outlining_of_inline_function (olddecl);
+
+         /* The new defn must not be inline.
+            FIXME what about -finline-functions? */
+         DECL_INLINE (newdecl) = 0;
+       }
+
       TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
       /* This is since we don't automatically
         copy the attributes of NEWDECL into OLDDECL.  */
index fa62101..ed4970c 100644 (file)
@@ -3760,7 +3760,6 @@ static void init_file_table               PARAMS ((struct file_table *));
 static void add_incomplete_type                PARAMS ((tree));
 static void retry_incomplete_types     PARAMS ((void));
 static void gen_type_die_for_member    PARAMS ((tree, tree, dw_die_ref));
-static void gen_abstract_function      PARAMS ((tree));
 static rtx save_rtx                    PARAMS ((rtx));
 static void splice_child_die           PARAMS ((dw_die_ref, dw_die_ref));
 static int file_info_cmp               PARAMS ((const void *, const void *));
@@ -9014,8 +9013,8 @@ add_bound_info (subrange_die, bound_attr, bound)
         We assume that a MEM rtx is safe because gcc wouldn't put the
         value there unless it was going to be used repeatedly in the
         function, i.e. for cleanups.  */
-      if (! optimize || (SAVE_EXPR_RTL (bound)
-                        && GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
+      if (SAVE_EXPR_RTL (bound)
+         && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
        {
          register dw_die_ref ctx = lookup_decl_die (current_function_decl);
          register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
@@ -9320,7 +9319,7 @@ add_abstract_origin_attribute (die, origin)
        fn = TYPE_STUB_DECL (fn);
       fn = decl_function_context (fn);
       if (fn)
-       gen_abstract_function (fn);
+       dwarf2out_abstract_function (fn);
     }
 
   if (DECL_P (origin))
@@ -10022,8 +10021,8 @@ gen_type_die_for_member (type, member, context_die)
    of a function which we may later generate inlined and/or
    out-of-line instances of.  */
 
-static void
-gen_abstract_function (decl)
+void
+dwarf2out_abstract_function (decl)
      tree decl;
 {
   register dw_die_ref old_die = lookup_decl_die (decl);
@@ -10105,7 +10104,11 @@ gen_subprogram_die (decl, context_die)
       register unsigned file_index
        = lookup_filename (&decl_file_table, DECL_SOURCE_FILE (decl));
 
-      if (get_AT_flag (old_die, DW_AT_declaration) != 1)
+      if (!get_AT_flag (old_die, DW_AT_declaration)
+         /* We can have a normal definition following an inline one in the
+            case of redefinition of GNU C extern inlines.
+            It seems reasonable to use AT_specification in this case.  */
+         && !get_AT_unsigned (old_die, DW_AT_inline))
        {
          /* ??? This can happen if there is a bug in the program, for
             instance, if it has duplicate function definitions.  Ideally,
@@ -10175,15 +10178,17 @@ gen_subprogram_die (decl, context_die)
 
   if (declaration)
     {
-      if (! origin)
-       add_AT_flag (subr_die, DW_AT_declaration, 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.  */
-      if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl))
-       equate_decl_number_to_die (decl, subr_die);
+      if (!(old_die && get_AT_unsigned (old_die, DW_AT_inline)))
+       {
+         add_AT_flag (subr_die, DW_AT_declaration, 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.  */
+         if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl))
+           equate_decl_number_to_die (decl, subr_die);
+       }
     }
   else if (DECL_ABSTRACT (decl))
     {
@@ -10206,7 +10211,7 @@ gen_subprogram_die (decl, context_die)
     }
   else if (!DECL_EXTERNAL (decl))
     {
-      if (origin == NULL_TREE)
+      if (!(old_die && get_AT_unsigned (old_die, DW_AT_inline)))
        equate_decl_number_to_die (decl, subr_die);
 
       ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
@@ -10490,7 +10495,7 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
       /* Emit info for the abstract instance first, if we haven't yet.  */
-      gen_abstract_function (decl);
+      dwarf2out_abstract_function (decl);
 
       add_abstract_origin_attribute (subr_die, decl);
       ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
@@ -11265,12 +11270,12 @@ gen_decl_die (decl, context_die)
         emit info for the abstract instance and set up to refer to it.  */
       if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl)
          && ! class_scope_p (context_die)
-         /* gen_abstract_function won't emit a die if this is just a
+         /* dwarf2out_abstract_function won't emit a die if this is just a
             declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
             that case, because that works only if we have a die.  */
          && DECL_INITIAL (decl) != NULL_TREE)
        {
-         gen_abstract_function (decl);
+         dwarf2out_abstract_function (decl);
          set_decl_origin_self (decl);
        }
 
index bced6a6..a48dbf8 100644 (file)
@@ -39,4 +39,5 @@ extern void debug_dwarf                       PARAMS ((void));
 struct die_struct;
 extern void debug_dwarf_die            PARAMS ((struct die_struct *));
 extern void dwarf2out_set_demangle_name_func PARAMS ((const char *(*) (const char *)));
+extern void dwarf2out_abstract_function PARAMS ((tree));
 extern void dwarf2out_add_library_unit_info PARAMS ((const char *, const char *));
index 9f28a37..bcb3619 100644 (file)
@@ -2846,6 +2846,10 @@ output_inline_function (fndecl)
   if (f->no_debugging_symbols)
     write_symbols = NO_DEBUG;
 
+  /* Do any preparation, such as emitting abstract debug info for the inline
+     before it gets mangled by optimization.  */
+  note_outlining_of_inline_function (fndecl);
+
   /* Compile this function all the way down to assembly code.  */
   rest_of_compilation (fndecl);
 
index 3818998..6a00107 100644 (file)
@@ -2681,6 +2681,24 @@ note_deferral_of_defined_inline_function (decl)
 #endif
 }
 
+/* FNDECL is an inline function which is about to be emitted out of line.
+   Do any preparation, such as emitting abstract debug info for the inline
+   before it gets mangled by optimization.  */
+
+void
+note_outlining_of_inline_function (fndecl)
+     tree fndecl;
+{
+#ifdef DWARF2_DEBUGGING_INFO
+  /* The DWARF 2 backend tries to reduce debugging bloat by not emitting
+     the abstract description of inline functions until something tries to
+     reference them.  Force it out now, before optimizations mangle the
+     block tree.  */
+  if (write_symbols == DWARF2_DEBUG)
+    dwarf2out_abstract_function (fndecl);
+#endif
+}
+
 /* This is called from finish_function (within yyparse)
    after each top-level definition is parsed.
    It is supposed to compile that function or variable
index 233059a..dc36dd5 100644 (file)
@@ -128,6 +128,8 @@ extern int wrapup_global_declarations   PARAMS ((union tree_node **, int));
 extern void check_global_declarations   PARAMS ((union tree_node **, int));
 extern void note_deferral_of_defined_inline_function
                                        PARAMS ((union tree_node *));
+extern void note_outlining_of_inline_function
+                                       PARAMS ((union tree_node *));
 extern int errorcount;
 extern int warningcount;
 extern int sorrycount;