From 1edf43d63f1f23b070786a1da29edbc63cdebae1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 16 Feb 2001 08:03:10 -0500 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 +++++++++++++++ gcc/c-decl.c | 13 +++++++++++++ gcc/dwarf2out.c | 45 +++++++++++++++++++++++++-------------------- gcc/dwarf2out.h | 1 + gcc/integrate.c | 4 ++++ gcc/toplev.c | 18 ++++++++++++++++++ gcc/toplev.h | 2 ++ 7 files changed, 78 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6e3517b..35ecb4b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ 2001-02-16 Jason Merrill + * 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 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index f0d229d..a2118fd 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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. */ diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index fa62101..ed4970c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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); } diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index bced6a6..a48dbf8 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -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 *)); diff --git a/gcc/integrate.c b/gcc/integrate.c index 9f28a37..bcb3619 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -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); diff --git a/gcc/toplev.c b/gcc/toplev.c index 3818998..6a00107 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -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 diff --git a/gcc/toplev.h b/gcc/toplev.h index 233059a..dc36dd5 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -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; -- 2.7.4