mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-05 14:59:45 +08:00
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:
parent
e756464b1f
commit
f9329c35d7
@ -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.
|
||||
|
@ -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
|
||||
|
23
gcc/cgraph.c
23
gcc/cgraph.c
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
86
gcc/cp/pt.c
86
gcc/cp/pt.c
@ -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;
|
||||
int newname_len;
|
||||
|
||||
sprintf(numbuf, "%i", i);
|
||||
newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2);
|
||||
sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), i);
|
||||
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
|
||||
{
|
||||
|
320
gcc/dwarf2out.c
320
gcc/dwarf2out.c
@ -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));
|
||||
|
@ -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, \
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
16
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-1.C
Normal file
16
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-1.C
Normal 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);
|
||||
|
22
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-2.C
Normal file
22
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-2.C
Normal 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>();
|
||||
|
24
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-3.C
Normal file
24
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-3.C
Normal 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>();
|
||||
|
32
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C
Normal file
32
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C
Normal 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>();
|
||||
|
28
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-5.C
Normal file
28
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-5.C
Normal 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>();
|
||||
|
38
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-6.C
Normal file
38
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-6.C
Normal 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>();
|
||||
|
||||
|
61
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C
Normal file
61
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C
Normal 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);
|
||||
}
|
15
gcc/testsuite/g++.dg/debug/dwarf2/template-params-1.C
Normal file
15
gcc/testsuite/g++.dg/debug/dwarf2/template-params-1.C
Normal 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;
|
||||
|
23
gcc/testsuite/g++.dg/debug/dwarf2/template-params-2.C
Normal file
23
gcc/testsuite/g++.dg/debug/dwarf2/template-params-2.C
Normal 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;
|
||||
|
25
gcc/testsuite/g++.dg/debug/dwarf2/template-params-3.C
Normal file
25
gcc/testsuite/g++.dg/debug/dwarf2/template-params-3.C
Normal 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;
|
||||
|
30
gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C
Normal file
30
gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C
Normal 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;
|
||||
}
|
||||
|
29
gcc/testsuite/g++.dg/debug/dwarf2/template-params-5.C
Normal file
29
gcc/testsuite/g++.dg/debug/dwarf2/template-params-5.C
Normal 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;
|
||||
|
44
gcc/testsuite/g++.dg/debug/dwarf2/template-params-6.C
Normal file
44
gcc/testsuite/g++.dg/debug/dwarf2/template-params-6.C
Normal 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 ();
|
||||
}
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user