From d40a19da1370ab4930788ede0a5c9e9171a16656 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 22 Sep 2009 20:20:03 +0000 Subject: [PATCH] re PR debug/41266 (Emit DW_TAG_template_parameter_pack and DW_TAG_formal_parameter_pack) Fix for PR debug/41266 ChangeLog: * include/dwarf2.h (enum dwarf_tag): Add DW_TAG_template_parameter_pack and DW_TAG_formal_parameter_pack. gcc/ChangeLog: * dwarf2out.c (template_parameter_pack_die, gen_formal_parameter_pack_die ): New functions. (make_ith_pack_parameter_name): Remove this function. (dwarf_tag_name): Support printing DW_TAG_template_parameter_pack and DW_TAG_formal_parameter_pack. (gen_generic_params_dies): Represent each template parameter pack by a DW_TAG_template_parameter_pack DIE. Argument pack elements are represented by usual DW_TAG_template_*_parameter DIEs that are children of the DW_TAG_template_parameter_pack element DIE. (generic_parameter_die): This doesn't deal with parameter pack names anymore. Don't generate DW_AT_name for some DIEs, e.g. children of parameter pack DIEs. (gen_formal_parameter_die): Add a flag to not emit DW_AT_name in certain cases, e.g. for pack elements. (gen_formal_types_die, gen_decl_die): Adjust usage of gen_formal_parameter_die. (gen_subprogram_die): Represent each function parameter pack by a DW_TAG_formal_parameter_pack DIE. Arguments of of the pack are represented by usual DW_TAG_formal_parameter DIEs that are children of the DW_TAG_formal_parameter_pack DIE. Remove references to ____builtin_va_alist decls as no part of the compiler uses those anymore. * langhooks.h (struct lang_hooks_for_decls): Add function_parm_expanded_from_pack_p, get_generic_function_decl and function_parameter_pack_p hooks. Fix comment for get_innermost_generic_parms hook. * langhooks-def.h (LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P ): Declare new hook macros and use them to initialize lang_hook. gcc/cp/ChangeLog: * cp-lang.c (LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, LANG_HOOKS_GET_GENERIC_FUNCTION_DECL): Initialize these hooks for the c++ FE. * cp-tree.h (function_parameter_pack_p, get_function_template_decl, function_parameter_expanded_from_pack_p): Declare ... * pt.c (function_parameter_pack_p, get_function_template_decl, function_parameter_expanded_from_pack_p): ... new hooks. (get_template_info): Make this more robust. (template_args_variadic_p, make_ith_pack_parameter_name): Add a new line between comment and function. (get_template_argument_pack_elems): Fix comment. (tsubst_decl): Arguments of function parameter packs are not parameter packs themselves. gcc/testsuite/ChangeLog: * g++.dg/debug/dwarf2/template-func-params-4.C: Adjust. * g++.dg/debug/dwarf2/template-func-params-7.C: Likewise. * g++.dg/debug/dwarf2/template-params-4.C: Likewise. From-SVN: r152043 --- gcc/ChangeLog | 32 +++ gcc/cp/ChangeLog | 17 ++ gcc/cp/cp-lang.c | 9 +- gcc/cp/cp-tree.h | 4 +- gcc/cp/pt.c | 53 ++++- gcc/dwarf2out.c | 245 ++++++++++++++------- gcc/langhooks-def.h | 7 + gcc/langhooks.h | 12 +- gcc/testsuite/ChangeLog | 6 + .../g++.dg/debug/dwarf2/template-func-params-4.C | 14 +- .../g++.dg/debug/dwarf2/template-func-params-7.C | 16 +- .../g++.dg/debug/dwarf2/template-params-4.C | 14 +- include/ChangeLog | 5 + include/dwarf2.h | 8 + 14 files changed, 340 insertions(+), 102 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0c3a0b6..5a3554c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2009-09-22 Dodji Seketeli + + * dwarf2out.c (template_parameter_pack_die, + gen_formal_parameter_pack_die ): New functions. + (make_ith_pack_parameter_name): Remove this function. + (dwarf_tag_name): Support printing DW_TAG_template_parameter_pack and + DW_TAG_formal_parameter_pack. + (gen_generic_params_dies): Represent each template parameter pack + by a DW_TAG_template_parameter_pack DIE. Argument pack elements are + represented by usual DW_TAG_template_*_parameter DIEs that are + children of the DW_TAG_template_parameter_pack element DIE. + (generic_parameter_die): This doesn't deal with parameter pack + names anymore. Don't generate DW_AT_name for some DIEs, e.g. children of + parameter pack DIEs. + (gen_formal_parameter_die): Add a flag to not emit DW_AT_name + in certain cases, e.g. for pack elements. + (gen_formal_types_die, gen_decl_die): Adjust usage of + gen_formal_parameter_die. + (gen_subprogram_die): Represent each function parameter pack by a + DW_TAG_formal_parameter_pack DIE. Arguments of of the pack are + represented by usual DW_TAG_formal_parameter DIEs that are children + of the DW_TAG_formal_parameter_pack DIE. Remove references to + ____builtin_va_alist decls as no part of the compiler uses those + anymore. + * langhooks.h (struct lang_hooks_for_decls): Add + function_parm_expanded_from_pack_p, get_generic_function_decl + and function_parameter_pack_p hooks. Fix comment for + get_innermost_generic_parms hook. + * langhooks-def.h (LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, + LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P ): Declare new hook + macros and use them to initialize lang_hook. + 2009-09-22 Richard Henderson * system.h (TRAMPOLINE_TEMPLATE, INITIALIZE_TRAMPOLINE): Poison. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d2fa331..ae3045e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2009-09-22 Dodji Seketeli + + * cp-lang.c (LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, + LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, + LANG_HOOKS_GET_GENERIC_FUNCTION_DECL): Initialize these + hooks for the c++ FE. + * cp-tree.h (function_parameter_pack_p, get_function_template_decl, + function_parameter_expanded_from_pack_p): Declare ... + * pt.c (function_parameter_pack_p, get_function_template_decl, + function_parameter_expanded_from_pack_p): ... new hooks. + (get_template_info): Make this more robust. + (template_args_variadic_p, make_ith_pack_parameter_name): Add a new + line between comment and function. + (get_template_argument_pack_elems): Fix comment. + (tsubst_decl): Arguments of function parameter packs are not + parameter packs themselves. + 2009-09-21 Jason Merrill PR c++/41421 diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 9521eab..d84325d 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -59,13 +59,20 @@ static tree cp_eh_personality (void); #undef LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS #define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS \ get_template_innermost_arguments +#undef LANG_HOOKS_FUNCTION_PARAMETER_PACK_P +#define LANG_HOOKS_FUNCTION_PARAMETER_PACK_P \ + function_parameter_pack_p #undef LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS #define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS \ get_template_argument_pack_elems #undef LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P #define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P \ template_template_parameter_p - +#undef LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P +#define LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P \ + function_parameter_expanded_from_pack_p +#undef LANG_HOOKS_GET_GENERIC_FUNCTION_DECL +#define LANG_HOOKS_GET_GENERIC_FUNCTION_DECL get_function_template_decl #undef LANG_HOOKS_DECL_PRINTABLE_NAME #define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name #undef LANG_HOOKS_DWARF_NAME diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 816b4ca..c089bb7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4643,6 +4643,8 @@ extern tree instantiate_decl (tree, int, bool); extern int comp_template_parms (const_tree, const_tree); extern bool uses_parameter_packs (tree); extern bool template_parameter_pack_p (const_tree); +extern bool function_parameter_pack_p (const_tree); +extern bool function_parameter_expanded_from_pack_p (tree, tree); extern tree make_pack_expansion (tree); extern bool check_for_bare_parameter_packs (tree); extern tree get_template_info (const_tree); @@ -4692,7 +4694,7 @@ bool template_template_parameter_p (const_tree); extern tree get_primary_template_innermost_parameters (const_tree); extern tree get_template_innermost_arguments (const_tree); extern tree get_template_argument_pack_elems (const_tree); - +extern tree get_function_template_decl (const_tree); /* in repo.c */ extern void init_repo (void); extern int repo_emit_p (tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7e3a545..08964da 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -294,6 +294,9 @@ get_template_info (const_tree t) { tree tinfo = NULL_TREE; + if (!t || t == error_mark_node) + return NULL; + if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) tinfo = DECL_TEMPLATE_INFO (t); @@ -2617,6 +2620,7 @@ comp_template_parms (const_tree parms1, const_tree parms2) } /* Determine whether PARM is a parameter pack. */ + bool template_parameter_pack_p (const_tree parm) { @@ -2635,8 +2639,49 @@ template_parameter_pack_p (const_tree parm) && TEMPLATE_TYPE_PARAMETER_PACK (parm)); } +/* Determine if T is a function parameter pack. */ + +bool +function_parameter_pack_p (const_tree t) +{ + if (t && TREE_CODE (t) == PARM_DECL) + return FUNCTION_PARAMETER_PACK_P (t); + return false; +} + +/* Return the function template declaration of PRIMARY_FUNC_TMPL_INST. + PRIMARY_FUNC_TMPL_INST is a primary function template instantiation. */ + +tree +get_function_template_decl (const_tree primary_func_tmpl_inst) +{ + if (! primary_func_tmpl_inst + || TREE_CODE (primary_func_tmpl_inst) != FUNCTION_DECL + || ! primary_template_instantiation_p (primary_func_tmpl_inst)) + return NULL; + + return DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (primary_func_tmpl_inst)); +} + +/* Return true iff the function parameter PARAM_DECL was expanded + from the function parameter pack PACK. */ + +bool +function_parameter_expanded_from_pack_p (tree param_decl, tree pack) +{ + if (! function_parameter_pack_p (pack)) + return false; + + gcc_assert (DECL_NAME (param_decl) && DECL_NAME (pack)); + + /* The parameter pack and its pack arguments have the same + DECL_PARM_INDEX. */ + return DECL_PARM_INDEX (pack) == DECL_PARM_INDEX (param_decl); +} + /* Determine whether ARGS describes a variadic template args list, i.e., one that is terminated by a template argument pack. */ + static bool template_args_variadic_p (tree args) { @@ -2659,6 +2704,7 @@ template_args_variadic_p (tree args) /* Generate a new name for the parameter pack name NAME (an IDENTIFIER_NODE) that incorporates its */ + static tree make_ith_pack_parameter_name (tree name, int i) { @@ -2735,7 +2781,8 @@ get_template_innermost_arguments (const_tree t) return args; } -/* Return the arguments pack of T if T is a template, NULL otherwise. */ +/* Return the argument pack elements of T if T is a template argument pack, + NULL otherwise. */ tree get_template_argument_pack_elems (const_tree t) @@ -8825,6 +8872,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (DECL_TEMPLATE_PARM_P (t)) SET_DECL_TEMPLATE_PARM_P (r); + /* An argument of a function parameter pack is not a parameter + pack. */ + FUNCTION_PARAMETER_PACK_P (r) = false; + if (expanded_types) /* We're on the Ith parameter of the function parameter pack. */ diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 9c128f1..f25b18b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -5932,7 +5932,8 @@ static dw_die_ref base_type_die (tree); static int is_base_type (tree); static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref); static dw_die_ref modified_type_die (tree, int, int, dw_die_ref); -static dw_die_ref generic_parameter_die (tree, tree, dw_die_ref, int); +static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref); +static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref); static int type_is_enum (const_tree); static unsigned int dbx_reg_number (const_rtx); static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); @@ -6000,7 +6001,8 @@ static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_re static void gen_entry_point_die (tree, dw_die_ref); #endif static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref); -static dw_die_ref gen_formal_parameter_die (tree, tree, dw_die_ref); +static dw_die_ref gen_formal_parameter_die (tree, tree, bool, dw_die_ref); +static dw_die_ref gen_formal_parameter_pack_die (tree, tree, dw_die_ref, tree*); static void gen_unspecified_parameters_die (tree, dw_die_ref); static void gen_formal_types_die (tree, dw_die_ref); static void gen_subprogram_die (tree, dw_die_ref); @@ -6032,7 +6034,6 @@ static dw_die_ref declare_in_namespace (tree, dw_die_ref); static struct dwarf_file_data * lookup_filename (const char *); static void retry_incomplete_types (void); static void gen_type_die_for_member (tree, tree, dw_die_ref); -static tree make_ith_pack_parameter_name (tree, int); static void gen_generic_params_dies (tree); static void splice_child_die (dw_die_ref, dw_die_ref); static int file_info_cmp (const void *, const void *); @@ -6337,6 +6338,10 @@ dwarf_tag_name (unsigned int tag) return "DW_TAG_condition"; case DW_TAG_shared_type: return "DW_TAG_shared_type"; + case DW_TAG_template_parameter_pack: + return "DW_TAG_template_parameter_pack"; + case DW_TAG_formal_parameter_pack: + return "DW_TAG_formal_parameter_pack"; case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; case DW_TAG_format_label: @@ -10512,27 +10517,6 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type, return mod_type_die; } -/* Generate a new name for the parameter pack name NAME (an - IDENTIFIER_NODE) that incorporates its */ - -static tree -make_ith_pack_parameter_name (tree name, int i) -{ - /* Munge the name to include the parameter index. */ -#define NUMBUF_LEN 128 - char numbuf[NUMBUF_LEN]; - char* newname; - int newname_len; - - snprintf (numbuf, NUMBUF_LEN, "%i", i); - newname_len = IDENTIFIER_LENGTH (name) - + strlen (numbuf) + 2; - newname = (char*) alloca (newname_len); - snprintf (newname, newname_len, - "%s#%i", IDENTIFIER_POINTER (name), i); - return get_identifier (newname); -} - /* Generate DIEs for the generic parameters of T. T must be either a generic type or a generic function. See http://gcc.gnu.org/wiki/TemplateParmsDwarf for more. */ @@ -10564,30 +10548,27 @@ gen_generic_params_dies (tree t) args = lang_hooks.get_innermost_generic_args (t); for (i = 0; i < parms_num; i++) { - tree parm, arg; + tree parm, arg, arg_pack_elems; parm = TREE_VEC_ELT (parms, i); arg = TREE_VEC_ELT (args, i); + arg_pack_elems = lang_hooks.types.get_argument_pack_elems (arg); + gcc_assert (parm && TREE_VALUE (parm) && arg); + if (parm && TREE_VALUE (parm) && arg) { - tree pack_elems = - lang_hooks.types.get_argument_pack_elems (arg); - if (pack_elems) - { - /* So ARG is an argument pack and the elements of that pack - are stored in PACK_ELEMS. */ - int i, len; - - len = TREE_VEC_LENGTH (pack_elems); - for (i = 0; i < len; i++) - generic_parameter_die (TREE_VALUE (parm), - TREE_VEC_ELT (pack_elems, i), - die, i); - } - else /* Arg is not an argument pack. */ - generic_parameter_die (TREE_VALUE (parm), - arg, die, - -1/* Not a param pack. */); + /* If PARM represents a template parameter pack, + emit a DW_TAG_template_parameter_pack DIE, followed + by DW_TAG_template_*_parameter DIEs for the argument + pack elements of ARG. Note that ARG would then be + an argument pack. */ + if (arg_pack_elems) + template_parameter_pack_die (TREE_VALUE (parm), + arg_pack_elems, + die); + else + generic_parameter_die (TREE_VALUE (parm), arg, + true /* Emit DW_AT_name */, die); } } } @@ -10596,15 +10577,15 @@ gen_generic_params_dies (tree t) the representation of a generic type parameter. For instance, in the C++ front end, PARM would be a template parameter. ARG is the argument to PARM. + EMIT_NAME_P if tree, the DIE will have DW_AT_name attribute set to the + name of the PARM. PARENT_DIE is the parent DIE which the new created DIE should be added to, - as a child node. - PACK_ELEM_INDEX is >= 0 if PARM is a generic parameter pack, and if ARG - is one of the unpacked elements of the parameter PACK. In that case, - PACK_ELEM_INDEX is the index of ARG in the parameter pack. */ + as a child node. */ static dw_die_ref -generic_parameter_die (tree parm, tree arg, dw_die_ref parent_die, - int pack_elem_index) +generic_parameter_die (tree parm, tree arg, + bool emit_name_p, + dw_die_ref parent_die) { dw_die_ref tmpl_die = NULL; const char *name = NULL; @@ -10637,20 +10618,17 @@ generic_parameter_die (tree parm, tree arg, dw_die_ref parent_die, { tree tmpl_type; - if (pack_elem_index >= 0) + /* If PARM is a generic parameter pack, it means we are + emitting debug info for a template argument pack element. + In other terms, ARG is a template argument pack element. + In that case, we don't emit any DW_AT_name attribute for + the die. */ + if (emit_name_p) { - /* PARM is an element of a parameter pack. - Generate a name for it. */ - tree identifier = make_ith_pack_parameter_name (DECL_NAME (parm), - pack_elem_index); - if (identifier) - name = IDENTIFIER_POINTER (identifier); + name = IDENTIFIER_POINTER (DECL_NAME (parm)); + gcc_assert (name); + add_AT_string (tmpl_die, DW_AT_name, name); } - else - name = IDENTIFIER_POINTER (DECL_NAME (parm)); - - gcc_assert (name); - add_AT_string (tmpl_die, DW_AT_name, name); if (!lang_hooks.decls.generic_generic_parameter_decl_p (parm)) { @@ -10695,6 +10673,33 @@ generic_parameter_die (tree parm, tree arg, dw_die_ref parent_die, return tmpl_die; } +/* Generate and return a DW_TAG_template_parameter_pack DIE representing. + PARM_PACK must be a template parameter pack. The returned DIE + will be child DIE of PARENT_DIE. */ + +static dw_die_ref +template_parameter_pack_die (tree parm_pack, + tree parm_pack_args, + dw_die_ref parent_die) +{ + dw_die_ref die; + int j; + + gcc_assert (parent_die + && parm_pack + && DECL_NAME (parm_pack)); + + die = new_die (DW_TAG_template_parameter_pack, parent_die, parm_pack); + add_AT_string (die, DW_AT_name, IDENTIFIER_POINTER (DECL_NAME (parm_pack))); + + for (j = 0; j < TREE_VEC_LENGTH (parm_pack_args); j++) + generic_parameter_die (parm_pack, + TREE_VEC_ELT (parm_pack_args, j), + false /* Don't emit DW_AT_name */, + die); + return die; +} + /* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is an enumerated type. */ @@ -15380,10 +15385,13 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die) DIE to represent a formal parameter object (or some inlining thereof). If it's the latter, then this function is only being called to output a DW_TAG_formal_parameter DIE to stand as a placeholder for some formal - argument type of some subprogram type. */ + argument type of some subprogram type. + If EMIT_NAME_P is true, name and source coordinate attributes + are emitted. */ static dw_die_ref -gen_formal_parameter_die (tree node, tree origin, dw_die_ref context_die) +gen_formal_parameter_die (tree node, tree origin, bool emit_name_p, + dw_die_ref context_die) { tree node_or_origin = node ? node : origin; dw_die_ref parm_die @@ -15399,7 +15407,8 @@ gen_formal_parameter_die (tree node, tree origin, dw_die_ref context_die) else { tree type = TREE_TYPE (node); - add_name_and_src_coords_attributes (parm_die, node); + if (emit_name_p) + add_name_and_src_coords_attributes (parm_die, node); if (decl_by_reference_p (node)) add_type_attribute (parm_die, TREE_TYPE (type), 0, 0, context_die); @@ -15432,6 +15441,49 @@ gen_formal_parameter_die (tree node, tree origin, dw_die_ref context_die) return parm_die; } +/* Generate and return a DW_TAG_formal_parameter_pack. Also generate + children DW_TAG_formal_parameter DIEs representing the arguments of the + parameter pack. + + PARM_PACK must be a function parameter pack. + PACK_ARG is the first argument of the parameter pack. Its TREE_CHAIN + must point to the subsequent arguments of the function PACK_ARG belongs to. + SUBR_DIE is the DIE of the function PACK_ARG belongs to. + If NEXT_ARG is non NULL, *NEXT_ARG is set to the function argument + following the last one for which a DIE was generated. */ + +static dw_die_ref +gen_formal_parameter_pack_die (tree parm_pack, + tree pack_arg, + dw_die_ref subr_die, + tree *next_arg) +{ + tree arg; + dw_die_ref parm_pack_die; + + gcc_assert (parm_pack + && lang_hooks.function_parameter_pack_p (parm_pack) + && DECL_NAME (parm_pack) + && subr_die); + + parm_pack_die = new_die (DW_TAG_formal_parameter_pack, subr_die, parm_pack); + add_AT_string (parm_pack_die, DW_AT_name, + IDENTIFIER_POINTER (DECL_NAME (parm_pack))); + + for (arg = pack_arg; arg; arg = TREE_CHAIN (arg)) + { + if (! lang_hooks.decls.function_parm_expanded_from_pack_p (arg, + parm_pack)) + break; + gen_formal_parameter_die (arg, NULL, + false /* Don't emit name attribute. */, + parm_pack_die); + } + if (next_arg) + *next_arg = arg; + return parm_pack_die; +} + /* Generate a special type of DIE used as a stand-in for a trailing ellipsis at the end of an (ANSI prototyped) formal parameters list. */ @@ -15475,7 +15527,9 @@ gen_formal_types_die (tree function_or_method_type, dw_die_ref context_die) break; /* Output a (nameless) DIE to represent the formal parameter itself. */ - parm_die = gen_formal_parameter_die (formal_type, NULL, context_die); + parm_die = gen_formal_parameter_die (formal_type, NULL, + true /* Emit name attribute. */, + context_die); if ((TREE_CODE (function_or_method_type) == METHOD_TYPE && link == first_parm_type) || (arg && DECL_ARTIFICIAL (arg))) @@ -15887,21 +15941,46 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) else { /* Generate DIEs to represent all known formal parameters. */ - tree arg_decls = DECL_ARGUMENTS (decl); - tree parm; - - /* When generating DIEs, generate the unspecified_parameters DIE - instead if we come across the arg "__builtin_va_alist" */ - for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) - if (TREE_CODE (parm) == PARM_DECL) - { - if (DECL_NAME (parm) - && !strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)), - "__builtin_va_alist")) - gen_unspecified_parameters_die (parm, subr_die); - else + tree parm = DECL_ARGUMENTS (decl); + tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl); + tree generic_decl_parm = generic_decl + ? DECL_ARGUMENTS (generic_decl) + : NULL; + + /* Now we want to walk the list of parameters of the function and + emit their relevant DIEs. + + We consider the case of DECL being an instance of a generic function + as well as it being a normal function. + + If DECL is an instance of a generic function we walk the + parameters of the generic function declaration _and_ the parameters of + DECL itself. This is useful because we want to emit specific DIEs for + function parameter packs and those are declared as part of the + generic function declaration. In that particular case, + the parameter pack yields a DW_TAG_formal_parameter_pack DIE. + That DIE has children DIEs representing the set of arguments + of the pack. Note that the set of pack arguments can be empty. + In that case, the DW_TAG_formal_parameter_pack DIE will not have any + children DIE. + + Otherwise, we just consider the parameters of DECL. */ + while (generic_decl_parm || parm) + { + if (generic_decl_parm + && lang_hooks.function_parameter_pack_p (generic_decl_parm)) + gen_formal_parameter_pack_die (generic_decl_parm, + parm, subr_die, + &parm); + else if (parm) + { gen_decl_die (parm, NULL, subr_die); - } + parm = TREE_CHAIN (parm); + } + + if (generic_decl_parm) + generic_decl_parm = TREE_CHAIN (generic_decl_parm); + } /* Decide whether we need an unspecified_parameters DIE at the end. There are 2 more cases to do this for: 1) the ansi ... declaration - @@ -17489,7 +17568,9 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die) if (!origin) origin = decl_ultimate_origin (decl); if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL) - gen_formal_parameter_die (decl, origin, context_die); + gen_formal_parameter_die (decl, origin, + true /* Emit name attribute. */, + context_die); else gen_variable_die (decl, origin, context_die); break; @@ -17511,7 +17592,9 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die) gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die); else gen_type_die (TREE_TYPE (decl_or_origin), context_die); - gen_formal_parameter_die (decl, origin, context_die); + gen_formal_parameter_die (decl, origin, + true /* Emit name attribute. */, + context_die); break; case NAMESPACE_DECL: diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index dc4fdee..fa078ad 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -157,8 +157,12 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_GENERIC_TYPE_P hook_bool_const_tree_false #define LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS hook_tree_const_tree_null #define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS hook_tree_const_tree_null +#define LANG_HOOKS_FUNCTION_PARAMETER_PACK_P hook_bool_const_tree_false #define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS hook_tree_const_tree_null #define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P hook_bool_const_tree_false +#define LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P \ + hook_bool_tree_tree_false +#define LANG_HOOKS_GET_GENERIC_FUNCTION_DECL hook_tree_const_tree_null #define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type #define LANG_HOOKS_TYPE_MAX_SIZE lhd_return_null_const_tree @@ -214,6 +218,8 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_GETDECLS, \ LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \ LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \ + LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \ + LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \ LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \ LANG_HOOKS_WRITE_GLOBALS, \ LANG_HOOKS_DECL_OK_FOR_SIBCALL, \ @@ -268,6 +274,7 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_FOR_TYPES_INITIALIZER, \ LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \ LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \ + LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, \ LANG_HOOKS_GIMPLIFY_EXPR, \ LANG_HOOKS_FOLD_OBJ_TYPE_REF, \ LANG_HOOKS_BUILTIN_FUNCTION, \ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 349a5d8..ab64040 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -172,6 +172,13 @@ struct lang_hooks_for_decls of a generic type, e.g a template template parameter for the C++ FE. */ bool (*generic_generic_parameter_decl_p) (const_tree); + /* Determine if a function parameter got expanded from a + function parameter pack. */ + bool (*function_parm_expanded_from_pack_p) (tree, tree); + + /* Returns the generic declaration of a generic function instantiations. */ + tree (*get_generic_function_decl) (const_tree); + /* Returns true when we should warn for an unused global DECL. We will already have checked that it has static binding. */ bool (*warn_unused_global) (const_tree); @@ -379,7 +386,7 @@ struct lang_hooks struct lang_hooks_for_types types; - /* Retuns the generic parameters of an instantiation of + /* Returns the generic parameters of an instantiation of a generic type or decl, e.g. C++ template instantiation. */ tree (*get_innermost_generic_parms) (const_tree); @@ -387,6 +394,9 @@ struct lang_hooks of a generic type of decl, e.g. C++ template instantiation. */ tree (*get_innermost_generic_args) (const_tree); + /* Determine if a tree is a function parameter pack. */ + bool (*function_parameter_pack_p) (const_tree); + /* Perform language-specific gimplification on the argument. Returns an enum gimplify_status, though we can't see that type here. */ int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fd26fb24..efd31a7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-09-22 Dodji Seketeli + + * g++.dg/debug/dwarf2/template-func-params-4.C: Adjust. + * g++.dg/debug/dwarf2/template-func-params-7.C: Likewise. + * g++.dg/debug/dwarf2/template-params-4.C: Likewise. + 2009-09-22 Alexandre Oliva PR debug/41295 diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C index 0eb0fe5..f75d0e6 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C @@ -1,10 +1,16 @@ // Contributed by Dodji Seketeli // Origin PR debug/30161 // { dg-options "-std=c++0x -g -dA" } -// { dg-final { scan-assembler "DW_TAG_template_type_param" } } -// { dg-final { scan-assembler "DW_AT_name.*P#0" } } -// { dg-final { scan-assembler "DW_AT_name.*P#1" } } -// { dg-final { scan-assembler "DW_AT_name.*P#2" } } +// +// In theory the compiler instantiates count, +// count and count. In practice, only +// count is emitted, thanks to constant folding. +// So in theory, each of the 3 instances of count yields a +// DW_TAG_tempalate_parameter_pack DIE, but in practise, there is only one +// DW_TAG_template_parameter_pack as there is only count +// is emitted. +// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_template_parameter_pack" 1} } +// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_template_type_param" 3} } template struct count; diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C index dc6ac99..8a883f8 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C @@ -16,17 +16,15 @@ // { dg-final {scan-assembler-times "\"printf.0\".*?DW_AT_name" 1 } } // printf and printf have a pack expansion as -// function parameters. In the former, the elements of the parameter pack -// expansion are PackTypes#0, PackTypes#1 and the arguments are args#0 and -// args#1. In the later, the element of the parameter pack expansion -// is PackTypes#0 and the argument is args#0. -// { dg-final {scan-assembler-times "DW_AT_name: \"PackTypes#0\"" 2 } } -// { dg-final {scan-assembler-times "\"args#0.0\".*?DW_AT_name" 2 } } -// { dg-final {scan-assembler-times "\"PackTypes#1.0\".*?DW_AT_name" 1 } } -// { dg-final {scan-assembler-times "\"args#1.0\".*?DW_AT_name" 1 } } - +// function parameters. There should then be 3 +// DW_TAG_template_parameter_pack and 3 DW_TAG_formal_parameter_pack DIEs +// { dg-final {scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_template_parameter_pack" 3 } } +// { dg-final {scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_formal_parameter_pack" 3 } } +// These 3 function template instantiations has a total of 3 template +// parameters named T. // { dg_final {scan-assembler-times "\.ascii \"T.0\"\[\t \]+.*?DW_AT_name" 3 } } + void printf(const char* s) { diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C index 09d1d95..e83ef61 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C @@ -1,10 +1,16 @@ // Contributed by Dodji Seketeli // Origin PR debug/30161 // { dg-options "-std=c++0x -g -dA" } -// { dg-final { scan-assembler "DW_TAG_template_type_param" } } -// { dg-final { scan-assembler "DW_AT_name.*Args#0" } } -// { dg-final { scan-assembler "DW_AT_name.*Args#1" } } -// { dg-final { scan-assembler "DW_AT_name.*Args#2" } } +// +// In theory the compiler instantiates count, +// count and count. In practice, only +// count is emitted, thanks to constant folding. +// So in theory, each of the 3 instances of count yields a +// DW_TAG_tempalate_parameter_pack DIE, but in practise, there is only one +// DW_TAG_template_parameter_pack as there is only count +// is emitted. +// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_template_parameter_pack" 1} } +// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_template_type_param" 3} } template struct count; diff --git a/include/ChangeLog b/include/ChangeLog index 4bd5e81..3ba01d2 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2009-09-22 Dodji Seketeli + + * dwarf2.h (enum dwarf_tag): Add + DW_TAG_template_parameter_pack and DW_TAG_formal_parameter_pack. + 2009-07-24 Ian Lance Taylor PR bootstrap/40854 diff --git a/include/dwarf2.h b/include/dwarf2.h index befaceb..608f7b5 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -200,6 +200,14 @@ enum dwarf_tag DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, + /* DWARF 5? */ + + /* Template parameter pack extension, specified at + http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates + . */ + DW_TAG_template_parameter_pack = 0x43, + DW_TAG_formal_parameter_pack = 0x44, + /* SGI/MIPS Extensions. */ DW_TAG_MIPS_loop = 0x4081, /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */ -- 2.7.4