aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2001-02-16 08:03:10 -0500
committerJason Merrill <jason@gcc.gnu.org>2001-02-16 08:03:10 -0500
commit1edf43d63f1f23b070786a1da29edbc63cdebae1 (patch)
tree5ae76ee139c95d2ba34d0cb6fa406f2f92e70519 /gcc
parenta901fa64045a73517d8c212740b57e8b7650f3ad (diff)
downloadgcc-1edf43d63f1f23b070786a1da29edbc63cdebae1.zip
gcc-1edf43d63f1f23b070786a1da29edbc63cdebae1.tar.gz
gcc-1edf43d63f1f23b070786a1da29edbc63cdebae1.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/c-decl.c13
-rw-r--r--gcc/dwarf2out.c45
-rw-r--r--gcc/dwarf2out.h1
-rw-r--r--gcc/integrate.c4
-rw-r--r--gcc/toplev.c18
-rw-r--r--gcc/toplev.h2
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 <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>
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;