diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 9cb9dd7..e9f9a63 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -130,6 +130,43 @@ cxx_types_compatible_p (tree x, tree y)
   return same_type_ignoring_top_level_qualifiers_p (x, y);
 }
 
+/* Return 0 if TYPE is NOT a C++ method or function type with a
+   ref-qualifier, 1 if the ref-qualifier is '&', and 2 if it is
+   '&&'.  */
+
+int
+cp_get_ref_qualifier (const_tree type)
+{
+  if ((TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == FUNCTION_TYPE)
+      && FUNCTION_REF_QUALIFIED (type))
+    return FUNCTION_RVALUE_QUALIFIED (type) ? 2 : 1;
+  else
+    return 0;
+}
+
+/* Return NULL if TYPE is NOT a C++ pointer to member function type.
+   Otherwise, return the class type when the selector is 0, or the
+   member function type when the selector is 1.  */
+
+tree
+cp_get_ptrmemfn_type (const_tree type, int selector)
+{
+  if (!TYPE_PTRMEMFUNC_P (type))
+    return NULL_TREE;
+
+  switch (selector)
+    {
+    case 0:
+      return TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
+
+    case 1:
+      return TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type));
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Return true if DECL is explicit member function.  */
 
 bool
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 3ad3eb6..00780c7 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -21,7 +21,10 @@ 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 int cp_get_ref_qualifier (const_tree);
+extern tree cp_get_ptrmemfn_type (const_tree, int);
 
 extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
 					 tree, bool);
@@ -127,6 +130,10 @@ 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_REF_QUALIFIER
+#define LANG_HOOKS_GET_REF_QUALIFIER cp_get_ref_qualifier
+#undef LANG_HOOKS_GET_PTRMEMFN_TYPE
+#define LANG_HOOKS_GET_PTRMEMFN_TYPE cp_get_ptrmemfn_type
 #undef LANG_HOOKS_TO_TARGET_CHARSET
 #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
 #undef LANG_HOOKS_GIMPLIFY_EXPR
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 3b25358..f40f759 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3383,7 +3383,7 @@ static void gen_label_die (tree, dw_die_ref);
 static void gen_lexical_block_die (tree, dw_die_ref);
 static void gen_inlined_subroutine_die (tree, dw_die_ref);
 static void gen_field_die (tree, struct vlr_context *, dw_die_ref);
-static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
+static void gen_ptr_to_mbr_type_die (tree, dw_die_ref, tree, tree);
 static dw_die_ref gen_compile_unit_die (const char *);
 static void gen_inheritance_die (tree, tree, tree, dw_die_ref);
 static void gen_member_die (tree, dw_die_ref);
@@ -20535,6 +20535,24 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 	{
 	  add_AT_flag (subr_die, DW_AT_declaration, 1);
 
+	  /* If this is a method with a ref-qualifier, generate the
+	     corresponding attribute.  */
+	  int rqual = lang_hooks.types.get_ref_qualifier (TREE_TYPE (decl));
+	  if (rqual && (dwarf_version >= 5 || !dwarf_strict))
+	    switch (rqual)
+	      {
+	      case 1:
+		add_AT_flag (subr_die, DW_AT_reference, 1);
+		break;
+
+	      case 2:
+		add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
+		break;
+
+	      default:
+		gcc_unreachable ();
+	      }
+
 	  /* If this is an explicit function declaration then generate
 	     a DW_AT_explicit attribute.  */
 	  if (lang_hooks.decls.function_decl_explicit_p (decl)
@@ -21742,10 +21760,13 @@ 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)
+gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die,
+			 tree class_type, tree member_type)
 {
   dw_die_ref ptr_die
     = new_die (DW_TAG_ptr_to_member_type,
@@ -21753,9 +21774,15 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
 
   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,
+		  lookup_type_die (class_type));
+  add_type_attribute (ptr_die, member_type, TYPE_UNQUALIFIED, false,
 		      context_die);
+
+  if (TREE_CODE (type) == OFFSET_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;
@@ -22663,6 +22690,25 @@ 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 this is a C++ method or function type with a ref-qualifier,
+     generate the corresponding attribute.  */
+  int rqual = lang_hooks.types.get_ref_qualifier (type);
+
+  if (rqual && (dwarf_version >= 5 || !dwarf_strict))
+    switch (rqual)
+      {
+      case 1:
+	add_AT_flag (subr_die, DW_AT_reference, 1);
+	break;
+
+      case 2:
+	add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
+	break;
+
+      default:
+	gcc_unreachable ();
+      }
 }
 
 /* Generate a DIE for a type definition.  */
@@ -22887,10 +22933,13 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   /* 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).  */
+     now.  (Vectors and arrays are special because the debugging info
+     is in the cloned type itself; method types are special because
+     they are never cv-qualified, but they can be ref-qualified, and
+     we don't want to drop these qualifiers from the method type).  */
   if (TREE_CODE (type) != VECTOR_TYPE
-      && TREE_CODE (type) != ARRAY_TYPE)
+      && TREE_CODE (type) != ARRAY_TYPE
+      && TREE_CODE (type) != METHOD_TYPE)
     type = type_main_variant (type);
 
   /* If this is an array type with hidden descriptor, handle it first.  */
@@ -22956,7 +23005,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 
       /* Now output a DIE to represent this pointer-to-data-member type
 	 itself.  */
-      gen_ptr_to_mbr_type_die (type, context_die);
+      gen_ptr_to_mbr_type_die (type, context_die,
+			       TYPE_OFFSET_BASETYPE (type), TREE_TYPE (type));
       break;
 
     case FUNCTION_TYPE:
@@ -22978,8 +23028,25 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       gen_array_type_die (type, context_die);
       break;
 
-    case ENUMERAL_TYPE:
     case RECORD_TYPE:
+      {
+	tree class_type = lang_hooks.types.get_ptrmemfn_type (type, 0);
+	if (class_type != NULL_TREE)
+	  {
+	    gen_type_die_with_usage (class_type, context_die,
+				     DINFO_USAGE_IND_USE);
+
+	    tree memfn_type = lang_hooks.types.get_ptrmemfn_type (type, 1);
+	    gen_type_die_with_usage (memfn_type, context_die,
+				     DINFO_USAGE_IND_USE);
+
+	    gen_ptr_to_mbr_type_die (type, context_die,
+				     class_type, memfn_type);
+	    return;
+	  }
+      }
+      /* Fall through.  */
+    case ENUMERAL_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
       gen_tagged_type_die (type, context_die, usage);
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 99ec401..5a09103 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -458,6 +458,14 @@ hook_tree_const_tree_null (const_tree t ATTRIBUTE_UNUSED)
   return NULL;
 }
 
+/* Generic hook that takes a const_tree and an int, and returns NULL_TREE.  */
+tree
+hook_tree_const_tree_int_null (const_tree t ATTRIBUTE_UNUSED,
+			       int i ATTRIBUTE_UNUSED)
+{
+  return NULL;
+}
+
 /* Generic hook that takes a rtx_insn * and an int and returns a bool.  */
 
 bool
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 2dc59ba..723be57 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -88,6 +88,7 @@ extern int hook_int_rtx_mode_as_bool_0 (rtx, machine_mode, addr_space_t,
 					bool);
 
 extern tree hook_tree_const_tree_null (const_tree);
+extern tree hook_tree_const_tree_int_null (const_tree, int);
 
 extern tree hook_tree_tree_tree_null (tree, tree);
 extern tree hook_tree_tree_tree_tree_null (tree, tree, tree);
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 10d910c..5961c42 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -180,6 +180,8 @@ 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_GET_REF_QUALIFIER	hook_int_const_tree_0
+#define LANG_HOOKS_GET_PTRMEMFN_TYPE    hook_tree_const_tree_int_null
 
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
   LANG_HOOKS_MAKE_TYPE, \
@@ -202,7 +204,9 @@ 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_GET_REF_QUALIFIER, \
+  LANG_HOOKS_GET_PTRMEMFN_TYPE \
 }
 
 /* Declaration hooks.  */
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 44c258e..cf8b550 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -160,6 +160,16 @@ 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 *);
+
+  /* Return 0 if TYPE is NOT a C++ method or function type with a
+     ref-qualifier, 1 if the ref-qualifier is '&', and 2 if it is
+     '&&'.  */
+  int (*get_ref_qualifier) (const_tree);
+
+  /* Return NULL if TYPE is NOT a C++ pointer to member function type.
+     Otherwise, return the class type when the selector is 0, or the
+     member function type when the selector is 1.  */
+  tree (*get_ptrmemfn_type) (const_tree, int);
 };
 
 /* Language hooks related to decls and the symbol table.  */
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
index 0000000..5d65196
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C
@@ -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/refqual-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C
new file mode 100644
index 0000000..221008e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C
@@ -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
index 0000000..ddf33c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C
@@ -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;
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 67b2a5b..8546f7e 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -309,6 +309,8 @@ DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
 /* DWARF 5.  */
+DW_AT (DW_AT_reference, 0x77)
+DW_AT (DW_AT_rvalue_reference, 0x78)
 DW_AT (DW_AT_noreturn, 0x87)
 DW_AT (DW_AT_deleted, 0x8a)
 DW_AT (DW_AT_defaulted, 0x8b)
