Commit 1edf43d6 by Jason Merrill Committed by Jason Merrill

dwarf2out.c (add_bound_info): Don't crash if SAVE_EXPR_RTL is NULL.

        * 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.

From-SVN: r39763
parent a901fa64
2001-02-16 Jason Merrill <jason@redhat.com> 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. * tree.h (BLOCK_CHAIN): Use BLOCK_CHECK.
2001-02-16 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at> 2001-02-16 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
......
...@@ -1928,6 +1928,19 @@ duplicate_decls (newdecl, olddecl, different_binding_level) ...@@ -1928,6 +1928,19 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
/* For functions, static overrides non-static. */ /* For functions, static overrides non-static. */
if (TREE_CODE (newdecl) == FUNCTION_DECL) 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); TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
/* This is since we don't automatically /* This is since we don't automatically
copy the attributes of NEWDECL into OLDDECL. */ copy the attributes of NEWDECL into OLDDECL. */
......
...@@ -3760,7 +3760,6 @@ static void init_file_table PARAMS ((struct file_table *)); ...@@ -3760,7 +3760,6 @@ static void init_file_table PARAMS ((struct file_table *));
static void add_incomplete_type PARAMS ((tree)); static void add_incomplete_type PARAMS ((tree));
static void retry_incomplete_types PARAMS ((void)); static void retry_incomplete_types PARAMS ((void));
static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref)); 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 rtx save_rtx PARAMS ((rtx));
static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref)); static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref));
static int file_info_cmp PARAMS ((const void *, const void *)); static int file_info_cmp PARAMS ((const void *, const void *));
...@@ -9014,8 +9013,8 @@ add_bound_info (subrange_die, bound_attr, bound) ...@@ -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 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 value there unless it was going to be used repeatedly in the
function, i.e. for cleanups. */ function, i.e. for cleanups. */
if (! optimize || (SAVE_EXPR_RTL (bound) if (SAVE_EXPR_RTL (bound)
&& GET_CODE (SAVE_EXPR_RTL (bound)) == MEM)) && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM))
{ {
register dw_die_ref ctx = lookup_decl_die (current_function_decl); register dw_die_ref ctx = lookup_decl_die (current_function_decl);
register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx); register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx);
...@@ -9320,7 +9319,7 @@ add_abstract_origin_attribute (die, origin) ...@@ -9320,7 +9319,7 @@ add_abstract_origin_attribute (die, origin)
fn = TYPE_STUB_DECL (fn); fn = TYPE_STUB_DECL (fn);
fn = decl_function_context (fn); fn = decl_function_context (fn);
if (fn) if (fn)
gen_abstract_function (fn); dwarf2out_abstract_function (fn);
} }
if (DECL_P (origin)) if (DECL_P (origin))
...@@ -10022,8 +10021,8 @@ gen_type_die_for_member (type, member, context_die) ...@@ -10022,8 +10021,8 @@ gen_type_die_for_member (type, member, context_die)
of a function which we may later generate inlined and/or of a function which we may later generate inlined and/or
out-of-line instances of. */ out-of-line instances of. */
static void void
gen_abstract_function (decl) dwarf2out_abstract_function (decl)
tree decl; tree decl;
{ {
register dw_die_ref old_die = lookup_decl_die (decl); register dw_die_ref old_die = lookup_decl_die (decl);
...@@ -10105,7 +10104,11 @@ gen_subprogram_die (decl, context_die) ...@@ -10105,7 +10104,11 @@ gen_subprogram_die (decl, context_die)
register unsigned file_index register unsigned file_index
= lookup_filename (&decl_file_table, DECL_SOURCE_FILE (decl)); = 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 /* ??? This can happen if there is a bug in the program, for
instance, if it has duplicate function definitions. Ideally, instance, if it has duplicate function definitions. Ideally,
...@@ -10175,15 +10178,17 @@ gen_subprogram_die (decl, context_die) ...@@ -10175,15 +10178,17 @@ gen_subprogram_die (decl, context_die)
if (declaration) if (declaration)
{ {
if (! origin) if (!(old_die && get_AT_unsigned (old_die, DW_AT_inline)))
add_AT_flag (subr_die, DW_AT_declaration, 1); {
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 first time we see a member function, it is in the context of
the class first. The next time is the definition, which is the class to which it belongs. We make sure of this by emitting
handled above. The two may come from the same source text. */ the class first. The next time is the definition, which is
if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl)) handled above. The two may come from the same source text. */
equate_decl_number_to_die (decl, subr_die); if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl))
equate_decl_number_to_die (decl, subr_die);
}
} }
else if (DECL_ABSTRACT (decl)) else if (DECL_ABSTRACT (decl))
{ {
...@@ -10206,7 +10211,7 @@ gen_subprogram_die (decl, context_die) ...@@ -10206,7 +10211,7 @@ gen_subprogram_die (decl, context_die)
} }
else if (!DECL_EXTERNAL (decl)) 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); equate_decl_number_to_die (decl, subr_die);
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
...@@ -10490,7 +10495,7 @@ gen_inlined_subroutine_die (stmt, context_die, depth) ...@@ -10490,7 +10495,7 @@ gen_inlined_subroutine_die (stmt, context_die, depth)
char label[MAX_ARTIFICIAL_LABEL_BYTES]; char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Emit info for the abstract instance first, if we haven't yet. */ /* 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); add_abstract_origin_attribute (subr_die, decl);
ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
...@@ -11265,12 +11270,12 @@ gen_decl_die (decl, context_die) ...@@ -11265,12 +11270,12 @@ gen_decl_die (decl, context_die)
emit info for the abstract instance and set up to refer to it. */ emit info for the abstract instance and set up to refer to it. */
if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl) if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl)
&& ! class_scope_p (context_die) && ! 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 declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in
that case, because that works only if we have a die. */ that case, because that works only if we have a die. */
&& DECL_INITIAL (decl) != NULL_TREE) && DECL_INITIAL (decl) != NULL_TREE)
{ {
gen_abstract_function (decl); dwarf2out_abstract_function (decl);
set_decl_origin_self (decl); set_decl_origin_self (decl);
} }
......
...@@ -39,4 +39,5 @@ extern void debug_dwarf PARAMS ((void)); ...@@ -39,4 +39,5 @@ extern void debug_dwarf PARAMS ((void));
struct die_struct; struct die_struct;
extern void debug_dwarf_die PARAMS ((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_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 *)); extern void dwarf2out_add_library_unit_info PARAMS ((const char *, const char *));
...@@ -2846,6 +2846,10 @@ output_inline_function (fndecl) ...@@ -2846,6 +2846,10 @@ output_inline_function (fndecl)
if (f->no_debugging_symbols) if (f->no_debugging_symbols)
write_symbols = NO_DEBUG; 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. */ /* Compile this function all the way down to assembly code. */
rest_of_compilation (fndecl); rest_of_compilation (fndecl);
......
...@@ -2681,6 +2681,24 @@ note_deferral_of_defined_inline_function (decl) ...@@ -2681,6 +2681,24 @@ note_deferral_of_defined_inline_function (decl)
#endif #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) /* This is called from finish_function (within yyparse)
after each top-level definition is parsed. after each top-level definition is parsed.
It is supposed to compile that function or variable It is supposed to compile that function or variable
......
...@@ -128,6 +128,8 @@ extern int wrapup_global_declarations PARAMS ((union tree_node **, int)); ...@@ -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 check_global_declarations PARAMS ((union tree_node **, int));
extern void note_deferral_of_defined_inline_function extern void note_deferral_of_defined_inline_function
PARAMS ((union tree_node *)); PARAMS ((union tree_node *));
extern void note_outlining_of_inline_function
PARAMS ((union tree_node *));
extern int errorcount; extern int errorcount;
extern int warningcount; extern int warningcount;
extern int sorrycount; extern int sorrycount;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment