aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/c-decl.c38
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/class.c4
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/cp/optimize.c9
-rw-r--r--gcc/dbxout.c4
-rw-r--r--gcc/dwarf2out.c93
-rw-r--r--gcc/dwarfout.c8
-rw-r--r--gcc/integrate.c3
-rw-r--r--gcc/toplev.c8
-rw-r--r--gcc/tree.h8
14 files changed, 151 insertions, 73 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f0ffdcc..57d50323 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,25 @@
+2001-02-21 Jason Merrill <jason@redhat.com>
+
+ * tree.h (DECL_UNINLINABLE): Move from C++ frontend.
+ (struct tree_decl): Add uninlinable bitfield.
+ * c-decl.c (duplicate_decls): Set it.
+ * integrate.c (function_cannot_inline_p): Check it.
+
+ * dwarf2out.c (add_name_and_src_coords_attributes): Don't add
+ DW_AT_MIPS_linkage_name to abstract methods.
+ (dwarf2out_abstract_function): Emit class context before calling
+ set_decl_abstract_flags. Don't clear DECL_ABSTRACT.
+ (gen_subprogram_die): Remove obsolete code.
+ (gen_member_die): Don't include clones in the member list.
+ (gen_decl_die): Emit abstract info for clone origin.
+ * dwarfout.c (output_type): Don't include clones in the member list.
+ * dbxout.c (dbxout_type_methods): Ignore abstract methods.
+ * toplev.c (note_deferral_of_defined_inline_function): Don't clear
+ DECL_ABSTRACT on a function that already has it set.
+
+ * dwarf2out.c (gen_formal_types_die): Also accept a FUNCTION_DECL.
+ (get_subprogram_die): Pass it in.
+
2001-02-21 Richard Earnshaw <rearnsha@arm.com>
* flow.c (mark_set_1): Make not_dead unsigned long. For
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index a2118fd..0f104a4 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1928,19 +1928,6 @@ 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. */
@@ -1974,12 +1961,27 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
- DECL_INLINE (olddecl) = 1;
+ /* 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);
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ /* The new defn must not be inline. */
+ DECL_INLINE (newdecl) = 0;
+ DECL_UNINLINABLE (newdecl) = 1;
+ }
+ else
+ {
+ /* If either decl says `inline', this fn is inline,
+ unless its definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
+ DECL_INLINE (olddecl) = 1;
+
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ }
if (DECL_BUILT_IN (olddecl))
{
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5387d68..9c0ad71 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2001-02-21 Jason Merrill <jason@redhat.com>
+
+ * cp-tree.h (struct lang_decl_flags): Remove uninlinable flag.
+ (DECL_UNINLINABLE): Move to middle-end.
+
+ * class.c (clone_function_decl): Set DECL_ABSTRACT on original fn.
+ * decl.c (duplicate_decls): Preserve DECL_ABSTRACT.
+ * class.c (build_clone): Set DECL_ABSTRACT_ORIGIN for the clone.
+ * optimize.c (maybe_clone_body): Set DECL_ABSTRACT_ORIGIN for the
+ parms and outer BLOCK. note_deferral_of_defined_inline_function.
+
+ * method.c (implicitly_declare_fn): Don't set DECL_ARTIFICIAL on
+ second parm of op=.
+
2001-02-19 Mark Mitchell <mark@codesourcery.com>
* decl2.c (set_decl_namespace): Allow explicit instantiations in
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 6752c90..2ba9e03 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4179,6 +4179,7 @@ build_clone (fn, name)
clone = copy_decl (fn);
/* Remember where this function came from. */
DECL_CLONED_FUNCTION (clone) = fn;
+ DECL_ABSTRACT_ORIGIN (clone) = fn;
/* Reset the function name. */
DECL_NAME (clone) = name;
DECL_ASSEMBLER_NAME (clone) = DECL_NAME (clone);
@@ -4339,6 +4340,9 @@ clone_function_decl (fn, update_method_vec_p)
if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
+
+ /* Note that this is an abstract function that is never emitted. */
+ DECL_ABSTRACT (fn) = 1;
}
/* For each of the constructors and destructors in T, create an
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f1e6df5..240832a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1811,7 +1811,7 @@ struct lang_decl_flags
unsigned static_function : 1;
unsigned pure_virtual : 1;
unsigned has_in_charge_parm_p : 1;
- unsigned uninlinable : 1;
+ unsigned has_vtt_parm_p : 1;
unsigned deferred : 1;
unsigned use_template : 2;
@@ -1828,7 +1828,7 @@ struct lang_decl_flags
unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
unsigned generate_with_vtable_p : 1;
- unsigned has_vtt_parm_p : 1;
+ /* One unused bit. */
union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
@@ -2469,10 +2469,6 @@ extern int flag_new_for_scope;
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp))
-/* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
-#define DECL_UNINLINABLE(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.uninlinable)
-
/* Returns non-zero if DECL has external linkage, as specified by the
language standard. (This predicate may hold even when the
corresponding entity is not actually given external linkage in the
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index af5ac8a..85e9fa6 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3626,6 +3626,9 @@ duplicate_decls (newdecl, olddecl)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ /* Preserve abstractness on cloned [cd]tors. */
+ DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
+
if (! types_match)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 349afcb..75e713d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1026,8 +1026,6 @@ implicitly_declare_fn (kind, type, const_p)
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 20000408);
- if (kind != sfk_constructor && kind != sfk_destructor)
- DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn))) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_THIS_INLINE (fn) = 1;
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 115b467..21c94ea 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -932,6 +932,9 @@ maybe_clone_body (fn)
&& !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
return 0;
+ /* Emit the DWARF1 abstract instance. */
+ note_deferral_of_defined_inline_function (fn);
+
/* We know that any clones immediately follow FN in the TYPE_METHODS
list. */
for (clone = TREE_CHAIN (fn);
@@ -996,6 +999,7 @@ maybe_clone_body (fn)
from the CLONE to this parameter. */
if (DECL_HAS_VTT_PARM_P (clone))
{
+ DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
splay_tree_insert (id.decl_map,
(splay_tree_key) parm,
(splay_tree_value) clone_parm);
@@ -1013,6 +1017,7 @@ maybe_clone_body (fn)
function. */
else
{
+ DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
splay_tree_insert (id.decl_map,
(splay_tree_key) parm,
(splay_tree_value) clone_parm);
@@ -1029,7 +1034,9 @@ maybe_clone_body (fn)
/* Now, expand this function into RTL, if appropriate. */
function_name_declared_p = 1;
- expand_body (finish_function (0));
+ finish_function (0);
+ BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
+ expand_body (clone);
pop_from_top_level ();
}
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 4c4a61a..05a95a4 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -841,7 +841,9 @@ dbxout_type_methods (type)
last = fndecl;
- if (DECL_IGNORED_P (fndecl))
+ /* Also ignore abstract methods; those are only interesting to
+ the DWARF backends. */
+ if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl))
continue;
if (flag_minimal_debug)
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ed4970c..ce3efaf 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -9390,7 +9390,8 @@ add_name_and_src_coords_attributes (die, decl)
if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
&& TREE_PUBLIC (decl)
- && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+ && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
+ && !DECL_ABSTRACT (decl))
add_AT_string (die, DW_AT_MIPS_linkage_name,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
}
@@ -9936,24 +9937,22 @@ gen_formal_types_die (function_or_method_type, context_die)
{
register tree link;
register tree formal_type = NULL;
- register tree first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
+ register tree first_parm_type;
+ tree arg;
-#if 0
- /* In the case where we are generating a formal types list for a C++
- non-static member function type, skip over the first thing on the
- TYPE_ARG_TYPES list because it only represents the type of the hidden
- `this pointer'. The debugger should be able to figure out (without
- being explicitly told) that this non-static member function type takes a
- `this pointer' and should be able to figure what the type of that hidden
- parameter is from the DW_AT_member attribute of the parent
- DW_TAG_subroutine_type DIE. */
- if (TREE_CODE (function_or_method_type) == METHOD_TYPE)
- first_parm_type = TREE_CHAIN (first_parm_type);
-#endif
+ if (TREE_CODE (function_or_method_type) == FUNCTION_DECL)
+ {
+ arg = DECL_ARGUMENTS (function_or_method_type);
+ function_or_method_type = TREE_TYPE (function_or_method_type);
+ }
+ else
+ arg = NULL_TREE;
+
+ first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
/* Make our first pass over the list of formal parameter types and output a
DW_TAG_formal_parameter DIE for each one. */
- for (link = first_parm_type; link; link = TREE_CHAIN (link))
+ for (link = first_parm_type; link; )
{
register dw_die_ref parm_die;
@@ -9963,9 +9962,14 @@ gen_formal_types_die (function_or_method_type, context_die)
/* Output a (nameless) DIE to represent the formal parameter itself. */
parm_die = gen_formal_parameter_die (formal_type, context_die);
- if (TREE_CODE (function_or_method_type) == METHOD_TYPE
- && link == first_parm_type)
+ if ((TREE_CODE (function_or_method_type) == METHOD_TYPE
+ && link == first_parm_type)
+ || (arg && DECL_ARTIFICIAL (arg)))
add_AT_flag (parm_die, DW_AT_artificial, 1);
+
+ link = TREE_CHAIN (link);
+ if (arg)
+ arg = TREE_CHAIN (arg);
}
/* If this function type has an ellipsis, add a
@@ -10025,19 +10029,34 @@ void
dwarf2out_abstract_function (decl)
tree decl;
{
- register dw_die_ref old_die = lookup_decl_die (decl);
+ register dw_die_ref old_die;
tree save_fn;
+ tree context;
+ int was_abstract = DECL_ABSTRACT (decl);
+
+ /* Make sure we have the actual abstract inline, not a clone. */
+ decl = DECL_ORIGIN (decl);
+ old_die = lookup_decl_die (decl);
if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
/* We've already generated the abstract instance. */
return;
+ /* Be sure we've emitted the in-class declaration DIE (if any) first, so
+ we don't get confused by DECL_ABSTRACT. */
+ context = decl_class_context (decl);
+ if (context)
+ gen_type_die_for_member
+ (context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
+
+ /* Pretend we've just finished compiling this function. */
save_fn = current_function_decl;
current_function_decl = decl;
set_decl_abstract_flags (decl, 1);
dwarf2out_decl (decl);
- set_decl_abstract_flags (decl, 0);
+ if (! was_abstract)
+ set_decl_abstract_flags (decl, 0);
current_function_decl = save_fn;
}
@@ -10088,17 +10107,6 @@ gen_subprogram_die (decl, context_die)
subr_die = new_die (DW_TAG_subprogram, context_die);
add_abstract_origin_attribute (subr_die, origin);
}
- else if (old_die && DECL_ABSTRACT (decl)
- && get_AT_unsigned (old_die, DW_AT_inline))
- {
- /* This must be a redefinition of an extern inline function.
- We can just reuse the old die here. */
- subr_die = old_die;
-
- /* Clear out the inlined attribute and parm types. */
- remove_AT (subr_die, DW_AT_inline);
- remove_children (subr_die);
- }
else if (old_die)
{
register unsigned file_index
@@ -10261,7 +10269,7 @@ gen_subprogram_die (decl, context_die)
if (debug_info_level <= DINFO_LEVEL_TERSE)
;
else if (declaration)
- gen_formal_types_die (TREE_TYPE (decl), subr_die);
+ gen_formal_types_die (decl, subr_die);
else
{
/* Generate DIEs to represent all known formal parameters */
@@ -10738,6 +10746,10 @@ gen_member_die (type, context_die)
/* Now output info about the function members (if any). */
for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member))
{
+ /* Don't include clones in the member list. */
+ if (DECL_ABSTRACT_ORIGIN (member))
+ continue;
+
child = lookup_decl_die (member);
if (child)
splice_child_die (context_die, child);
@@ -11266,20 +11278,23 @@ gen_decl_die (decl, context_die)
&& (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl)))
break;
+ /* If we're emitting a clone, emit info for the abstract instance. */
+ if (DECL_ORIGIN (decl) != decl)
+ dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl));
/* If we're emitting an out-of-line copy of an inline function,
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)
- /* 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)
+ else if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl)
+ && ! class_scope_p (context_die)
+ /* 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)
{
dwarf2out_abstract_function (decl);
set_decl_origin_self (decl);
}
-
- if (debug_info_level > DINFO_LEVEL_TERSE)
+ /* Otherwise we're emitting the primary DIE for this decl. */
+ else if (debug_info_level > DINFO_LEVEL_TERSE)
{
/* Before we describe the FUNCTION_DECL itself, make sure that we
have described its return type. */
diff --git a/gcc/dwarfout.c b/gcc/dwarfout.c
index 9c7cb47..370d14f 100644
--- a/gcc/dwarfout.c
+++ b/gcc/dwarfout.c
@@ -4444,7 +4444,13 @@ output_type (type, containing_scope)
for (func_member = TYPE_METHODS (type);
func_member;
func_member = TREE_CHAIN (func_member))
- output_decl (func_member, type);
+ {
+ /* Don't include clones in the member list. */
+ if (DECL_ABSTRACT_ORIGIN (func_member))
+ continue;
+
+ output_decl (func_member, type);
+ }
}
--in_class;
diff --git a/gcc/integrate.c b/gcc/integrate.c
index bcb3619..270a9c5 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -139,6 +139,9 @@ function_cannot_inline_p (fndecl)
register tree parms;
rtx result;
+ if (DECL_UNINLINABLE (fndecl))
+ return N_("function cannot be inline");
+
/* No inlines with varargs. */
if ((last && TREE_VALUE (last) != void_type_node)
|| current_function_varargs)
diff --git a/gcc/toplev.c b/gcc/toplev.c
index b76b6ba..0e592bc 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2661,19 +2661,23 @@ note_deferral_of_defined_inline_function (decl)
/* Generate the DWARF info for the "abstract" instance of a function
which we may later generate inlined and/or out-of-line instances
of. */
- if (write_symbols == DWARF_DEBUG && DECL_INLINE (decl))
+ if (write_symbols == DWARF_DEBUG
+ && (DECL_INLINE (decl) || DECL_ABSTRACT (decl))
+ && ! DECL_ABSTRACT_ORIGIN (decl))
{
/* The front-end may not have set CURRENT_FUNCTION_DECL, but the
DWARF code expects it to be set in this case. Intuitively,
DECL is the function we just finished defining, so setting
CURRENT_FUNCTION_DECL is sensible. */
tree saved_cfd = current_function_decl;
+ int was_abstract = DECL_ABSTRACT (decl);
current_function_decl = decl;
/* Let the DWARF code do its work. */
set_decl_abstract_flags (decl, 1);
dwarfout_file_scope_decl (decl, 0);
- set_decl_abstract_flags (decl, 0);
+ if (! was_abstract)
+ set_decl_abstract_flags (decl, 0);
/* Reset CURRENT_FUNCTION_DECL. */
current_function_decl = saved_cfd;
diff --git a/gcc/tree.h b/gcc/tree.h
index 60427b9..3d2e384 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -239,8 +239,6 @@ struct tree_common
INTEGER_TYPE, ENUMERAL_TYPE, FIELD_DECL
DECL_BUILT_IN_NONANSI in
FUNCTION_DECL
- TREE_PARMLIST in
- TREE_PARMLIST (C++)
SAVE_EXPR_NOPLACEHOLDER in
SAVE_EXPR
@@ -1461,6 +1459,9 @@ struct tree_type
where it is called. */
#define DECL_INLINE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inline_flag)
+/* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
+#define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable)
+
/* Nonzero in a FUNCTION_DECL means this is a built-in function
that is not specified by ansi C and that users are supposed to be allowed
to redefine for any purpose whatever. */
@@ -1632,7 +1633,8 @@ struct tree_decl
unsigned pointer_depth : 2;
unsigned non_addressable : 1;
unsigned user_align : 1;
- /* Three unused bits. */
+ unsigned uninlinable : 1;
+ /* Two unused bits. */
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;