tree.h (DECL_UNINLINABLE): Move from C++ frontend.

* 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.
        * cp-tree.h (struct lang_decl_flags): Remove uninlinable flag.
        (DECL_UNINLINABLE): Move to middle-end.

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

        * dwarf2out.c (gen_formal_types_die): Also accept a FUNCTION_DECL.
        (get_subprogram_die): Pass it in.
        * method.c (implicitly_declare_fn): Don't set DECL_ARTIFICIAL on
        second parm of op=.

From-SVN: r39945
This commit is contained in:
Jason Merrill 2001-02-21 09:42:27 -05:00 committed by Jason Merrill
parent 3c88f36654
commit 5daf7c0a17
14 changed files with 151 additions and 73 deletions

View File

@ -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

View File

@ -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))
{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 ();
}

View File

@ -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)

View File

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

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;