Emit DWARF for template parameters (PR debug/30161)

ChangeLog:
	PR debug/30161
	* include/dwarf2.h (enum dwarf_tag): Added
	DW_TAG_GNU_template_template_param
	(enum dwarf_attribute): Added DW_AT_GNU_template_name.

gcc/ChangeLog:
	PR debug/30161
	* cgraph.h (cgraph_get_node): Declare ...
	* cgraph.c (cgraph_get_node): ... new function.
	* dwarf2out.c (gen_generic_params_dies,
	generic_parameter_die, tree_add_const_value_attribute_for_decl,
	make_ith_pack_parameter_name,
	append_entry_to_tmpl_value_parm_die_table,
	gen_remaining_tmpl_value_param_die_attribute): New functions.
	(gen_subprogram_die): Generate debug info for template parameters
	if debug info level is higher than DINFO_LEVEL_TERSE.
	Use tree_add_const_value_attribute_for_decl instead of
	tree_add_const_value_attribute.
	(gen_const_die): Use tree_add_const_value_attribute_for_decl
	instead of tree_add_const_value_attribute.
	(gen_struct_or_union_type_die): Generate debug
	info for template parameters if debug info level is higher than
	DINFO_LEVEL_TERSE.
	(tree_add_const_value_attribute): Handle integral and pointer
	constants. Update comment.
	(dwarf_tag_name): Support DW_TAG_GNU_template_template_param.
	(dwarf_attr_name): Support DW_AT_GNU_template_name.
	(reference_to_unused): Fix thinko. Remove redundant predicates from
	tests.
	(tree_add_const_value_attribute): Make this work for constant
	expressions only.
	tree_add_const_value_attribute_for_decl is to be used for variable
	DECLs now.
	(add_location_or_const_value_attribute): Use
	tree_add_const_value_attribute_for_decl now.
	(dwarf2out_finish): Emit the DW_AT_const_value attribute of
	DW_TAG_template_value_param DIEs after function DIEs have been
	emitted.
	* langhooks.h (lang_hooks_for_types): Add
	get_argument_pack_elems.
	(lang_hooks_for_decls): Add generic_generic_parameter_decl_p.
	(lang_hooks): Added get_innermost_generic_parms,
	get_innermost_generic_args.
	* langhooks-def.h (LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS,
	LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS,
	LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS,
	LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P): New language hooks.

gcc/cp/ChangeLog:
	PR debug/30161
	* cp-tree.h (get_template_info): Parameter should be const.
	(CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P): Fix typo.
	(get_template_argument_pack_elems,
	get_primary_template_innermost_parameters,
	get_template_innermost_arguments, template_template_parameter_p):
	Declare ...
	* pt.c (get_template_argument_pack_elems,
	get_template_innermost_parameters, get_template_innermost_arguments,
	template_template_parameter_p):
	... New C++ front end implementation of new language hooks.
	(primary_template_instantiation_p): New private helper.
	(make_ith_pack_parameter_name): Use snprintf and strnlen instead of
	printf and strlen.
	(get_template_info): Const-ify parameter.
	* cp-lang.c (LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS,
	LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS,
	LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS,
	LANG_HOOKS_GENERIC_TYPE_PARAMETER_DECL_P): Initialize these
	interfaces for the C++ front-end.

gcc/testsuite/ChangeLog:
	PR debug/30161
	* g++.dg/debug/dwarf2/template-params-1.C: New test.
	* g++.dg/debug/dwarf2/template-params-2.C: Likewise.
	* g++.dg/debug/dwarf2/template-params-3.C: Likewise.
	* g++.dg/debug/dwarf2/template-params-4.C: Likewise.
	* g++.dg/debug/dwarf2/template-params-5.C: Likewise.
	* g++.dg/debug/dwarf2/template-params-6.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-1.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-2.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-3.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-4.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-5.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-6.C: Likewise.
	* g++.dg/debug/dwarf2/template-func-params-7.C: Likewise.

From-SVN: r151249
This commit is contained in:
Dodji Seketeli 2009-08-31 21:48:04 +00:00 committed by Dodji Seketeli
parent e756464b1f
commit f9329c35d7
26 changed files with 935 additions and 28 deletions

View File

@ -1,3 +1,10 @@
2009-08-31 Dodji Seketeli <dodji@redhat.com>
PR debug/30161
* include/dwarf2.h (enum dwarf_tag): Added
DW_TAG_GNU_template_template_param
(enum dwarf_attribute): Added DW_AT_GNU_template_name.
2009-08-30 Paolo Bonzini <bonzini@gnu.org>
* Makefile.tpl (AWK): Fix typo.

View File

@ -1,3 +1,47 @@
2009-08-31 Dodji Seketeli <dodji@redhat.com>
PR debug/30161
* cgraph.h (cgraph_get_node): Declare ...
* cgraph.c (cgraph_get_node): ... new function.
* dwarf2out.c (gen_generic_params_dies,
generic_parameter_die, tree_add_const_value_attribute_for_decl,
make_ith_pack_parameter_name,
append_entry_to_tmpl_value_parm_die_table,
gen_remaining_tmpl_value_param_die_attribute): New functions.
(gen_subprogram_die): Generate debug info for template parameters
if debug info level is higher than DINFO_LEVEL_TERSE.
Use tree_add_const_value_attribute_for_decl instead of
tree_add_const_value_attribute.
(gen_const_die): Use tree_add_const_value_attribute_for_decl
instead of tree_add_const_value_attribute.
(gen_struct_or_union_type_die): Generate debug
info for template parameters if debug info level is higher than
DINFO_LEVEL_TERSE.
(tree_add_const_value_attribute): Handle integral and pointer
constants. Update comment.
(dwarf_tag_name): Support DW_TAG_GNU_template_template_param.
(dwarf_attr_name): Support DW_AT_GNU_template_name.
(reference_to_unused): Fix thinko. Remove redundant predicates from
tests.
(tree_add_const_value_attribute): Make this work for constant
expressions only.
tree_add_const_value_attribute_for_decl is to be used for variable
DECLs now.
(add_location_or_const_value_attribute): Use
tree_add_const_value_attribute_for_decl now.
(dwarf2out_finish): Emit the DW_AT_const_value attribute of
DW_TAG_template_value_param DIEs after function DIEs have been
emitted.
* langhooks.h (lang_hooks_for_types): Add
get_argument_pack_elems.
(lang_hooks_for_decls): Add generic_generic_parameter_decl_p.
(lang_hooks): Added get_innermost_generic_parms,
get_innermost_generic_args.
* langhooks-def.h (LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS,
LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS,
LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS,
LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P): New language hooks.
2009-08-31 DJ Delorie <dj@redhat.com>
* config/mep/mep.c (machine_function): Add frame_locked flag. Set
@ -11,6 +55,7 @@
(mep_return_in_memory): Zero-sized objects are passed in memory.
(mep_reorg_noframe): Make sure we have accurate REG_DEAD notes.
2009-08-31 Richard Guenther <rguenther@suse.de>
* builtins.c (fold_builtin_memory_op): Use the alias oracle

View File

@ -493,6 +493,29 @@ cgraph_node (tree decl)
return node;
}
/* Returns the cgraph node assigned to DECL or NULL if no cgraph node
is assigned. */
struct cgraph_node *
cgraph_get_node (tree decl)
{
struct cgraph_node key, *node = NULL, **slot;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
if (!cgraph_hash)
cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
key.decl = decl;
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
NO_INSERT);
if (slot && *slot)
node = *slot;
return node;
}
/* Insert already constructed node into hashtable. */
void

View File

@ -388,6 +388,8 @@ void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node *,
gimple, gcov_type, int, int);
struct cgraph_node * cgraph_get_node (tree);
struct cgraph_node *cgraph_node (tree);
struct cgraph_node *cgraph_node_for_asm (tree asmname);
struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);

View File

@ -1,3 +1,26 @@
2009-08-31 Dodji Seketeli <dodji@redhat.com>
PR debug/30161
* cp-tree.h (get_template_info): Parameter should be const.
(CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P): Fix typo.
(get_template_argument_pack_elems,
get_primary_template_innermost_parameters,
get_template_innermost_arguments, template_template_parameter_p):
Declare ...
* pt.c (get_template_argument_pack_elems,
get_template_innermost_parameters, get_template_innermost_arguments,
template_template_parameter_p):
... New C++ front end implementation of new language hooks.
(primary_template_instantiation_p): New private helper.
(make_ith_pack_parameter_name): Use snprintf and strnlen instead of
printf and strlen.
(get_template_info): Const-ify parameter.
* cp-lang.c (LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS,
LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS,
LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS,
LANG_HOOKS_GENERIC_TYPE_PARAMETER_DECL_P): Initialize these
interfaces for the C++ front-end.
2009-08-31 Jason Merrill <jason@redhat.com>
PR c++/41127

View File

@ -49,6 +49,20 @@ static enum classify_record cp_classify_record (tree type);
#define LANG_HOOKS_CLASSIFY_RECORD cp_classify_record
#undef LANG_HOOKS_GENERIC_TYPE_P
#define LANG_HOOKS_GENERIC_TYPE_P class_tmpl_impl_spec_p
#undef LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS
#define LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS \
get_primary_template_innermost_parameters
#undef LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS
#define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS \
get_template_innermost_arguments
#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_DECL_PRINTABLE_NAME
#define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name
#undef LANG_HOOKS_DWARF_NAME

View File

@ -3283,7 +3283,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P(NODE) \
(CLASS_TYPE_P (NODE) \
&& CLASSTYPE_USE_TEMPLATE (NODE) \
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
@ -4638,7 +4638,7 @@ extern bool uses_parameter_packs (tree);
extern bool template_parameter_pack_p (const_tree);
extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (tree);
extern tree get_template_info (tree);
extern tree get_template_info (const_tree);
extern tree get_types_needing_access_check (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
@ -4680,6 +4680,10 @@ extern bool explicit_class_specialization_p (tree);
extern struct tinst_level *outermost_tinst_level(void);
extern bool parameter_of_template_p (tree, tree);
extern void init_template_processing (void);
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);
/* in repo.c */
extern void init_repo (void);

View File

@ -191,6 +191,7 @@ static tree tsubst_decl (tree, tree, tsubst_flags_t);
static void perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree);
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static bool primary_template_instantiation_p (const_tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@ -287,7 +288,7 @@ finish_member_template_decl (tree decl)
/* Return the template info node corresponding to T, whatever T is. */
tree
get_template_info (tree t)
get_template_info (const_tree t)
{
tree tinfo = NULL_TREE;
@ -2660,15 +2661,90 @@ static tree
make_ith_pack_parameter_name (tree name, int i)
{
/* Munge the name to include the parameter index. */
char numbuf[128];
#define NUMBUF_LEN 128
char numbuf[NUMBUF_LEN];
char* newname;
sprintf(numbuf, "%i", i);
newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2);
sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), i);
int newname_len;
snprintf (numbuf, NUMBUF_LEN, "%i", i);
newname_len = IDENTIFIER_LENGTH (name)
+ strnlen (numbuf, NUMBUF_LEN) + 2;
newname = (char*)alloca (newname_len);
snprintf (newname, newname_len,
"%s#%i", IDENTIFIER_POINTER (name), i);
return get_identifier (newname);
}
/* Return true if T is a primary function
or class template instantiation. */
static bool
primary_template_instantiation_p (const_tree t)
{
if (!t)
return false;
if (TREE_CODE (t) == FUNCTION_DECL)
return DECL_LANG_SPECIFIC (t)
&& DECL_TEMPLATE_INSTANTIATION (t)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
else if (CLASS_TYPE_P (t))
return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
return false;
}
/* Return true if PARM is a template template parameter. */
bool
template_template_parameter_p (const_tree parm)
{
return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
}
/* Return the template parameters of T if T is a
primary template instantiation, NULL otherwise. */
tree
get_primary_template_innermost_parameters (const_tree t)
{
tree parms = NULL, template_info = NULL;
if ((template_info = get_template_info (t))
&& primary_template_instantiation_p (t))
parms = INNERMOST_TEMPLATE_PARMS
(DECL_TEMPLATE_PARMS (TI_TEMPLATE (template_info)));
return parms;
}
/* Returns the template arguments of T if T is a template instantiation,
NULL otherwise. */
tree
get_template_innermost_arguments (const_tree t)
{
tree args = NULL, template_info = NULL;
if ((template_info = get_template_info (t))
&& TI_ARGS (template_info))
args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (template_info));
return args;
}
/* Return the arguments pack of T if T is a template, NULL otherwise. */
tree
get_template_argument_pack_elems (const_tree t)
{
if (TREE_CODE (t) != TYPE_ARGUMENT_PACK
&& TREE_CODE (t) != NONTYPE_ARGUMENT_PACK)
return NULL;
return ARGUMENT_PACK_ARGS (t);
}
/* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data
{

View File

@ -5551,6 +5551,14 @@ static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
The key is DECL_UID() ^ die_parent. */
static GTY ((param_is (struct die_struct))) htab_t common_block_die_table;
typedef struct GTY(()) die_arg_entry_struct {
dw_die_ref die;
tree arg;
} die_arg_entry;
DEF_VEC_O(die_arg_entry);
DEF_VEC_ALLOC_O(die_arg_entry,gc);
/* Node of the variable location list. */
struct GTY ((chain_next ("%h.next"))) var_loc_node {
rtx GTY (()) var_loc_note;
@ -5691,6 +5699,8 @@ static GTY(()) struct dwarf_file_data * file_table_last_lookup;
within the current function. */
static HOST_WIDE_INT frame_pointer_fb_offset;
static GTY(()) VEC(die_arg_entry,gc) *tmpl_value_parm_die_table;
/* Forward declarations for functions defined in this file. */
static int is_pseudo_reg (const_rtx);
@ -5826,6 +5836,7 @@ 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 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);
@ -5861,6 +5872,7 @@ static rtx rtl_for_decl_location (tree);
static void add_location_or_const_value_attribute (dw_die_ref, tree,
enum dwarf_attribute);
static void tree_add_const_value_attribute (dw_die_ref, tree);
static void tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
static void add_comp_dir_attribute (dw_die_ref);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
@ -5924,6 +5936,8 @@ 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 *);
static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
@ -5941,6 +5955,8 @@ static void prune_unused_types_walk_attribs (dw_die_ref);
static void prune_unused_types_prune (dw_die_ref);
static void prune_unused_types (void);
static int maybe_emit_file (struct dwarf_file_data *fd);
static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree);
static void gen_remaining_tmpl_value_param_die_attribute (void);
/* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION
@ -6237,6 +6253,8 @@ dwarf_tag_name (unsigned int tag)
return "DW_TAG_GNU_BINCL";
case DW_TAG_GNU_EINCL:
return "DW_TAG_GNU_EINCL";
case DW_TAG_GNU_template_template_param:
return "DW_TAG_GNU_template_template_param";
default:
return "DW_TAG_<unknown>";
}
@ -6438,6 +6456,8 @@ dwarf_attr_name (unsigned int attr)
return "DW_AT_body_end";
case DW_AT_GNU_vector:
return "DW_AT_GNU_vector";
case DW_AT_GNU_template_name:
return "DW_AT_GNU_template_name";
case DW_AT_VMS_rtnbeg_pd_address:
return "DW_AT_VMS_rtnbeg_pd_address";
@ -10353,6 +10373,189 @@ 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)
+ strnlen (numbuf, NUMBUF_LEN) + 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. */
static void
gen_generic_params_dies (tree t)
{
tree parms, args;
int parms_num, i;
dw_die_ref die = NULL;
if (!t || (TYPE_P (t) && !COMPLETE_TYPE_P (t)))
return;
if (TYPE_P (t))
die = lookup_type_die (t);
else if (DECL_P (t))
die = lookup_decl_die (t);
gcc_assert (die);
parms = lang_hooks.get_innermost_generic_parms (t);
if (!parms)
/* T has no generic parameter. It means T is neither a generic type
or function. End of story. */
return;
parms_num = TREE_VEC_LENGTH (parms);
args = lang_hooks.get_innermost_generic_args (t);
for (i = 0; i < parms_num; i++)
{
tree parm, arg;
parm = TREE_VEC_ELT (parms, i);
arg = TREE_VEC_ELT (args, i);
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. */);
}
}
}
/* Create and return a DIE for PARM which should be
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.
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. */
static dw_die_ref
generic_parameter_die (tree parm, tree arg, dw_die_ref parent_die,
int pack_elem_index)
{
dw_die_ref tmpl_die = NULL;
const char *name = NULL;
if (!parm || !DECL_NAME (parm) || !arg)
return NULL;
/* We support non-type generic parameters and arguments,
type generic parameters and arguments, as well as
generic generic parameters (a.k.a. template template parameters in C++)
and arguments. */
if (TREE_CODE (parm) == PARM_DECL)
/* PARM is a nontype generic parameter */
tmpl_die = new_die (DW_TAG_template_value_param, parent_die, parm);
else if (TREE_CODE (parm) == TYPE_DECL)
/* PARM is a type generic parameter. */
tmpl_die = new_die (DW_TAG_template_type_param, parent_die, parm);
else if (lang_hooks.decls.generic_generic_parameter_decl_p (parm))
/* PARM is a generic generic parameter.
Its DIE is a GNU extension. It shall have a
DW_AT_name attribute to represent the name of the template template
parameter, and a DW_AT_GNU_template_name attribute to represent the
name of the template template argument. */
tmpl_die = new_die (DW_TAG_GNU_template_template_param,
parent_die, parm);
else
gcc_unreachable ();
if (tmpl_die)
{
tree tmpl_type;
if (pack_elem_index >= 0)
{
/* 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);
}
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))
{
/* DWARF3, 5.6.8 says if PARM is a non-type generic parameter
TMPL_DIE should have a child DW_AT_type attribute that is set
to the type of the argument to PARM, which is ARG.
If PARM is a type generic parameter, TMPL_DIE should have a
child DW_AT_type that is set to ARG. */
tmpl_type = TYPE_P (arg) ? arg : TREE_TYPE (arg);
add_type_attribute (tmpl_die, tmpl_type, 0,
TREE_THIS_VOLATILE (tmpl_type),
parent_die);
}
else
{
/* So TMPL_DIE is a DIE representing a
a generic generic template parameter, a.k.a template template
parameter in C++ and arg is a template. */
/* The DW_AT_GNU_template_name attribute of the DIE must be set
to the name of the argument. */
name = dwarf2_name (TYPE_P (arg) ? TYPE_NAME (arg) : arg, 1);
add_AT_string (tmpl_die, DW_AT_GNU_template_name, name);
}
if (TREE_CODE (parm) == PARM_DECL)
/* So PARM is a non-type generic parameter.
DWARF3 5.6.8 says we must set a DW_AT_const_value child
attribute of TMPL_DIE which value represents the value
of ARG.
We must be careful here:
The value of ARG might reference some function decls.
We might currently be emitting debug info for a generic
type and types are emitted before function decls, we don't
know if the function decls referenced by ARG will actually be
emitted after cgraph computations.
So must defer the generation of the DW_AT_const_value to
after cgraph is ready. */
append_entry_to_tmpl_value_parm_die_table (tmpl_die, arg);
}
return tmpl_die;
}
/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
an enumerated type. */
@ -12057,17 +12260,20 @@ reference_to_unused (tree * tp, int * walk_subtrees,
else if (!cgraph_global_info_ready
&& (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
return *tp;
else if (DECL_P (*tp) && TREE_CODE (*tp) == VAR_DECL)
else if (TREE_CODE (*tp) == VAR_DECL)
{
struct varpool_node *node = varpool_node (*tp);
if (!node->needed)
return *tp;
}
else if (DECL_P (*tp) && TREE_CODE (*tp) == FUNCTION_DECL
else if (TREE_CODE (*tp) == FUNCTION_DECL
&& (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp)))
{
struct cgraph_node *node = cgraph_node (*tp);
if (node->process || TREE_ASM_WRITTEN (*tp))
/* The call graph machinery must have finished analyzing,
optimizing and gimplifying the CU by now.
So if *TP has no call graph node associated
to it, it means *TP will not be emitted. */
if (!cgraph_get_node (*tp))
return *tp;
}
else if (TREE_CODE (*tp) == STRING_CST && !TREE_ASM_WRITTEN (*tp))
@ -12639,7 +12845,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
}
/* None of that worked, so it must not really have a location;
try adding a constant value attribute from the DECL_INITIAL. */
tree_add_const_value_attribute (die, decl);
tree_add_const_value_attribute_for_decl (die, decl);
}
/* Add VARIABLE and DIE into deferred locations list. */
@ -12800,29 +13006,25 @@ native_encode_initializer (tree init, unsigned char *array, int size)
}
}
/* If we don't have a copy of this variable in memory for some reason (such
as a C++ member constant that doesn't have an out-of-line definition),
we should tell the debugger about the constant value. */
/* Attach a DW_AT_const_value attribute to DIE. The value of the
attribute is the const value T. */
static void
tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
tree_add_const_value_attribute (dw_die_ref die, tree t)
{
tree init;
tree type = TREE_TYPE (decl);
tree type = TREE_TYPE (t);
rtx rtl;
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL)
if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
return;
init = DECL_INITIAL (decl);
if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init)
/* OK */;
else
return;
init = t;
gcc_assert (!DECL_P (init));
rtl = rtl_for_decl_init (init, type);
if (rtl)
add_const_value_attribute (var_die, rtl);
add_const_value_attribute (die, rtl);
/* If the host and target are sane, try harder. */
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& initializer_constant_valid_p (init, type))
@ -12833,11 +13035,35 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
unsigned char *array = GGC_CNEWVEC (unsigned char, size);
if (native_encode_initializer (init, array, size))
add_AT_vec (var_die, DW_AT_const_value, size, 1, array);
add_AT_vec (die, DW_AT_const_value, size, 1, array);
}
}
}
/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
attribute is the const value of T, where T is an integral constant
variable with static storage duration
(so it can't be a PARM_DECL or a RESULT_DECL). */
static void
tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
{
if (!decl
|| (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != CONST_DECL))
return;
if (TREE_READONLY (decl)
&& ! TREE_THIS_VOLATILE (decl)
&& DECL_INITIAL (decl))
/* OK */;
else
return;
tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
}
/* Convert the CFI instructions for the current function into a
location list. This is used for DW_AT_frame_base when we targeting
a dwarf2 consumer that does not support the dwarf3
@ -14534,6 +14760,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
loc_descriptor_from_tree (cfun->static_chain_decl));
}
/* Generate child dies for template paramaters. */
if (debug_info_level > DINFO_LEVEL_TERSE)
gen_generic_params_dies (decl);
/* Now output descriptions of the arguments for this function. This gets
(unnecessarily?) complex because of the fact that the DECL_ARGUMENT list
for a FUNCTION_DECL doesn't indicate cases where there was a trailing
@ -14895,7 +15125,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
add_pubname (decl_or_origin, var_die);
}
else
tree_add_const_value_attribute (var_die, decl_or_origin);
tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
}
/* Generate a DIE to represent a named constant. */
@ -14913,7 +15143,7 @@ gen_const_die (tree decl, dw_die_ref context_die)
add_AT_flag (const_die, DW_AT_external, 1);
if (DECL_ARTIFICIAL (decl))
add_AT_flag (const_die, DW_AT_artificial, 1);
tree_add_const_value_attribute (const_die, decl);
tree_add_const_value_attribute_for_decl (const_die, decl);
}
/* Generate a DIE to represent a label identifier. */
@ -15332,6 +15562,11 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
else
remove_AT (type_die, DW_AT_declaration);
/* Generate child dies for template paramaters. */
if (debug_info_level > DINFO_LEVEL_TERSE
&& COMPLETE_TYPE_P (type))
gen_generic_params_dies (type);
/* If this type has been completed, then give it a byte_size attribute and
then give a list of members. */
if (complete && !ns_decl)
@ -16587,6 +16822,49 @@ maybe_emit_file (struct dwarf_file_data * fd)
return fd->emitted_number;
}
/* Schedule generation of a DW_AT_const_value attribute to DIE.
That generation should happen after function debug info has been
generated. The value of the attribute is the constant value of ARG. */
static void
append_entry_to_tmpl_value_parm_die_table (dw_die_ref die, tree arg)
{
die_arg_entry entry;
if (!die || !arg)
return;
if (!tmpl_value_parm_die_table)
tmpl_value_parm_die_table
= VEC_alloc (die_arg_entry, gc, 32);
entry.die = die;
entry.arg = arg;
VEC_safe_push (die_arg_entry, gc,
tmpl_value_parm_die_table,
&entry);
}
/* Add a DW_AT_const_value attribute to DIEs that were scheduled
by append_entry_to_tmpl_value_parm_die_table. This function must
be called after function DIEs have been generated. */
static void
gen_remaining_tmpl_value_param_die_attribute (void)
{
if (tmpl_value_parm_die_table)
{
unsigned i;
die_arg_entry *e;
for (i = 0;
VEC_iterate (die_arg_entry, tmpl_value_parm_die_table, i, e);
i++)
tree_add_const_value_attribute (e->die, e->arg);
}
}
/* Replace DW_AT_name for the decl with name. */
static void
@ -17346,6 +17624,8 @@ dwarf2out_finish (const char *filename)
dw_die_ref die = 0;
unsigned int i;
gen_remaining_tmpl_value_param_die_attribute ();
/* Add the name for the main input file now. We delayed this from
dwarf2out_init to avoid complications with PCH. */
add_name_attribute (comp_unit_die, remap_debug_filename (filename));

View File

@ -153,6 +153,10 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_CLASSIFY_RECORD NULL
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
#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_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_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
@ -170,6 +174,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_TYPE_FOR_MODE, \
LANG_HOOKS_TYPE_FOR_SIZE, \
LANG_HOOKS_GENERIC_TYPE_P, \
LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS, \
LANG_HOOKS_TYPE_PROMOTES_TO, \
LANG_HOOKS_REGISTER_BUILTIN_TYPE, \
LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \
@ -206,6 +211,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_PUSHDECL, \
LANG_HOOKS_GETDECLS, \
LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
LANG_HOOKS_WRITE_GLOBALS, \
LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
@ -259,6 +265,8 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_TREE_DUMP_INITIALIZER, \
LANG_HOOKS_DECLS, \
LANG_HOOKS_FOR_TYPES_INITIALIZER, \
LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
LANG_HOOKS_GIMPLIFY_EXPR, \
LANG_HOOKS_FOLD_OBJ_TYPE_REF, \
LANG_HOOKS_BUILTIN_FUNCTION, \

View File

@ -91,6 +91,9 @@ struct lang_hooks_for_types
e.g. C++ template implicit specializations. */
bool (*generic_p) (const_tree);
/* Returns the TREE_VEC of elements of a given generic argument pack. */
tree (*get_argument_pack_elems) (const_tree);
/* Given a type, apply default promotions to unnamed function
arguments and return the new type. Return the same type if no
change. Required by any language that supports variadic
@ -165,6 +168,10 @@ struct lang_hooks_for_decls
/* Returns true if DECL is explicit member function. */
bool (*function_decl_explicit_p) (tree);
/* Returns True if the parameter is a generic parameter decl
of a generic type, e.g a template template parameter for the C++ FE. */
bool (*generic_generic_parameter_decl_p) (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);
@ -380,6 +387,14 @@ struct lang_hooks
struct lang_hooks_for_types types;
/* Retuns the generic parameters of an instantiation of
a generic type or decl, e.g. C++ template instantiation. */
tree (*get_innermost_generic_parms) (const_tree);
/* Returns the TREE_VEC of arguments of an instantiation
of a generic type of decl, e.g. C++ template instantiation. */
tree (*get_innermost_generic_args) (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 *);

View File

@ -1,3 +1,20 @@
2009-08-31 Dodji Seketeli <dodji@redhat.com>
PR debug/30161
* g++.dg/debug/dwarf2/template-params-1.C: New test.
* g++.dg/debug/dwarf2/template-params-2.C: Likewise.
* g++.dg/debug/dwarf2/template-params-3.C: Likewise.
* g++.dg/debug/dwarf2/template-params-4.C: Likewise.
* g++.dg/debug/dwarf2/template-params-5.C: Likewise.
* g++.dg/debug/dwarf2/template-params-6.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-1.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-2.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-3.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-4.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-5.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-6.C: Likewise.
* g++.dg/debug/dwarf2/template-func-params-7.C: Likewise.
2009-08-31 Jason Merrill <jason@redhat.com>
PR c++/41127

View File

@ -0,0 +1,16 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-do compile }
// { dg-final { scan-assembler "DW_TAG_template_type_param" } }
// { dg-final { scan-assembler "U.*DW_AT_name" } }
template <class U>
U
func(U m)
{
return m;
}
int i = func<int>(2);

View File

@ -0,0 +1,22 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-do compile }
// { dg-final { scan-assembler "DW_TAG_template_value_param" } }
// { dg-final { scan-assembler "i.*DW_AT_name" } }
// { dg-final { scan-assembler "3.*DW_AT_const_value" } }
template <int i>
int
func()
{
int j = i;
return j;
}
const int foo = 1;
const int bar = 2;
int h = func<foo+bar>();

View File

@ -0,0 +1,24 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-final { scan-assembler "DW_TAG_template_value_param" } }
// { dg-final { scan-assembler "f.*DW_AT_name" } }
// { dg-final { scan-assembler "_Z4blehv.*DW_AT_const_value" } }
typedef void (*func_ptr)();
template <func_ptr f>
int
func()
{
f();
return 0;
}
void
bleh()
{
}
int c = func<bleh>();

View File

@ -0,0 +1,32 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// 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" } }
template <typename... Args> struct count;
template <>
struct count<>
{
static const int value = 0;
};
template <typename T, typename... Args>
struct count<T, Args...>
{
static const int value = 1 + count<Args...>::value;
};
template<typename... P>
int
do_count()
{
return count<P...>::value;
}
int c = do_count<int, char, long>();

View File

@ -0,0 +1,28 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-final { scan-assembler "DW_TAG_template_type_param" } }
// { dg-final { scan-assembler "T.*DW_AT_name" } }
template <class T>
struct vector
{
int size;
vector () : size (0)
{
}
};
template<template <class T> class U>
int
bar()
{
U<int> u;
return u.size;
}
vector<int> v;
int j = bar<vector>();

View File

@ -0,0 +1,38 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-final { scan-assembler-times "DW_TAG_GNU_template_template_param" 2 } }
// { dg-final { scan-assembler-times "DW_AT_GNU_template_name: \"vector\"" 1 } }
// { dg-final { scan-assembler-times ".ascii \"U.0\".*?DW_AT_name" 1 } }
template <class T>
struct vector_base
{
static int get_sizeof_t()
{
return 0;
}
};
template <class T>
struct vector : public vector_base<T>
{
static int get_sizeof_t()
{
return sizeof (T);
}
T member1;
T member2;
};
template <template <class T> class U>
int
bar()
{
return U<int>::get_sizeof_t();
}
int i = bar<vector>();

View File

@ -0,0 +1,61 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA -std=c++0x" }
// { dg-do compile }
// There must be 5 subprograms generated:
// printf(const char*), printf<int, char, int>,
// printf<char, int>, printf<int> and foo().
// { dg-final {scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_subprogram" 5 } }
// That makes 6 template type parameters.
// { dg-final {scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_template_type_param" 6 } }
// { dg-final {scan-assembler-times "DW_AT_name: \"printf<int, char, int>\"" 1 } }
// { dg-final {scan-assembler-times "DW_AT_name: \"printf<char, int>\"" 1 } }
// { dg-final {scan-assembler-times "DW_AT_name: \"printf<int>\"" 1 } }
// { dg-final {scan-assembler-times "DW_AT_name: \"printf\"" 1 } }
// printf<int, char, int> and printf<char, int> 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 "DW_AT_name: \"args#0\"" 2 } }
// { dg-final {scan-assembler-times "DW_AT_name: \"PackTypes#1\"" 1 } }
// { dg-final {scan-assembler-times "DW_AT_name: \"args#1\"" 1 } }
// { dg_final {scan-assembler-times "\.ascii \"T.0\"\[\t \]+.*?DW_AT_name" 3 } }
void
printf(const char* s)
{
/* Commented this to not pull std::cout into what should be
a simple test.
while (*s)
std::cout << *s++;
*/
}
template<typename T, typename... PackTypes>
void
printf(const char* s,
T value,
PackTypes... args)
{
while (*s)
{
if (*s == '%' && *++s != '%')
{
/* std::cout << value; */
return printf(++s, args...);
}
}
}
void
foo ()
{
int x;
printf("%c %d", x, 'x', 3);
}

View File

@ -0,0 +1,15 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-do compile }
// { dg-final { scan-assembler "DW_TAG_template_type_param" } }
// { dg-final { scan-assembler "U.*DW_AT_name" } }
template <class U>
class A
{
U m;
};
A<int> a;

View File

@ -0,0 +1,23 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-do compile }
// { dg-final { scan-assembler "DW_TAG_template_value_param" } }
// { dg-final { scan-assembler "i.*DW_AT_name" } }
// { dg-final { scan-assembler "3.*DW_AT_const_value" } }
template <int i>
struct A
{
int m;
A ()
{
m = i;
}
};
const int foo = 1;
const int bar = 2;
A<foo+bar> a;

View File

@ -0,0 +1,25 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-final { scan-assembler "DW_TAG_template_value_param" } }
// { dg-final { scan-assembler "f.*DW_AT_name" } }
// { dg-final { scan-assembler "_Z4blehv.*DW_AT_const_value" } }
typedef void (*func_ptr) ();
template <func_ptr f>
struct A
{
A ()
{
f ();
}
};
void
bleh ()
{
}
A<bleh> a;

View File

@ -0,0 +1,30 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// 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" } }
template <typename... Args> struct count;
template <>
struct count<>
{
static const int value = 0;
};
template <typename T, typename... Args>
struct count<T, Args...>
{
static const int value = 1 + count<Args...>::value;
};
int
foo ()
{
count<int, char, long> c;
int nb = count<int, char, long>::value;
return nb;
}

View File

@ -0,0 +1,29 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-final { scan-assembler "DW_TAG_template_type_param" } }
// { dg-final { scan-assembler "T.*DW_AT_name" } }
template <class T>
struct vector
{
int size;
vector () : size (0)
{
}
};
template<template <class T> class U>
struct bar
{
U<int> u;
int m;
bar () : m (u.size)
{
}
};
vector<int> v;
bar<vector> b;

View File

@ -0,0 +1,44 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR debug/30161
// { dg-options "-g -dA" }
// { dg-final { scan-assembler-times "DW_TAG_GNU_template_template_param" 2 } }
// { dg-final { scan-assembler-times "DW_AT_GNU_template_name: \"vector\"" 1 } }
// { dg-final { scan-assembler-times ".ascii \"U.0\".*?DW_AT_name" 1 } }
template <class T>
struct vector_base
{
T tab[3 + 1];
static int get_sizeof_t()
{
return sizeof (tab);
}
};
template <class T>
struct vector : public vector_base<T>
{
static int get_sizeof_t()
{
return sizeof (T);
}
T member1;
T member2;
};
template <template <class T> class U>
struct bar
{
int foo()
{
return U<int>::get_sizeof_t ();
}
};
int
foo_func ()
{
bar<vector> b;
return b.foo ();
}

View File

@ -210,6 +210,9 @@ enum dwarf_tag
DW_TAG_class_template = 0x4103, /* For C++. */
DW_TAG_GNU_BINCL = 0x4104,
DW_TAG_GNU_EINCL = 0x4105,
/* Template template parameter.
See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */
DW_TAG_GNU_template_template_param = 0x4106,
/* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
DW_TAG_upc_shared_type = 0x8765,
DW_TAG_upc_strict_type = 0x8766,
@ -390,6 +393,9 @@ enum dwarf_attribute
DW_AT_body_begin = 0x2105,
DW_AT_body_end = 0x2106,
DW_AT_GNU_vector = 0x2107,
/* Template template argument name.
See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */
DW_AT_GNU_template_name = 0x2110,
/* VMS extensions. */
DW_AT_VMS_rtnbeg_pd_address = 0x2201,
/* UPC extension. */