diff options
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/c-decl.c | 38 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/class.c | 4 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/method.c | 2 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 9 | ||||
-rw-r--r-- | gcc/dbxout.c | 4 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 93 | ||||
-rw-r--r-- | gcc/dwarfout.c | 8 | ||||
-rw-r--r-- | gcc/integrate.c | 3 | ||||
-rw-r--r-- | gcc/toplev.c | 8 | ||||
-rw-r--r-- | gcc/tree.h | 8 |
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; @@ -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; |