Commit f9329c35 by Dodji Seketeli Committed by Dodji Seketeli

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
parent e756464b
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> 2009-08-30 Paolo Bonzini <bonzini@gnu.org>
* Makefile.tpl (AWK): Fix typo. * Makefile.tpl (AWK): Fix typo.
......
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> 2009-08-31 DJ Delorie <dj@redhat.com>
* config/mep/mep.c (machine_function): Add frame_locked flag. Set * config/mep/mep.c (machine_function): Add frame_locked flag. Set
...@@ -11,6 +55,7 @@ ...@@ -11,6 +55,7 @@
(mep_return_in_memory): Zero-sized objects are passed in memory. (mep_return_in_memory): Zero-sized objects are passed in memory.
(mep_reorg_noframe): Make sure we have accurate REG_DEAD notes. (mep_reorg_noframe): Make sure we have accurate REG_DEAD notes.
2009-08-31 Richard Guenther <rguenther@suse.de> 2009-08-31 Richard Guenther <rguenther@suse.de>
* builtins.c (fold_builtin_memory_op): Use the alias oracle * builtins.c (fold_builtin_memory_op): Use the alias oracle
......
...@@ -493,6 +493,29 @@ cgraph_node (tree decl) ...@@ -493,6 +493,29 @@ cgraph_node (tree decl)
return node; 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. */ /* Insert already constructed node into hashtable. */
void void
......
...@@ -388,6 +388,8 @@ void cgraph_node_remove_callees (struct cgraph_node *node); ...@@ -388,6 +388,8 @@ void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node *, struct cgraph_node *,
gimple, gcov_type, int, int); gimple, gcov_type, int, int);
struct cgraph_node * cgraph_get_node (tree);
struct cgraph_node *cgraph_node (tree); struct cgraph_node *cgraph_node (tree);
struct cgraph_node *cgraph_node_for_asm (tree asmname); struct cgraph_node *cgraph_node_for_asm (tree asmname);
struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple); struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
......
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> 2009-08-31 Jason Merrill <jason@redhat.com>
PR c++/41127 PR c++/41127
......
...@@ -49,6 +49,20 @@ static enum classify_record cp_classify_record (tree type); ...@@ -49,6 +49,20 @@ static enum classify_record cp_classify_record (tree type);
#define LANG_HOOKS_CLASSIFY_RECORD cp_classify_record #define LANG_HOOKS_CLASSIFY_RECORD cp_classify_record
#undef LANG_HOOKS_GENERIC_TYPE_P #undef LANG_HOOKS_GENERIC_TYPE_P
#define LANG_HOOKS_GENERIC_TYPE_P class_tmpl_impl_spec_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 #undef LANG_HOOKS_DECL_PRINTABLE_NAME
#define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name #define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name
#undef LANG_HOOKS_DWARF_NAME #undef LANG_HOOKS_DWARF_NAME
......
...@@ -3283,7 +3283,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -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) \ #define CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P(NODE) \
(CLASS_TYPE_P (NODE) \ (CLASS_TYPE_P (NODE) \
&& CLASSTYPE_USE_TEMPLATE (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 DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \ #define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
...@@ -4638,7 +4638,7 @@ extern bool uses_parameter_packs (tree); ...@@ -4638,7 +4638,7 @@ extern bool uses_parameter_packs (tree);
extern bool template_parameter_pack_p (const_tree); extern bool template_parameter_pack_p (const_tree);
extern tree make_pack_expansion (tree); extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (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 tree get_types_needing_access_check (tree);
extern int template_class_depth (tree); extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree); extern int is_specialization_of (tree, tree);
...@@ -4680,6 +4680,10 @@ extern bool explicit_class_specialization_p (tree); ...@@ -4680,6 +4680,10 @@ extern bool explicit_class_specialization_p (tree);
extern struct tinst_level *outermost_tinst_level(void); extern struct tinst_level *outermost_tinst_level(void);
extern bool parameter_of_template_p (tree, tree); extern bool parameter_of_template_p (tree, tree);
extern void init_template_processing (void); 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 */ /* in repo.c */
extern void init_repo (void); extern void init_repo (void);
......
...@@ -191,6 +191,7 @@ static tree tsubst_decl (tree, tree, tsubst_flags_t); ...@@ -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 perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree); 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 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 /* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function processing T. T can be FUNCTION_DECL for instantiated function
...@@ -287,7 +288,7 @@ finish_member_template_decl (tree decl) ...@@ -287,7 +288,7 @@ finish_member_template_decl (tree decl)
/* Return the template info node corresponding to T, whatever T is. */ /* Return the template info node corresponding to T, whatever T is. */
tree tree
get_template_info (tree t) get_template_info (const_tree t)
{ {
tree tinfo = NULL_TREE; tree tinfo = NULL_TREE;
...@@ -2660,15 +2661,90 @@ static tree ...@@ -2660,15 +2661,90 @@ static tree
make_ith_pack_parameter_name (tree name, int i) make_ith_pack_parameter_name (tree name, int i)
{ {
/* Munge the name to include the parameter index. */ /* Munge the name to include the parameter index. */
char numbuf[128]; #define NUMBUF_LEN 128
char numbuf[NUMBUF_LEN];
char* newname; char* newname;
int newname_len;
sprintf(numbuf, "%i", i);
newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2); snprintf (numbuf, NUMBUF_LEN, "%i", i);
sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), 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 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. */ /* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data struct find_parameter_pack_data
{ {
......
...@@ -5551,6 +5551,14 @@ static GTY ((param_is (struct die_struct))) htab_t decl_die_table; ...@@ -5551,6 +5551,14 @@ static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
The key is DECL_UID() ^ die_parent. */ The key is DECL_UID() ^ die_parent. */
static GTY ((param_is (struct die_struct))) htab_t common_block_die_table; 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. */ /* Node of the variable location list. */
struct GTY ((chain_next ("%h.next"))) var_loc_node { struct GTY ((chain_next ("%h.next"))) var_loc_node {
rtx GTY (()) var_loc_note; rtx GTY (()) var_loc_note;
...@@ -5691,6 +5699,8 @@ static GTY(()) struct dwarf_file_data * file_table_last_lookup; ...@@ -5691,6 +5699,8 @@ static GTY(()) struct dwarf_file_data * file_table_last_lookup;
within the current function. */ within the current function. */
static HOST_WIDE_INT frame_pointer_fb_offset; 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. */ /* Forward declarations for functions defined in this file. */
static int is_pseudo_reg (const_rtx); static int is_pseudo_reg (const_rtx);
...@@ -5826,6 +5836,7 @@ static dw_die_ref base_type_die (tree); ...@@ -5826,6 +5836,7 @@ static dw_die_ref base_type_die (tree);
static int is_base_type (tree); static int is_base_type (tree);
static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref); 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 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 int type_is_enum (const_tree);
static unsigned int dbx_reg_number (const_rtx); static unsigned int dbx_reg_number (const_rtx);
static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
...@@ -5861,6 +5872,7 @@ static rtx rtl_for_decl_location (tree); ...@@ -5861,6 +5872,7 @@ static rtx rtl_for_decl_location (tree);
static void add_location_or_const_value_attribute (dw_die_ref, tree, static void add_location_or_const_value_attribute (dw_die_ref, tree,
enum dwarf_attribute); enum dwarf_attribute);
static void tree_add_const_value_attribute (dw_die_ref, tree); 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_name_attribute (dw_die_ref, const char *);
static void add_comp_dir_attribute (dw_die_ref); static void add_comp_dir_attribute (dw_die_ref);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree); 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); ...@@ -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 struct dwarf_file_data * lookup_filename (const char *);
static void retry_incomplete_types (void); static void retry_incomplete_types (void);
static void gen_type_die_for_member (tree, tree, dw_die_ref); 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 void splice_child_die (dw_die_ref, dw_die_ref);
static int file_info_cmp (const void *, const void *); static int file_info_cmp (const void *, const void *);
static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, 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); ...@@ -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_prune (dw_die_ref);
static void prune_unused_types (void); static void prune_unused_types (void);
static int maybe_emit_file (struct dwarf_file_data *fd); 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. */ /* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION #ifndef DEBUG_INFO_SECTION
...@@ -6237,6 +6253,8 @@ dwarf_tag_name (unsigned int tag) ...@@ -6237,6 +6253,8 @@ dwarf_tag_name (unsigned int tag)
return "DW_TAG_GNU_BINCL"; return "DW_TAG_GNU_BINCL";
case DW_TAG_GNU_EINCL: case DW_TAG_GNU_EINCL:
return "DW_TAG_GNU_EINCL"; return "DW_TAG_GNU_EINCL";
case DW_TAG_GNU_template_template_param:
return "DW_TAG_GNU_template_template_param";
default: default:
return "DW_TAG_<unknown>"; return "DW_TAG_<unknown>";
} }
...@@ -6438,6 +6456,8 @@ dwarf_attr_name (unsigned int attr) ...@@ -6438,6 +6456,8 @@ dwarf_attr_name (unsigned int attr)
return "DW_AT_body_end"; return "DW_AT_body_end";
case DW_AT_GNU_vector: case DW_AT_GNU_vector:
return "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: case DW_AT_VMS_rtnbeg_pd_address:
return "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, ...@@ -10353,6 +10373,189 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
return mod_type_die; 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 /* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
an enumerated type. */ an enumerated type. */
...@@ -12057,17 +12260,20 @@ reference_to_unused (tree * tp, int * walk_subtrees, ...@@ -12057,17 +12260,20 @@ reference_to_unused (tree * tp, int * walk_subtrees,
else if (!cgraph_global_info_ready else if (!cgraph_global_info_ready
&& (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL)) && (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
return *tp; 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); struct varpool_node *node = varpool_node (*tp);
if (!node->needed) if (!node->needed)
return *tp; 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))) && (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp)))
{ {
struct cgraph_node *node = cgraph_node (*tp); /* The call graph machinery must have finished analyzing,
if (node->process || TREE_ASM_WRITTEN (*tp)) 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; return *tp;
} }
else if (TREE_CODE (*tp) == STRING_CST && !TREE_ASM_WRITTEN (*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, ...@@ -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; /* None of that worked, so it must not really have a location;
try adding a constant value attribute from the DECL_INITIAL. */ 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. */ /* Add VARIABLE and DIE into deferred locations list. */
...@@ -12800,29 +13006,25 @@ native_encode_initializer (tree init, unsigned char *array, int size) ...@@ -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 /* Attach a DW_AT_const_value attribute to DIE. The value of the
as a C++ member constant that doesn't have an out-of-line definition), attribute is the const value T. */
we should tell the debugger about the constant value. */
static void 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 init;
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (t);
rtx rtl; 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; return;
init = DECL_INITIAL (decl); init = t;
if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init) gcc_assert (!DECL_P (init));
/* OK */;
else
return;
rtl = rtl_for_decl_init (init, type); rtl = rtl_for_decl_init (init, type);
if (rtl) if (rtl)
add_const_value_attribute (var_die, rtl); add_const_value_attribute (die, rtl);
/* If the host and target are sane, try harder. */ /* If the host and target are sane, try harder. */
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8 else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& initializer_constant_valid_p (init, type)) && initializer_constant_valid_p (init, type))
...@@ -12833,11 +13035,35 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl) ...@@ -12833,11 +13035,35 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
unsigned char *array = GGC_CNEWVEC (unsigned char, size); unsigned char *array = GGC_CNEWVEC (unsigned char, size);
if (native_encode_initializer (init, array, 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 /* Convert the CFI instructions for the current function into a
location list. This is used for DW_AT_frame_base when we targeting location list. This is used for DW_AT_frame_base when we targeting
a dwarf2 consumer that does not support the dwarf3 a dwarf2 consumer that does not support the dwarf3
...@@ -14534,6 +14760,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) ...@@ -14534,6 +14760,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
loc_descriptor_from_tree (cfun->static_chain_decl)); 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 /* Now output descriptions of the arguments for this function. This gets
(unnecessarily?) complex because of the fact that the DECL_ARGUMENT list (unnecessarily?) complex because of the fact that the DECL_ARGUMENT list
for a FUNCTION_DECL doesn't indicate cases where there was a trailing 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) ...@@ -14895,7 +15125,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
add_pubname (decl_or_origin, var_die); add_pubname (decl_or_origin, var_die);
} }
else 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. */ /* Generate a DIE to represent a named constant. */
...@@ -14913,7 +15143,7 @@ gen_const_die (tree decl, dw_die_ref context_die) ...@@ -14913,7 +15143,7 @@ gen_const_die (tree decl, dw_die_ref context_die)
add_AT_flag (const_die, DW_AT_external, 1); add_AT_flag (const_die, DW_AT_external, 1);
if (DECL_ARTIFICIAL (decl)) if (DECL_ARTIFICIAL (decl))
add_AT_flag (const_die, DW_AT_artificial, 1); 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. */ /* 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, ...@@ -15332,6 +15562,11 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
else else
remove_AT (type_die, DW_AT_declaration); 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 /* If this type has been completed, then give it a byte_size attribute and
then give a list of members. */ then give a list of members. */
if (complete && !ns_decl) if (complete && !ns_decl)
...@@ -16587,6 +16822,49 @@ maybe_emit_file (struct dwarf_file_data * fd) ...@@ -16587,6 +16822,49 @@ maybe_emit_file (struct dwarf_file_data * fd)
return fd->emitted_number; 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. */ /* Replace DW_AT_name for the decl with name. */
static void static void
...@@ -17346,6 +17624,8 @@ dwarf2out_finish (const char *filename) ...@@ -17346,6 +17624,8 @@ dwarf2out_finish (const char *filename)
dw_die_ref die = 0; dw_die_ref die = 0;
unsigned int i; unsigned int i;
gen_remaining_tmpl_value_param_die_attribute ();
/* Add the name for the main input file now. We delayed this from /* Add the name for the main input file now. We delayed this from
dwarf2out_init to avoid complications with PCH. */ dwarf2out_init to avoid complications with PCH. */
add_name_attribute (comp_unit_die, remap_debug_filename (filename)); add_name_attribute (comp_unit_die, remap_debug_filename (filename));
......
...@@ -153,6 +153,10 @@ extern tree lhd_make_node (enum tree_code); ...@@ -153,6 +153,10 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_CLASSIFY_RECORD NULL #define LANG_HOOKS_CLASSIFY_RECORD NULL
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error #define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
#define LANG_HOOKS_GENERIC_TYPE_P hook_bool_const_tree_false #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_TYPE_PROMOTES_TO lhd_type_promotes_to
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type
#define LANG_HOOKS_TYPE_MAX_SIZE lhd_return_null_const_tree #define LANG_HOOKS_TYPE_MAX_SIZE lhd_return_null_const_tree
...@@ -170,6 +174,7 @@ extern tree lhd_make_node (enum tree_code); ...@@ -170,6 +174,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_TYPE_FOR_MODE, \ LANG_HOOKS_TYPE_FOR_MODE, \
LANG_HOOKS_TYPE_FOR_SIZE, \ LANG_HOOKS_TYPE_FOR_SIZE, \
LANG_HOOKS_GENERIC_TYPE_P, \ LANG_HOOKS_GENERIC_TYPE_P, \
LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS, \
LANG_HOOKS_TYPE_PROMOTES_TO, \ LANG_HOOKS_TYPE_PROMOTES_TO, \
LANG_HOOKS_REGISTER_BUILTIN_TYPE, \ LANG_HOOKS_REGISTER_BUILTIN_TYPE, \
LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \ LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \
...@@ -206,6 +211,7 @@ extern tree lhd_make_node (enum tree_code); ...@@ -206,6 +211,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_PUSHDECL, \ LANG_HOOKS_PUSHDECL, \
LANG_HOOKS_GETDECLS, \ LANG_HOOKS_GETDECLS, \
LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \ LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \ LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
LANG_HOOKS_WRITE_GLOBALS, \ LANG_HOOKS_WRITE_GLOBALS, \
LANG_HOOKS_DECL_OK_FOR_SIBCALL, \ LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
...@@ -259,6 +265,8 @@ extern tree lhd_make_node (enum tree_code); ...@@ -259,6 +265,8 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_TREE_DUMP_INITIALIZER, \ LANG_HOOKS_TREE_DUMP_INITIALIZER, \
LANG_HOOKS_DECLS, \ LANG_HOOKS_DECLS, \
LANG_HOOKS_FOR_TYPES_INITIALIZER, \ LANG_HOOKS_FOR_TYPES_INITIALIZER, \
LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
LANG_HOOKS_GIMPLIFY_EXPR, \ LANG_HOOKS_GIMPLIFY_EXPR, \
LANG_HOOKS_FOLD_OBJ_TYPE_REF, \ LANG_HOOKS_FOLD_OBJ_TYPE_REF, \
LANG_HOOKS_BUILTIN_FUNCTION, \ LANG_HOOKS_BUILTIN_FUNCTION, \
......
...@@ -91,6 +91,9 @@ struct lang_hooks_for_types ...@@ -91,6 +91,9 @@ struct lang_hooks_for_types
e.g. C++ template implicit specializations. */ e.g. C++ template implicit specializations. */
bool (*generic_p) (const_tree); 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 /* Given a type, apply default promotions to unnamed function
arguments and return the new type. Return the same type if no arguments and return the new type. Return the same type if no
change. Required by any language that supports variadic change. Required by any language that supports variadic
...@@ -165,6 +168,10 @@ struct lang_hooks_for_decls ...@@ -165,6 +168,10 @@ struct lang_hooks_for_decls
/* Returns true if DECL is explicit member function. */ /* Returns true if DECL is explicit member function. */
bool (*function_decl_explicit_p) (tree); 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. /* Returns true when we should warn for an unused global DECL.
We will already have checked that it has static binding. */ We will already have checked that it has static binding. */
bool (*warn_unused_global) (const_tree); bool (*warn_unused_global) (const_tree);
...@@ -380,6 +387,14 @@ struct lang_hooks ...@@ -380,6 +387,14 @@ struct lang_hooks
struct lang_hooks_for_types types; 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 /* Perform language-specific gimplification on the argument. Returns an
enum gimplify_status, though we can't see that type here. */ enum gimplify_status, though we can't see that type here. */
int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *); int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *);
......
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> 2009-08-31 Jason Merrill <jason@redhat.com>
PR c++/41127 PR c++/41127
......
// 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);
// 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>();
// 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>();
// 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>();
// 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>();
// 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>();
// 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);
}
// 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;
// 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;
// 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;
// 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;
}
// 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;
// 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 ();
}
...@@ -210,6 +210,9 @@ enum dwarf_tag ...@@ -210,6 +210,9 @@ enum dwarf_tag
DW_TAG_class_template = 0x4103, /* For C++. */ DW_TAG_class_template = 0x4103, /* For C++. */
DW_TAG_GNU_BINCL = 0x4104, DW_TAG_GNU_BINCL = 0x4104,
DW_TAG_GNU_EINCL = 0x4105, 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. */ /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
DW_TAG_upc_shared_type = 0x8765, DW_TAG_upc_shared_type = 0x8765,
DW_TAG_upc_strict_type = 0x8766, DW_TAG_upc_strict_type = 0x8766,
...@@ -390,6 +393,9 @@ enum dwarf_attribute ...@@ -390,6 +393,9 @@ enum dwarf_attribute
DW_AT_body_begin = 0x2105, DW_AT_body_begin = 0x2105,
DW_AT_body_end = 0x2106, DW_AT_body_end = 0x2106,
DW_AT_GNU_vector = 0x2107, DW_AT_GNU_vector = 0x2107,
/* Template template argument name.
See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */
DW_AT_GNU_template_name = 0x2110,
/* VMS extensions. */ /* VMS extensions. */
DW_AT_VMS_rtnbeg_pd_address = 0x2201, DW_AT_VMS_rtnbeg_pd_address = 0x2201,
/* UPC extension. */ /* UPC extension. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment