summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c245
1 files changed, 164 insertions, 81 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 9c128f1ec2e..f25b18b037a 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: