re PR debug/28767 (GCC should output DW_TAG_ptr_to_member for member functions)
authorJakub Jelinek <jakub@gcc.gnu.org>
Thu, 3 Nov 2016 21:18:49 +0000 (22:18 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 3 Nov 2016 21:18:49 +0000 (22:18 +0100)
PR debug/28767
PR debug/56974
* langhooks.h (struct lang_hooks_for_types): Add type_dwarf_attribute
langhook.
* langhooks.c (lhd_type_dwarf_attribute): New function.
* langhooks-def.h (lhd_type_dwarf_attribute): Declare.
(LANG_HOOKS_TYPE_DWARF_ATTRIBUTE): Define.
(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.
(check_qualified_type, check_aligned_type): Call it.
* dwarf2out.c (modified_type_die): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type.
(gen_ptr_to_mbr_type_die): If lookup_type_die is already non-NULL,
return early.  For pointer-to-data-member add DW_AT_use_location
attribute.
(gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
if needed.
(gen_type_die_with_usage): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type.  Formatting fixes. Call
get_debug_type langhook.
cp/
* tree.c (cp_check_qualified_type): Use check_base_type and
TYPE_QUALS comparison instead of check_qualified_type.
(cxx_type_hash_eq): Return false if type_memfn_rqual don't match.
* cp-objcp-common.c (cp_get_debug_type): New function.
(cp_decl_dwarf_attribute): Don't handle types here.
(cp_type_dwarf_attribute): New function.
* cp-objcp-common.h (cp_get_debug_type, cp_type_dwarf_attribute):
Declare.
(LANG_HOOKS_GET_DEBUG_TYPE, LANG_HOOKS_TYPE_DWARF_ATTRIBUTE):
Define.
testsuite/
* g++.dg/debug/dwarf2/ptrdmem-1.C: New test.
* g++.dg/debug/dwarf2/ref-3.C: New test.
* g++.dg/debug/dwarf2/ref-4.C: New test.
* g++.dg/debug/dwarf2/refqual-1.C: New test.
* g++.dg/debug/dwarf2/refqual-2.C: New test.

From-SVN: r241832

14 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-objcp-common.h
gcc/dwarf2out.c
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C [new file with mode: 0644]

index dbbdba7..14486af 100644 (file)
@@ -1,3 +1,30 @@
+2016-11-03  Jakub Jelinek  <jakub@redhat.com>
+           Alexandre Oliva  <aoliva@redhat.com>
+           Jason Merrill  <jason@redhat.com>
+
+       PR debug/28767
+       PR debug/56974
+       * langhooks.h (struct lang_hooks_for_types): Add type_dwarf_attribute
+       langhook.
+       * langhooks.c (lhd_type_dwarf_attribute): New function.
+       * langhooks-def.h (lhd_type_dwarf_attribute): Declare.
+       (LANG_HOOKS_TYPE_DWARF_ATTRIBUTE): Define.
+       (LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
+       LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.
+       (check_qualified_type, check_aligned_type): Call it.
+       * dwarf2out.c (modified_type_die): Don't use type_main_variant
+       for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
+       check_base_type and check_lang_type.
+       (gen_ptr_to_mbr_type_die): If lookup_type_die is already non-NULL,
+       return early.  For pointer-to-data-member add DW_AT_use_location
+       attribute.
+       (gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
+       if needed.
+       (gen_type_die_with_usage): Don't use type_main_variant
+       for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
+       check_base_type and check_lang_type.  Formatting fixes. Call
+       get_debug_type langhook.
+
 2016-11-03  Jason Merrill  <jason@redhat.com>
 
        * tree.c (check_lang_type): New.
index c60c81d..d20453b 100644 (file)
@@ -1,3 +1,20 @@
+2016-11-03  Jakub Jelinek  <jakub@redhat.com>
+           Alexandre Oliva  <aoliva@redhat.com>
+           Jason Merrill  <jason@redhat.com>
+
+       PR debug/28767
+       PR debug/56974
+       * tree.c (cp_check_qualified_type): Use check_base_type and
+       TYPE_QUALS comparison instead of check_qualified_type.
+       (cxx_type_hash_eq): Return false if type_memfn_rqual don't match.
+       * cp-objcp-common.c (cp_get_debug_type): New function.
+       (cp_decl_dwarf_attribute): Don't handle types here.
+       (cp_type_dwarf_attribute): New function.
+       * cp-objcp-common.h (cp_get_debug_type, cp_type_dwarf_attribute):
+       Declare.
+       (LANG_HOOKS_GET_DEBUG_TYPE, LANG_HOOKS_TYPE_DWARF_ATTRIBUTE):
+       Define.
+
 2016-11-03  Jason Merrill  <jason@redhat.com>
 
        * tree.c (cp_check_qualified_type): Call check_base_type instead
index c6f0873..633831c 100644 (file)
@@ -131,6 +131,19 @@ cxx_types_compatible_p (tree x, tree y)
   return same_type_ignoring_top_level_qualifiers_p (x, y);
 }
 
+/* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
+   keep TYPE.  */
+
+tree
+cp_get_debug_type (const_tree type)
+{
+  if (TYPE_PTRMEMFUNC_P (type) && !typedef_variant_p (type))
+    return build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
+                             TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));
+
+  return NULL_TREE;
+}
+
 /* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
    value otherwise.  */
 int
@@ -179,11 +192,6 @@ cp_decl_dwarf_attribute (const_tree decl, int attr)
          && FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
          && !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
        return 1;
-      if ((TREE_CODE (decl) == FUNCTION_TYPE
-          || TREE_CODE (decl) == METHOD_TYPE)
-         && FUNCTION_REF_QUALIFIED (decl)
-         && !FUNCTION_RVALUE_QUALIFIED (decl))
-       return 1;
       break;
 
     case DW_AT_rvalue_reference:
@@ -192,11 +200,6 @@ cp_decl_dwarf_attribute (const_tree decl, int attr)
          && FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
          && FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
        return 1;
-      if ((TREE_CODE (decl) == FUNCTION_TYPE
-          || TREE_CODE (decl) == METHOD_TYPE)
-         && FUNCTION_REF_QUALIFIED (decl)
-         && FUNCTION_RVALUE_QUALIFIED (decl))
-       return 1;
       break;
 
     case DW_AT_inline:
@@ -216,6 +219,39 @@ cp_decl_dwarf_attribute (const_tree decl, int attr)
   return -1;
 }
 
+/* Return -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+   value otherwise.  */
+int
+cp_type_dwarf_attribute (const_tree type, int attr)
+{
+  if (type == NULL_TREE)
+    return -1;
+
+  switch (attr)
+    {
+    case DW_AT_reference:
+      if ((TREE_CODE (type) == FUNCTION_TYPE
+          || TREE_CODE (type) == METHOD_TYPE)
+         && FUNCTION_REF_QUALIFIED (type)
+         && !FUNCTION_RVALUE_QUALIFIED (type))
+       return 1;
+      break;
+
+    case DW_AT_rvalue_reference:
+      if ((TREE_CODE (type) == FUNCTION_TYPE
+          || TREE_CODE (type) == METHOD_TYPE)
+         && FUNCTION_REF_QUALIFIED (type)
+         && FUNCTION_RVALUE_QUALIFIED (type))
+       return 1;
+      break;
+
+    default:
+      break;
+    }
+
+  return -1;
+}
+
 /* Stubs to keep c-opts.c happy.  */
 void
 push_file_scope (void)
index 9dd847e..65ac95c 100644 (file)
@@ -21,12 +21,14 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_CP_OBJCP_COMMON
 #define GCC_CP_OBJCP_COMMON
 
-/* In cp/cp-lang.c and objcp/objcp-lang.c.  */
+/* In cp/objcp-common.c, cp/cp-lang.c and objcp/objcp-lang.c.  */
 
+extern tree cp_get_debug_type (const_tree);
 extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
                                         tree, bool);
 
 extern int cp_decl_dwarf_attribute (const_tree, int);
+extern int cp_type_dwarf_attribute (const_tree, int);
 extern void cp_common_init_ts (void);
 
 /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
@@ -125,12 +127,16 @@ extern void cp_common_init_ts (void);
 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
 #undef LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE
 #define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE cp_reconstruct_complex_type
+#undef LANG_HOOKS_GET_DEBUG_TYPE
+#define LANG_HOOKS_GET_DEBUG_TYPE cp_get_debug_type
 #undef LANG_HOOKS_TO_TARGET_CHARSET
 #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
 #undef LANG_HOOKS_GIMPLIFY_EXPR
 #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
 #undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
 #define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
+#undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
 #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
 #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
index b6161e5..1dfff38 100644 (file)
@@ -12573,8 +12573,20 @@ modified_type_die (tree type, int cv_quals, bool reverse,
         copy was created to help us keep track of typedef names) and
         that copy might have a different TYPE_UID from the original
         ..._TYPE node.  */
-      if (TREE_CODE (type) != VECTOR_TYPE
-         && TREE_CODE (type) != ARRAY_TYPE)
+      if (TREE_CODE (type) == FUNCTION_TYPE
+         || TREE_CODE (type) == METHOD_TYPE)
+       {
+         /* For function/method types, can't just use type_main_variant here,
+            because that can have different ref-qualifiers for C++,
+            but try to canonicalize.  */
+         tree main = TYPE_MAIN_VARIANT (type);
+         for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+           if (check_base_type (t, main) && check_lang_type (t, type))
+             return lookup_type_die (t);
+         return lookup_type_die (type);
+       }
+      else if (TREE_CODE (type) != VECTOR_TYPE
+              && TREE_CODE (type) != ARRAY_TYPE)
        return lookup_type_die (type_main_variant (type));
       else
        /* Vectors have the debugging information in the type,
@@ -23147,20 +23159,31 @@ gen_reference_type_die (tree type, dw_die_ref context_die)
 }
 #endif
 
-/* Generate a DIE for a pointer to a member type.  */
+/* Generate a DIE for a pointer to a member type.  TYPE can be an
+   OFFSET_TYPE, for a pointer to data member, or a RECORD_TYPE, for a
+   pointer to member function.  */
 
 static void
 gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
 {
-  dw_die_ref ptr_die
-    = new_die (DW_TAG_ptr_to_member_type,
-              scope_die_for (type, context_die), type);
+  if (lookup_type_die (type))
+    return;
+
+  dw_die_ref ptr_die = new_die (DW_TAG_ptr_to_member_type,
+                               scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ptr_die);
   add_AT_die_ref (ptr_die, DW_AT_containing_type,
                  lookup_type_die (TYPE_OFFSET_BASETYPE (type)));
   add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
                      context_die);
+
+  if (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
+      && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)
+    {
+      dw_loc_descr_ref op = new_loc_descr (DW_OP_plus, 0, 0);
+      add_AT_loc (ptr_die, DW_AT_use_location, op);
+    }
 }
 
 static char *producer_string;
@@ -24095,6 +24118,13 @@ gen_subroutine_type_die (tree type, dw_die_ref context_die)
 
   if (get_AT (subr_die, DW_AT_name))
     add_pubtype (type, subr_die);
+  if ((dwarf_version >= 5 || !dwarf_strict)
+      && lang_hooks.types.type_dwarf_attribute (type, DW_AT_reference) != -1)
+    add_AT_flag (subr_die, DW_AT_reference, 1);
+  if ((dwarf_version >= 5 || !dwarf_strict)
+      && lang_hooks.types.type_dwarf_attribute (type,
+                                               DW_AT_rvalue_reference) != -1)
+    add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
 }
 
 /* Generate a DIE for a type definition.  */
@@ -24316,13 +24346,36 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       return;
     }
 
+  if (lang_hooks.types.get_debug_type)
+    {
+      tree debug_type = lang_hooks.types.get_debug_type (type);
+
+      if (debug_type != NULL_TREE && debug_type != type)
+       {
+         gen_type_die_with_usage (debug_type, context_die, usage);
+         return;
+       }
+    }
+
   /* We are going to output a DIE to represent the unqualified version
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
      now.  (Vectors and arrays are special because the debugging info is in the
-     cloned type itself).  */
-  if (TREE_CODE (type) != VECTOR_TYPE
-      && TREE_CODE (type) != ARRAY_TYPE)
+     cloned type itself.  Similarly function/method types can contain extra
+     ref-qualification).  */
+  if (TREE_CODE (type) == FUNCTION_TYPE
+      || TREE_CODE (type) == METHOD_TYPE)
+    {
+      /* For function/method types, can't use type_main_variant here,
+        because that can have different ref-qualifiers for C++,
+        but try to canonicalize.  */
+      tree main = TYPE_MAIN_VARIANT (type);
+      for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+       if (check_base_type (t, main) && check_lang_type (t, type))
+         type = t;
+    }
+  else if (TREE_CODE (type) != VECTOR_TYPE
+          && TREE_CODE (type) != ARRAY_TYPE)
     type = type_main_variant (type);
 
   /* If this is an array type with hidden descriptor, handle it first.  */
@@ -24373,18 +24426,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       /* For these types, all that is required is that we output a DIE (or a
         set of DIEs) to represent the "basis" type.  */
       gen_type_die_with_usage (TREE_TYPE (type), context_die,
-                               DINFO_USAGE_IND_USE);
+                              DINFO_USAGE_IND_USE);
       break;
 
     case OFFSET_TYPE:
       /* This code is used for C++ pointer-to-data-member types.
         Output a description of the relevant class type.  */
       gen_type_die_with_usage (TYPE_OFFSET_BASETYPE (type), context_die,
-                                       DINFO_USAGE_IND_USE);
+                              DINFO_USAGE_IND_USE);
 
       /* Output a description of the type of the object pointed to.  */
       gen_type_die_with_usage (TREE_TYPE (type), context_die,
-                                       DINFO_USAGE_IND_USE);
+                              DINFO_USAGE_IND_USE);
 
       /* Now output a DIE to represent this pointer-to-data-member type
         itself.  */
@@ -24394,14 +24447,14 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     case FUNCTION_TYPE:
       /* Force out return type (in case it wasn't forced out already).  */
       gen_type_die_with_usage (TREE_TYPE (type), context_die,
-                                       DINFO_USAGE_DIR_USE);
+                              DINFO_USAGE_DIR_USE);
       gen_subroutine_type_die (type, context_die);
       break;
 
     case METHOD_TYPE:
       /* Force out return type (in case it wasn't forced out already).  */
       gen_type_die_with_usage (TREE_TYPE (type), context_die,
-                                       DINFO_USAGE_DIR_USE);
+                              DINFO_USAGE_DIR_USE);
       gen_subroutine_type_die (type, context_die);
       break;
 
index e49382b..5c330f0 100644 (file)
@@ -84,6 +84,7 @@ extern bool lhd_omp_mappable_type (tree);
 extern const char *lhd_get_substring_location (const substring_loc &,
                                               location_t *out_loc);
 extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
 
 #define LANG_HOOKS_NAME                        "GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE     sizeof (struct lang_identifier)
@@ -186,6 +187,7 @@ extern tree lhd_make_node (enum tree_code);
 #define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
 #define LANG_HOOKS_GET_DEBUG_TYPE      NULL
 #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE        lhd_type_dwarf_attribute
 
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
   LANG_HOOKS_MAKE_TYPE, \
@@ -208,7 +210,8 @@ extern tree lhd_make_node (enum tree_code);
   LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
   LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
   LANG_HOOKS_GET_DEBUG_TYPE, \
-  LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO \
+  LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+  LANG_HOOKS_TYPE_DWARF_ATTRIBUTE \
 }
 
 /* Declaration hooks.  */
index 370990e..6483dc1 100644 (file)
@@ -702,6 +702,15 @@ lhd_decl_dwarf_attribute (const_tree, int)
   return -1;
 }
 
+/* Default implementation of LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.  Don't add
+   any attributes.  */
+
+int
+lhd_type_dwarf_attribute (const_tree, int)
+{
+  return -1;
+}
+
 /* Returns true if the current lang_hooks represents the GNU C frontend.  */
 
 bool
index 6cd01a7..150227c 100644 (file)
@@ -162,6 +162,10 @@ struct lang_hooks_for_types
      for the debugger about scale factor, etc.  */
   bool (*get_fixed_point_type_info) (const_tree,
                                     struct fixed_point_type_info *);
+
+  /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+     value otherwise.  */
+  int (*type_dwarf_attribute) (const_tree, int);
 };
 
 /* Language hooks related to decls and the symbol table.  */
index 2a7d336..371f613 100644 (file)
@@ -1,10 +1,22 @@
-2016-11-03  Fritz Reese <fritzoreese@gmail.com>
+2016-11-03  Jakub Jelinek  <jakub@redhat.com>
+           Alexandre Oliva  <aoliva@redhat.com>
+           Jason Merrill  <jason@redhat.com>
+
+       PR debug/28767
+       PR debug/56974
+       * g++.dg/debug/dwarf2/ptrdmem-1.C: New test.
+       * g++.dg/debug/dwarf2/ref-3.C: New test.
+       * g++.dg/debug/dwarf2/ref-4.C: New test.
+       * g++.dg/debug/dwarf2/refqual-1.C: New test.
+       * g++.dg/debug/dwarf2/refqual-2.C: New test.
+
+2016-11-03  Fritz Reese  <fritzoreese@gmail.com>
 
        * gfortran.dg/dec_exp_1.f90: New test.
        * gfortran.dg/dec_exp_2.f90: Likewise.
        * gfortran.dg/dec_exp_3.f90: Likewise.
 
-2016-11-03  Fritz O. Reese <fritzoreese@gmail.com>
+2016-11-03  Fritz O. Reese  <fritzoreese@gmail.com>
 
        * gfortran.dg/dec_parameter_1.f: New test.
        * gfortran.dg/dec_parameter_2.f90: Likewise.
@@ -45,7 +57,7 @@
 
        * gcc.dg/store_merging_8.c: New testcase.
 
-2016-11-02  Fritz O. Reese <fritzoreese@gmail.com>
+2016-11-02  Fritz O. Reese  <fritzoreese@gmail.com>
 
        * gfortran.dg/warn_argument_mismatch_1.f90: New test.
 
        * gcc.target/i386/pr34012.c: Add -fno-store-merging to dg-options.
        * g++.dg/init/new17.C: Likewise.
 
-2016-10-26  Will Schmidt <will_schmidt@vnet.ibm.com>
+2016-10-26  Will Schmidt  <will_schmidt@vnet.ibm.com>
 
        PR middle-end/72747
        * c-c++-common/pr72747-1.c: New test.
        * gcc.dg/fold-convmaxconv-1.c: New test.
        * gcc.dg/fold-convminconv-1.c: New test.
 
-2016-10-26  Steven G. Kargl <kargl@gcc.gnu.org>
+2016-10-26  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/78092
        * gfortran.dg/pr78092.f90: New test.
 2016-01-28  Ilya Enkovich  <enkovich.gnu@gmail.com>
 
        * gcc.dg/declare-simd.c: New test.
+
 2016-01-28  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/69466
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C
new file mode 100644 (file)
index 0000000..5d65196
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_reference" { xfail { powerpc-ibm-aix* } } } }
+
+struct S;
+typedef int S::*pdm;
+pdm pmf = 0;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C
new file mode 100644 (file)
index 0000000..6294d02
--- /dev/null
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-g -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times " DW_AT_reference" 5 } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 5 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 6 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 7 } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 } }
+
+struct S
+{
+  void foo1 ();
+  void bar1 () &;
+  void baz1 () &&;
+  void foo2 () const;
+  void bar2 () const &;
+  void baz2 () const &&;
+  void foo3 () const;
+  void bar3 () const &;
+  void baz3 () const &&;
+  int d;
+};
+
+void
+test ()
+{
+  S s;
+  auto o1 = &S::foo1;
+  auto r1 = &S::bar1;
+  auto z1 = &S::baz1;
+  auto o2 = &S::foo2;
+  auto r2 = &S::bar2;
+  auto z2 = &S::baz2;
+  auto o3 = &S::foo3;
+  auto r3 = &S::bar3;
+  auto z3 = &S::baz3;
+  auto d1 = &S::d;
+  void (S::*o4) () const;
+  o4 = &S::foo3;
+  void (S::*r4) () const &;
+  r4 = &S::bar3;
+  void (S::*z4) () const &&;
+  z4 = &S::baz3;
+  (s.*o1) ();
+  (s.*r1) ();
+  (S ().*z1) ();
+  (s.*o2) ();
+  (s.*r2) ();
+  (S ().*z2) ();
+  (s.*o3) ();
+  (s.*r3) ();
+  (S ().*z3) ();
+  (s.*o4) ();
+  (s.*r4) ();
+  (S ().*z4) ();
+  s.*d1 = 2;
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C
new file mode 100644 (file)
index 0000000..b1fe0e4
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-g -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_typedef" 2 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 2 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 1 } }
+
+struct A { void foo (); int a; };
+typedef void (A::*PMF) ();
+typedef int A::*PMI;
+PMF pmf;
+PMI pmi;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C
new file mode 100644 (file)
index 0000000..221008e
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+   DW_AT_use_location in a pointer to member function, so we don't
+   output it for now.  */
+
+struct S {
+  void mf(void) &;
+};
+
+void S::mf() & {}
+
+typedef void (S::*pmft)(void) &;
+pmft pmf = &S::mf;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C
new file mode 100644 (file)
index 0000000..ddf33c1
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+   DW_AT_use_location in a pointer to member function, so we don't
+   output it for now.  */
+
+struct S {
+  void mf(void) &&;
+};
+
+void S::mf() && {}
+
+typedef void (S::*pmft)(void) &&;
+pmft pmf = &S::mf;