OSDN Git Service

Emit DWARF for template parameters (PR debug/30161)
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Aug 2009 21:48:04 +0000 (21:48 +0000)
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 Aug 2009 21:48:04 +0000 (21:48 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151249 138bc75d-0d04-0410-961f-82ee72b054a4

26 files changed:
ChangeLog
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cp/ChangeLog
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/dwarf2out.c
gcc/langhooks-def.h
gcc/langhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-params-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-params-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-params-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-params-5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/template-params-6.C [new file with mode: 0644]
include/dwarf2.h

index 1e010ad..971e402 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
index e8f8302..7acb781 100644 (file)
@@ -1,3 +1,47 @@
+2009-08-31  Dodji Seketeli  <dodji@redhat.com>
+
+       PR debug/30161
+       * cgraph.h (cgraph_get_node): Declare ...
+       * cgraph.c (cgraph_get_node): ... new function.
+       * dwarf2out.c (gen_generic_params_dies,
+       generic_parameter_die, tree_add_const_value_attribute_for_decl,
+       make_ith_pack_parameter_name,
+       append_entry_to_tmpl_value_parm_die_table,
+       gen_remaining_tmpl_value_param_die_attribute): New functions.
+       (gen_subprogram_die): Generate debug info for template parameters
+       if debug info level is higher than DINFO_LEVEL_TERSE.
+       Use tree_add_const_value_attribute_for_decl instead of
+       tree_add_const_value_attribute.
+       (gen_const_die): Use tree_add_const_value_attribute_for_decl
+       instead of tree_add_const_value_attribute.
+       (gen_struct_or_union_type_die): Generate debug
+       info for template parameters if debug info level is higher than
+       DINFO_LEVEL_TERSE.
+       (tree_add_const_value_attribute): Handle integral and pointer
+       constants. Update comment.
+       (dwarf_tag_name): Support DW_TAG_GNU_template_template_param.
+       (dwarf_attr_name): Support DW_AT_GNU_template_name.
+       (reference_to_unused): Fix thinko. Remove redundant predicates from
+       tests.
+       (tree_add_const_value_attribute): Make this work for constant
+       expressions only.
+       tree_add_const_value_attribute_for_decl is to be used for variable
+       DECLs now.
+       (add_location_or_const_value_attribute): Use
+       tree_add_const_value_attribute_for_decl now.
+       (dwarf2out_finish): Emit the DW_AT_const_value attribute of
+       DW_TAG_template_value_param DIEs after function DIEs have been
+       emitted.
+       * langhooks.h (lang_hooks_for_types): Add
+       get_argument_pack_elems.
+       (lang_hooks_for_decls): Add generic_generic_parameter_decl_p.
+       (lang_hooks): Added get_innermost_generic_parms,
+       get_innermost_generic_args.
+       * langhooks-def.h (LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS,
+       LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS,
+       LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS,
+       LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P): New language hooks.
+
 2009-08-31  DJ Delorie  <dj@redhat.com>
 
        * config/mep/mep.c (machine_function): Add frame_locked flag.  Set
@@ -11,6 +55,7 @@
        (mep_return_in_memory): Zero-sized objects are passed in memory.
        (mep_reorg_noframe): Make sure we have accurate REG_DEAD notes.
 
+
 2009-08-31  Richard Guenther  <rguenther@suse.de>
 
        * builtins.c (fold_builtin_memory_op): Use the alias oracle
index ded99f9..f7a0f96 100644 (file)
@@ -493,6 +493,29 @@ cgraph_node (tree decl)
   return node;
 }
 
+/* Returns the cgraph node assigned to DECL or NULL if no cgraph node
+   is assigned.  */
+
+struct cgraph_node *
+cgraph_get_node (tree decl)
+{
+  struct cgraph_node key, *node = NULL, **slot;
+
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+
+  if (!cgraph_hash)
+    cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
+
+  key.decl = decl;
+
+  slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
+                                                NO_INSERT);
+
+  if (slot && *slot)
+    node = *slot;
+  return node;
+}
+
 /* Insert already constructed node into hashtable.  */
 
 void
index 3e19520..6eadc27 100644 (file)
@@ -388,6 +388,8 @@ void cgraph_node_remove_callees (struct cgraph_node *node);
 struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
                                        struct cgraph_node *,
                                        gimple, gcov_type, int, int);
+
+struct cgraph_node * cgraph_get_node (tree);
 struct cgraph_node *cgraph_node (tree);
 struct cgraph_node *cgraph_node_for_asm (tree asmname);
 struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
index 78d075e..fa5bc97 100644 (file)
@@ -1,3 +1,26 @@
+2009-08-31  Dodji Seketeli  <dodji@redhat.com>
+
+       PR debug/30161
+       * cp-tree.h (get_template_info): Parameter should be const.
+       (CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P): Fix typo.
+       (get_template_argument_pack_elems,
+       get_primary_template_innermost_parameters,
+       get_template_innermost_arguments, template_template_parameter_p):
+       Declare ...
+       * pt.c (get_template_argument_pack_elems,
+       get_template_innermost_parameters, get_template_innermost_arguments,
+       template_template_parameter_p):
+       ... New C++ front end implementation of new language hooks.
+       (primary_template_instantiation_p): New private helper.
+       (make_ith_pack_parameter_name): Use snprintf and strnlen instead of
+       printf and strlen.
+       (get_template_info): Const-ify parameter.
+       * cp-lang.c (LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS,
+       LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS,
+       LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS,
+       LANG_HOOKS_GENERIC_TYPE_PARAMETER_DECL_P): Initialize these
+       interfaces for the C++ front-end.
+
 2009-08-31  Jason Merrill  <jason@redhat.com>
 
        PR c++/41127
index c8fa77c..bd35a65 100644 (file)
@@ -49,6 +49,20 @@ static enum classify_record cp_classify_record (tree type);
 #define LANG_HOOKS_CLASSIFY_RECORD cp_classify_record
 #undef LANG_HOOKS_GENERIC_TYPE_P
 #define LANG_HOOKS_GENERIC_TYPE_P class_tmpl_impl_spec_p
+
+#undef LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS
+#define LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS \
+       get_primary_template_innermost_parameters
+#undef LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS
+#define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS \
+       get_template_innermost_arguments
+#undef LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS
+#define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS \
+       get_template_argument_pack_elems
+#undef LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P
+#define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P \
+       template_template_parameter_p
+
 #undef LANG_HOOKS_DECL_PRINTABLE_NAME
 #define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name
 #undef LANG_HOOKS_DWARF_NAME
index ff9ca7b..4480103 100644 (file)
@@ -3283,7 +3283,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P(NODE)   \
   (CLASS_TYPE_P (NODE)                                         \
    && CLASSTYPE_USE_TEMPLATE (NODE)                            \
-   && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))  
+   && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
 
 #define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
 #define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
@@ -4638,7 +4638,7 @@ extern bool uses_parameter_packs                (tree);
 extern bool template_parameter_pack_p           (const_tree);
 extern tree make_pack_expansion                 (tree);
 extern bool check_for_bare_parameter_packs      (tree);
-extern tree get_template_info                  (tree);
+extern tree get_template_info                  (const_tree);
 extern tree get_types_needing_access_check     (tree);
 extern int template_class_depth                        (tree);
 extern int is_specialization_of                        (tree, tree);
@@ -4680,6 +4680,10 @@ extern bool explicit_class_specialization_p     (tree);
 extern struct tinst_level *outermost_tinst_level(void);
 extern bool parameter_of_template_p            (tree, tree);
 extern void init_template_processing           (void);
+bool template_template_parameter_p             (const_tree);
+extern tree get_primary_template_innermost_parameters  (const_tree);
+extern tree get_template_innermost_arguments   (const_tree);
+extern tree get_template_argument_pack_elems   (const_tree);
 
 /* in repo.c */
 extern void init_repo                          (void);
index b856140..03b89fa 100644 (file)
@@ -191,6 +191,7 @@ static tree tsubst_decl (tree, tree, tsubst_flags_t);
 static void perform_typedefs_access_check (tree tmpl, tree targs);
 static void append_type_to_template_for_access_check_1 (tree, tree, tree);
 static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
+static bool primary_template_instantiation_p (const_tree);
 
 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -287,7 +288,7 @@ finish_member_template_decl (tree decl)
 /* Return the template info node corresponding to T, whatever T is.  */
 
 tree
-get_template_info (tree t)
+get_template_info (const_tree t)
 {
   tree tinfo = NULL_TREE;
 
@@ -2660,15 +2661,90 @@ static tree
 make_ith_pack_parameter_name (tree name, int i)
 {
   /* Munge the name to include the parameter index.  */
-  char numbuf[128];
+#define NUMBUF_LEN 128
+  char numbuf[NUMBUF_LEN];
   char* newname;
-  
-  sprintf(numbuf, "%i", i);
-  newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2);
-  sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), i);
+  int newname_len;
+
+  snprintf (numbuf, NUMBUF_LEN, "%i", i);
+  newname_len = IDENTIFIER_LENGTH (name)
+               + strnlen (numbuf, NUMBUF_LEN) + 2;
+  newname = (char*)alloca (newname_len);
+  snprintf (newname, newname_len,
+           "%s#%i", IDENTIFIER_POINTER (name), i);
   return get_identifier (newname);
 }
 
+/* Return true if T is a primary function
+   or class template instantiation.  */
+
+static bool
+primary_template_instantiation_p (const_tree t)
+{
+  if (!t)
+    return false;
+
+  if (TREE_CODE (t) == FUNCTION_DECL)
+    return DECL_LANG_SPECIFIC (t)
+          && DECL_TEMPLATE_INSTANTIATION (t)
+          && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
+  else if (CLASS_TYPE_P (t))
+    return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
+          && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
+  return false;
+}
+
+/* Return true if PARM is a template template parameter.  */
+
+bool
+template_template_parameter_p (const_tree parm)
+{
+  return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
+}
+
+/* Return the template parameters of T if T is a
+   primary template instantiation, NULL otherwise.  */
+
+tree
+get_primary_template_innermost_parameters (const_tree t)
+{
+  tree parms = NULL, template_info = NULL;
+
+  if ((template_info = get_template_info (t))
+      && primary_template_instantiation_p (t))
+    parms = INNERMOST_TEMPLATE_PARMS
+       (DECL_TEMPLATE_PARMS (TI_TEMPLATE (template_info)));
+
+  return parms;
+}
+
+/* Returns the template arguments of T if T is a template instantiation,
+   NULL otherwise.  */
+
+tree
+get_template_innermost_arguments (const_tree t)
+{
+  tree args = NULL, template_info = NULL;
+
+  if ((template_info = get_template_info (t))
+      && TI_ARGS (template_info))
+    args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (template_info));
+
+  return args;
+}
+
+/* Return the arguments pack of T if T is a template, NULL otherwise.  */
+
+tree
+get_template_argument_pack_elems (const_tree t)
+{
+  if (TREE_CODE (t) != TYPE_ARGUMENT_PACK
+      && TREE_CODE (t) != NONTYPE_ARGUMENT_PACK)
+    return NULL;
+
+  return ARGUMENT_PACK_ARGS (t);
+}
+
 /* Structure used to track the progress of find_parameter_packs_r.  */
 struct find_parameter_pack_data 
 {
index 9ff6a17..c9c0188 100644 (file)
@@ -5551,6 +5551,14 @@ static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
    The key is DECL_UID() ^ die_parent.  */
 static GTY ((param_is (struct die_struct))) htab_t common_block_die_table;
 
+typedef struct GTY(()) die_arg_entry_struct {
+    dw_die_ref die;
+    tree arg;
+} die_arg_entry;
+
+DEF_VEC_O(die_arg_entry);
+DEF_VEC_ALLOC_O(die_arg_entry,gc);
+
 /* Node of the variable location list.  */
 struct GTY ((chain_next ("%h.next"))) var_loc_node {
   rtx GTY (()) var_loc_note;
@@ -5691,6 +5699,8 @@ static GTY(()) struct dwarf_file_data * file_table_last_lookup;
    within the current function.  */
 static HOST_WIDE_INT frame_pointer_fb_offset;
 
+static GTY(()) VEC(die_arg_entry,gc) *tmpl_value_parm_die_table;
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -5826,6 +5836,7 @@ static dw_die_ref base_type_die (tree);
 static int is_base_type (tree);
 static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
 static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
+static dw_die_ref generic_parameter_die (tree, tree, dw_die_ref, int);
 static int type_is_enum (const_tree);
 static unsigned int dbx_reg_number (const_rtx);
 static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
@@ -5861,6 +5872,7 @@ static rtx rtl_for_decl_location (tree);
 static void add_location_or_const_value_attribute (dw_die_ref, tree,
                                                   enum dwarf_attribute);
 static void tree_add_const_value_attribute (dw_die_ref, tree);
+static void tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_comp_dir_attribute (dw_die_ref);
 static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
@@ -5924,6 +5936,8 @@ static dw_die_ref declare_in_namespace (tree, dw_die_ref);
 static struct dwarf_file_data * lookup_filename (const char *);
 static void retry_incomplete_types (void);
 static void gen_type_die_for_member (tree, tree, dw_die_ref);
+static tree make_ith_pack_parameter_name (tree, int);
+static void gen_generic_params_dies (tree);
 static void splice_child_die (dw_die_ref, dw_die_ref);
 static int file_info_cmp (const void *, const void *);
 static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
@@ -5941,6 +5955,8 @@ static void prune_unused_types_walk_attribs (dw_die_ref);
 static void prune_unused_types_prune (dw_die_ref);
 static void prune_unused_types (void);
 static int maybe_emit_file (struct dwarf_file_data *fd);
+static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree);
+static void gen_remaining_tmpl_value_param_die_attribute (void);
 
 /* Section names used to hold DWARF debugging information.  */
 #ifndef DEBUG_INFO_SECTION
@@ -6237,6 +6253,8 @@ dwarf_tag_name (unsigned int tag)
       return "DW_TAG_GNU_BINCL";
     case DW_TAG_GNU_EINCL:
       return "DW_TAG_GNU_EINCL";
+    case DW_TAG_GNU_template_template_param:
+      return "DW_TAG_GNU_template_template_param";
     default:
       return "DW_TAG_<unknown>";
     }
@@ -6438,6 +6456,8 @@ dwarf_attr_name (unsigned int attr)
       return "DW_AT_body_end";
     case DW_AT_GNU_vector:
       return "DW_AT_GNU_vector";
+    case DW_AT_GNU_template_name:
+      return "DW_AT_GNU_template_name";
 
     case DW_AT_VMS_rtnbeg_pd_address:
       return "DW_AT_VMS_rtnbeg_pd_address";
@@ -10353,6 +10373,189 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
   return mod_type_die;
 }
 
+/* Generate a new name for the parameter pack name NAME (an
+   IDENTIFIER_NODE) that incorporates its */
+
+static tree
+make_ith_pack_parameter_name (tree name, int i)
+{
+  /* Munge the name to include the parameter index.  */
+#define NUMBUF_LEN 128
+  char numbuf[NUMBUF_LEN];
+  char* newname;
+  int newname_len;
+
+  snprintf (numbuf, NUMBUF_LEN, "%i", i);
+  newname_len = IDENTIFIER_LENGTH (name)
+               + strnlen (numbuf, NUMBUF_LEN) + 2;
+  newname = (char*) alloca (newname_len);
+  snprintf (newname, newname_len,
+           "%s#%i", IDENTIFIER_POINTER (name), i);
+  return get_identifier (newname);
+}
+
+/* Generate DIEs for the generic parameters of T.
+   T must be either a generic type or a generic function.
+   See http://gcc.gnu.org/wiki/TemplateParmsDwarf for more.  */
+
+static void
+gen_generic_params_dies (tree t)
+{
+  tree parms, args;
+  int parms_num, i;
+  dw_die_ref die = NULL;
+
+  if (!t || (TYPE_P (t) && !COMPLETE_TYPE_P (t)))
+    return;
+
+  if (TYPE_P (t))
+    die = lookup_type_die (t);
+  else if (DECL_P (t))
+    die = lookup_decl_die (t);
+
+  gcc_assert (die);
+
+  parms = lang_hooks.get_innermost_generic_parms (t);
+  if (!parms)
+    /* T has no generic parameter. It means T is neither a generic type
+       or function. End of story.  */
+    return;
+
+  parms_num = TREE_VEC_LENGTH (parms);
+  args = lang_hooks.get_innermost_generic_args (t);
+  for (i = 0; i < parms_num; i++)
+    {
+      tree parm, arg;
+
+      parm = TREE_VEC_ELT (parms, i);
+      arg = TREE_VEC_ELT (args, i);
+      if (parm && TREE_VALUE (parm) && arg)
+       {
+         tree pack_elems =
+           lang_hooks.types.get_argument_pack_elems (arg);
+         if (pack_elems)
+           {
+             /* So ARG is an argument pack and the elements of that pack
+                are stored in PACK_ELEMS.  */
+             int i, len;
+
+             len = TREE_VEC_LENGTH (pack_elems);
+             for (i = 0; i < len; i++)
+               generic_parameter_die (TREE_VALUE (parm),
+                                      TREE_VEC_ELT (pack_elems, i),
+                                      die, i);
+           }
+         else /* Arg is not an argument pack.  */
+           generic_parameter_die (TREE_VALUE (parm),
+                                  arg, die,
+                                  -1/* Not a param pack.  */);
+       }
+    }
+}
+
+/* Create and return a DIE for PARM which should be
+   the representation of a generic type parameter.
+   For instance, in the C++ front end, PARM would be a template parameter.
+   ARG is the argument to PARM.
+   PARENT_DIE is the parent DIE which the new created DIE should be added to,
+   as a child node.
+   PACK_ELEM_INDEX is >= 0 if PARM is a generic parameter pack, and if ARG
+   is one of the unpacked elements of the parameter PACK. In that case,
+   PACK_ELEM_INDEX is the index of ARG in the parameter pack.  */
+
+static dw_die_ref
+generic_parameter_die (tree parm, tree arg, dw_die_ref parent_die,
+                      int pack_elem_index)
+{
+  dw_die_ref tmpl_die = NULL;
+  const char *name = NULL;
+
+  if (!parm || !DECL_NAME (parm) || !arg)
+    return NULL;
+
+  /* We support non-type generic parameters and arguments,
+     type generic parameters and arguments, as well as
+     generic generic parameters (a.k.a. template template parameters in C++)
+     and arguments.  */
+  if (TREE_CODE (parm) == PARM_DECL)
+    /* PARM is a nontype generic parameter  */
+    tmpl_die = new_die (DW_TAG_template_value_param, parent_die, parm);
+  else if (TREE_CODE (parm) == TYPE_DECL)
+    /* PARM is a type generic parameter.  */
+    tmpl_die = new_die (DW_TAG_template_type_param, parent_die, parm);
+  else if (lang_hooks.decls.generic_generic_parameter_decl_p (parm))
+    /* PARM is a generic generic parameter.
+       Its DIE is a GNU extension. It shall have a
+       DW_AT_name attribute to represent the name of the template template
+       parameter, and a DW_AT_GNU_template_name attribute to represent the
+       name of the template template argument.  */
+    tmpl_die = new_die (DW_TAG_GNU_template_template_param,
+                       parent_die, parm);
+  else
+    gcc_unreachable ();
+
+  if (tmpl_die)
+    {
+      tree tmpl_type;
+
+      if (pack_elem_index >= 0)
+       {
+         /* PARM is an element of a parameter pack.
+            Generate a name for it.  */
+         tree identifier = make_ith_pack_parameter_name (DECL_NAME (parm),
+                                                         pack_elem_index);
+         if (identifier)
+           name = IDENTIFIER_POINTER (identifier);
+       }
+      else
+       name = IDENTIFIER_POINTER (DECL_NAME (parm));
+
+      gcc_assert (name);
+      add_AT_string (tmpl_die, DW_AT_name, name);
+
+      if (!lang_hooks.decls.generic_generic_parameter_decl_p (parm))
+       {
+         /* DWARF3, 5.6.8 says if PARM is a non-type generic parameter
+            TMPL_DIE should have a child DW_AT_type attribute that is set
+            to the type of the argument to PARM, which is ARG.
+            If PARM is a type generic parameter, TMPL_DIE should have a
+            child DW_AT_type that is set to ARG.  */
+         tmpl_type = TYPE_P (arg) ? arg : TREE_TYPE (arg);
+         add_type_attribute (tmpl_die, tmpl_type, 0,
+                             TREE_THIS_VOLATILE (tmpl_type),
+                             parent_die);
+       }
+      else
+       {
+         /* So TMPL_DIE is a DIE representing a
+            a generic generic template parameter, a.k.a template template
+            parameter in C++ and arg is a template.  */
+
+         /* The DW_AT_GNU_template_name attribute of the DIE must be set
+            to the name of the argument.  */
+         name = dwarf2_name (TYPE_P (arg) ? TYPE_NAME (arg) : arg, 1);
+         add_AT_string (tmpl_die, DW_AT_GNU_template_name, name);
+       }
+
+      if (TREE_CODE (parm) == PARM_DECL)
+       /* So PARM is a non-type generic parameter.
+          DWARF3 5.6.8 says we must set a DW_AT_const_value child
+          attribute of TMPL_DIE which value represents the value
+          of ARG.
+          We must be careful here:
+          The value of ARG might reference some function decls.
+          We might currently be emitting debug info for a generic
+          type and types are emitted before function decls, we don't
+          know if the function decls referenced by ARG will actually be
+          emitted after cgraph computations.
+          So must defer the generation of the DW_AT_const_value to
+          after cgraph is ready.  */
+       append_entry_to_tmpl_value_parm_die_table (tmpl_die, arg);
+    }
+
+  return tmpl_die;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
    an enumerated type.  */
 
@@ -12057,17 +12260,20 @@ reference_to_unused (tree * tp, int * walk_subtrees,
   else if (!cgraph_global_info_ready
           && (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
     return *tp;
-  else if (DECL_P (*tp) && TREE_CODE (*tp) == VAR_DECL)
+  else if (TREE_CODE (*tp) == VAR_DECL)
     {
       struct varpool_node *node = varpool_node (*tp);
       if (!node->needed)
        return *tp;
     }
-  else if (DECL_P (*tp) && TREE_CODE (*tp) == FUNCTION_DECL
+  else if (TREE_CODE (*tp) == FUNCTION_DECL
           && (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp)))
     {
-      struct cgraph_node *node = cgraph_node (*tp);
-      if (node->process || TREE_ASM_WRITTEN (*tp))
+      /* The call graph machinery must have finished analyzing,
+         optimizing and gimplifying the CU by now.
+        So if *TP has no call graph node associated
+        to it, it means *TP will not be emitted.  */
+      if (!cgraph_get_node (*tp))
        return *tp;
     }
   else if (TREE_CODE (*tp) == STRING_CST && !TREE_ASM_WRITTEN (*tp))
@@ -12639,7 +12845,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
     }
   /* None of that worked, so it must not really have a location;
      try adding a constant value attribute from the DECL_INITIAL.  */
-  tree_add_const_value_attribute (die, decl);
+  tree_add_const_value_attribute_for_decl (die, decl);
 }
 
 /* Add VARIABLE and DIE into deferred locations list.  */
@@ -12800,29 +13006,25 @@ native_encode_initializer (tree init, unsigned char *array, int size)
     }
 }
 
-/* If we don't have a copy of this variable in memory for some reason (such
-   as a C++ member constant that doesn't have an out-of-line definition),
-   we should tell the debugger about the constant value.  */
+/* Attach a DW_AT_const_value attribute to DIE. The value of the
+   attribute is the const value T.  */
 
 static void
-tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
+tree_add_const_value_attribute (dw_die_ref die, tree t)
 {
   tree init;
-  tree type = TREE_TYPE (decl);
+  tree type = TREE_TYPE (t);
   rtx rtl;
 
-  if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL)
+  if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
     return;
 
-  init = DECL_INITIAL (decl);
-  if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init)
-    /* OK */;
-  else
-    return;
+  init = t;
+  gcc_assert (!DECL_P (init));
 
   rtl = rtl_for_decl_init (init, type);
   if (rtl)
-    add_const_value_attribute (var_die, rtl);
+    add_const_value_attribute (die, rtl);
   /* If the host and target are sane, try harder.  */
   else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
           && initializer_constant_valid_p (init, type))
@@ -12833,11 +13035,35 @@ tree_add_const_value_attribute (dw_die_ref var_die, tree decl)
          unsigned char *array = GGC_CNEWVEC (unsigned char, size);
 
          if (native_encode_initializer (init, array, size))
-           add_AT_vec (var_die, DW_AT_const_value, size, 1, array);
+           add_AT_vec (die, DW_AT_const_value, size, 1, array);
        }
     }
 }
 
+/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
+   attribute is the const value of T, where T is an integral constant
+   variable with static storage duration
+   (so it can't be a PARM_DECL or a RESULT_DECL).  */
+
+static void
+tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
+{
+
+  if (!decl
+      || (TREE_CODE (decl) != VAR_DECL
+         && TREE_CODE (decl) != CONST_DECL))
+    return;
+
+    if (TREE_READONLY (decl)
+       && ! TREE_THIS_VOLATILE (decl)
+       && DECL_INITIAL (decl))
+      /* OK */;
+    else
+      return;
+
+    tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
+}
+
 /* Convert the CFI instructions for the current function into a
    location list.  This is used for DW_AT_frame_base when we targeting
    a dwarf2 consumer that does not support the dwarf3
@@ -14534,6 +14760,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                 loc_descriptor_from_tree (cfun->static_chain_decl));
     }
 
+  /* Generate child dies for template paramaters.  */
+  if (debug_info_level > DINFO_LEVEL_TERSE)
+    gen_generic_params_dies (decl);
+
   /* Now output descriptions of the arguments for this function. This gets
      (unnecessarily?) complex because of the fact that the DECL_ARGUMENT list
      for a FUNCTION_DECL doesn't indicate cases where there was a trailing
@@ -14895,7 +15125,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       add_pubname (decl_or_origin, var_die);
     }
   else
-    tree_add_const_value_attribute (var_die, decl_or_origin);
+    tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
 }
 
 /* Generate a DIE to represent a named constant.  */
@@ -14913,7 +15143,7 @@ gen_const_die (tree decl, dw_die_ref context_die)
     add_AT_flag (const_die, DW_AT_external, 1);
   if (DECL_ARTIFICIAL (decl))
     add_AT_flag (const_die, DW_AT_artificial, 1);
-  tree_add_const_value_attribute (const_die, decl);
+  tree_add_const_value_attribute_for_decl (const_die, decl);
 }
 
 /* Generate a DIE to represent a label identifier.  */
@@ -15332,6 +15562,11 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
   else
     remove_AT (type_die, DW_AT_declaration);
 
+  /* Generate child dies for template paramaters.  */
+  if (debug_info_level > DINFO_LEVEL_TERSE
+      && COMPLETE_TYPE_P (type))
+    gen_generic_params_dies (type);
+
   /* If this type has been completed, then give it a byte_size attribute and
      then give a list of members.  */
   if (complete && !ns_decl)
@@ -16587,6 +16822,49 @@ maybe_emit_file (struct dwarf_file_data * fd)
   return fd->emitted_number;
 }
 
+/* Schedule generation of a DW_AT_const_value attribute to DIE.
+   That generation should happen after function debug info has been
+   generated. The value of the attribute is the constant value of ARG.  */
+
+static void
+append_entry_to_tmpl_value_parm_die_table (dw_die_ref die, tree arg)
+{
+  die_arg_entry entry;
+
+  if (!die || !arg)
+    return;
+
+  if (!tmpl_value_parm_die_table)
+    tmpl_value_parm_die_table
+      = VEC_alloc (die_arg_entry, gc, 32);
+
+  entry.die = die;
+  entry.arg = arg;
+  VEC_safe_push (die_arg_entry, gc,
+                tmpl_value_parm_die_table,
+                &entry);
+}
+
+/* Add a DW_AT_const_value attribute to DIEs that were scheduled
+   by append_entry_to_tmpl_value_parm_die_table. This function must
+   be called after function DIEs have been generated.  */
+
+static void
+gen_remaining_tmpl_value_param_die_attribute (void)
+{
+  if (tmpl_value_parm_die_table)
+    {
+      unsigned i;
+      die_arg_entry *e;
+
+      for (i = 0;
+           VEC_iterate (die_arg_entry, tmpl_value_parm_die_table, i, e);
+           i++)
+       tree_add_const_value_attribute (e->die, e->arg);
+    }
+}
+
+
 /* Replace DW_AT_name for the decl with name.  */
  
 static void
@@ -17346,6 +17624,8 @@ dwarf2out_finish (const char *filename)
   dw_die_ref die = 0;
   unsigned int i;
 
+  gen_remaining_tmpl_value_param_die_attribute ();
+
   /* Add the name for the main input file now.  We delayed this from
      dwarf2out_init to avoid complications with PCH.  */
   add_name_attribute (comp_unit_die, remap_debug_filename (filename));
index 2631ff8..25d96e9 100644 (file)
@@ -153,6 +153,10 @@ extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_CLASSIFY_RECORD     NULL
 #define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
 #define LANG_HOOKS_GENERIC_TYPE_P      hook_bool_const_tree_false
+#define LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS hook_tree_const_tree_null
+#define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS hook_tree_const_tree_null
+#define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS hook_tree_const_tree_null
+#define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P hook_bool_const_tree_false
 #define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to
 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type
 #define LANG_HOOKS_TYPE_MAX_SIZE       lhd_return_null_const_tree
@@ -170,6 +174,7 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_TYPE_FOR_MODE, \
   LANG_HOOKS_TYPE_FOR_SIZE, \
   LANG_HOOKS_GENERIC_TYPE_P, \
+  LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS, \
   LANG_HOOKS_TYPE_PROMOTES_TO, \
   LANG_HOOKS_REGISTER_BUILTIN_TYPE, \
   LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \
@@ -206,6 +211,7 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_PUSHDECL, \
   LANG_HOOKS_GETDECLS, \
   LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
+  LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
   LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
   LANG_HOOKS_WRITE_GLOBALS, \
   LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
@@ -259,6 +265,8 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_TREE_DUMP_INITIALIZER, \
   LANG_HOOKS_DECLS, \
   LANG_HOOKS_FOR_TYPES_INITIALIZER, \
+  LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
+  LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
   LANG_HOOKS_GIMPLIFY_EXPR, \
   LANG_HOOKS_FOLD_OBJ_TYPE_REF, \
   LANG_HOOKS_BUILTIN_FUNCTION, \
index ed3e7e7..d708bb2 100644 (file)
@@ -91,6 +91,9 @@ struct lang_hooks_for_types
      e.g. C++ template implicit specializations.  */
   bool (*generic_p) (const_tree);
 
+  /* Returns the TREE_VEC of elements of a given generic argument pack.  */
+  tree (*get_argument_pack_elems) (const_tree);
+
   /* Given a type, apply default promotions to unnamed function
      arguments and return the new type.  Return the same type if no
      change.  Required by any language that supports variadic
@@ -165,6 +168,10 @@ struct lang_hooks_for_decls
   /* Returns true if DECL is explicit member function.  */
   bool (*function_decl_explicit_p) (tree);
 
+  /* Returns True if the parameter is a generic parameter decl
+     of a generic type, e.g a template template parameter for the C++ FE.  */
+  bool (*generic_generic_parameter_decl_p) (const_tree);
+
   /* Returns true when we should warn for an unused global DECL.
      We will already have checked that it has static binding.  */
   bool (*warn_unused_global) (const_tree);
@@ -380,6 +387,14 @@ struct lang_hooks
 
   struct lang_hooks_for_types types;
 
+  /* Retuns the generic parameters of an instantiation of
+     a generic type or decl, e.g. C++ template instantiation.  */
+  tree (*get_innermost_generic_parms) (const_tree);
+
+  /* Returns the TREE_VEC of arguments of an instantiation
+     of a generic type of decl, e.g. C++ template instantiation.  */
+  tree (*get_innermost_generic_args) (const_tree);
+
   /* Perform language-specific gimplification on the argument.  Returns an
      enum gimplify_status, though we can't see that type here.  */
   int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *);
index 67ea0ef..ff02594 100644 (file)
@@ -1,3 +1,20 @@
+2009-08-31  Dodji Seketeli  <dodji@redhat.com>
+
+       PR debug/30161
+       * g++.dg/debug/dwarf2/template-params-1.C: New test.
+       * g++.dg/debug/dwarf2/template-params-2.C: Likewise.
+       * g++.dg/debug/dwarf2/template-params-3.C: Likewise.
+       * g++.dg/debug/dwarf2/template-params-4.C: Likewise.
+       * g++.dg/debug/dwarf2/template-params-5.C: Likewise.
+       * g++.dg/debug/dwarf2/template-params-6.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-1.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-2.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-3.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-4.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-5.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-6.C: Likewise.
+       * g++.dg/debug/dwarf2/template-func-params-7.C: Likewise.
+
 2009-08-31  Jason Merrill  <jason@redhat.com>
 
        PR c++/41127
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-1.C
new file mode 100644 (file)
index 0000000..3a43d9f
--- /dev/null
@@ -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);
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-2.C
new file mode 100644 (file)
index 0000000..27c68d7
--- /dev/null
@@ -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>();
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-3.C
new file mode 100644 (file)
index 0000000..9f3dc8c
--- /dev/null
@@ -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>();
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-4.C
new file mode 100644 (file)
index 0000000..0eb0fe5
--- /dev/null
@@ -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>();
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-5.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-5.C
new file mode 100644 (file)
index 0000000..c4fd8dc
--- /dev/null
@@ -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>();
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-6.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-6.C
new file mode 100644 (file)
index 0000000..155add4
--- /dev/null
@@ -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>();
+
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-func-params-7.C
new file mode 100644 (file)
index 0000000..07aece6
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-1.C
new file mode 100644 (file)
index 0000000..e28297b
--- /dev/null
@@ -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;
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-2.C
new file mode 100644 (file)
index 0000000..ce5fbab
--- /dev/null
@@ -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;
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-3.C
new file mode 100644 (file)
index 0000000..06b0e2b
--- /dev/null
@@ -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;
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-4.C
new file mode 100644 (file)
index 0000000..09d1d95
--- /dev/null
@@ -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;
+}
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-5.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-5.C
new file mode 100644 (file)
index 0000000..f36eac5
--- /dev/null
@@ -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;
+
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-6.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-6.C
new file mode 100644 (file)
index 0000000..dc401fa
--- /dev/null
@@ -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 ();
+}
index 295abf5..befaceb 100644 (file)
@@ -210,6 +210,9 @@ enum dwarf_tag
     DW_TAG_class_template = 0x4103,    /* For C++.  */
     DW_TAG_GNU_BINCL = 0x4104,
     DW_TAG_GNU_EINCL = 0x4105,
+    /* Template template parameter.
+       See http://gcc.gnu.org/wiki/TemplateParmsDwarf .  */
+    DW_TAG_GNU_template_template_param = 0x4106,
     /* Extensions for UPC.  See: http://upc.gwu.edu/~upc.  */
     DW_TAG_upc_shared_type = 0x8765,
     DW_TAG_upc_strict_type = 0x8766,
@@ -390,6 +393,9 @@ enum dwarf_attribute
     DW_AT_body_begin = 0x2105,
     DW_AT_body_end   = 0x2106,
     DW_AT_GNU_vector = 0x2107,
+    /* Template template argument name.
+       See http://gcc.gnu.org/wiki/TemplateParmsDwarf .  */
+    DW_AT_GNU_template_name = 0x2110,
     /* VMS extensions.  */
     DW_AT_VMS_rtnbeg_pd_address = 0x2201,
     /* UPC extension.  */