aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2016-08-12 07:11:23 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2016-08-12 07:11:23 +0000
commit8aaf799b005461231d75f0889e3c78bd9b35eed9 (patch)
tree737d04532927f66a28ff5e733a2d7ca27a390589 /gcc
parentdf5b19dcc1a27395ba96503540ca0085ccaa7ef7 (diff)
downloadgcc-8aaf799b005461231d75f0889e3c78bd9b35eed9.zip
gcc-8aaf799b005461231d75f0889e3c78bd9b35eed9.tar.gz
gcc-8aaf799b005461231d75f0889e3c78bd9b35eed9.tar.bz2
[PR49366] emit loc exprs for C++ non-virtual pmf template value parms
We used to emit, in debug information, the values bound to pointer to member function template parameters only when they were NULL or virtual member functions, because those can be represented with DW_AT_const_value. In order to represent the symbolic pointer to member function constants for non-virtual member functions, we'd need to be able to emit relocations for part of DW_AT_const_value, which we don't. The more viable alternative is to use DW_AT_location to represent such values, as slated for inclusion in DWARFv5, according to <URL:http://www.dwarfstd.org/ShowIssue.php?issue=130412.1>. With this patch, when we can't emit a DW_AT_const_value, we emit each "member" of the pointer to member function "record" as a DW_OP_stack_value DW_OP_piece, as long as the referenced member function is output in the same translation unit, otherwise we'd get relocations to external symbols, something to avoid in debug sections. for gcc/ChangeLog PR debug/49366 * dwarf2out.c (loc_list_from_tree_1): Expand some CONSTRUCTORs in DW_OP_pieces, just enough to handle pointers to member functions. (gen_remaining_tmpl_value_param_die_attribute): Use a location expression on DWARFv5 if a constant value doesn't work. for gcc/testsuite/ChangeLog PR debug/49366 * g++.dg/debug/dwarf2/template-params-12.H: New. * g++.dg/debug/dwarf2/template-params-12f.C: New. * g++.dg/debug/dwarf2/template-params-12g.C: New. * g++.dg/debug/dwarf2/template-params-12n.C: New. * g++.dg/debug/dwarf2/template-params-12s.C: New. * g++.dg/debug/dwarf2/template-params-12u.C: New. * g++.dg/debug/dwarf2/template-params-12v.C: New. * g++.dg/debug/dwarf2/template-params-12w.C: New. From-SVN: r239401
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/dwarf2out.c93
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12.H17
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12f.C7
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12g.C7
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12n.C10
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12s.C8
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12u.C7
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12v.C6
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/template-params-12w.C6
11 files changed, 181 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b861721..cdc5f29 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2016-08-12 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/49366
+ * dwarf2out.c (loc_list_from_tree_1): Expand some CONSTRUCTORs
+ in DW_OP_pieces, just enough to handle pointers to member
+ functions.
+ (gen_remaining_tmpl_value_param_die_attribute): Use a location
+ expression on DWARFv5 if a constant value doesn't work.
+
2016-08-11 David Malcolm <dmalcolm@redhat.com>
* selftest-run-tests.c (selftest::run_tests): Call selftest_c_tests.
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e3cb586..c658220 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -16142,6 +16142,89 @@ loc_list_from_tree_1 (tree loc, int want_address,
case COMPLEX_CST:
if ((ret = cst_pool_loc_descr (loc)))
have_address = 1;
+ else if (TREE_CODE (loc) == CONSTRUCTOR)
+ {
+ tree type = TREE_TYPE (loc);
+ unsigned HOST_WIDE_INT size = int_size_in_bytes (type);
+ unsigned HOST_WIDE_INT offset = 0;
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
+
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ /* This is very limited, but it's enough to output
+ pointers to member functions, as long as the
+ referenced function is defined in the current
+ translation unit. */
+ FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (loc), cnt, ce)
+ {
+ tree val = ce->value;
+
+ tree field = ce->index;
+
+ if (val)
+ STRIP_NOPS (val);
+
+ if (!field || DECL_BIT_FIELD (field))
+ {
+ expansion_failed (loc, NULL_RTX,
+ "bitfield in record type constructor");
+ size = offset = (unsigned HOST_WIDE_INT)-1;
+ ret = NULL;
+ break;
+ }
+
+ HOST_WIDE_INT fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
+ unsigned HOST_WIDE_INT pos = int_byte_position (field);
+ gcc_assert (pos + fieldsize <= size);
+ if (pos < offset)
+ {
+ expansion_failed (loc, NULL_RTX,
+ "out-of-order fields in record constructor");
+ size = offset = (unsigned HOST_WIDE_INT)-1;
+ ret = NULL;
+ break;
+ }
+ if (pos > offset)
+ {
+ ret1 = new_loc_descr (DW_OP_piece, pos - offset, 0);
+ add_loc_descr (&ret, ret1);
+ offset = pos;
+ }
+ if (val && fieldsize != 0)
+ {
+ ret1 = loc_descriptor_from_tree (val, want_address, context);
+ if (!ret1)
+ {
+ expansion_failed (loc, NULL_RTX,
+ "unsupported expression in field");
+ size = offset = (unsigned HOST_WIDE_INT)-1;
+ ret = NULL;
+ break;
+ }
+ add_loc_descr (&ret, ret1);
+ }
+ if (fieldsize)
+ {
+ ret1 = new_loc_descr (DW_OP_piece, fieldsize, 0);
+ add_loc_descr (&ret, ret1);
+ offset = pos + fieldsize;
+ }
+ }
+
+ if (offset != size)
+ {
+ ret1 = new_loc_descr (DW_OP_piece, size - offset, 0);
+ add_loc_descr (&ret, ret1);
+ offset = size;
+ }
+
+ have_address = !!want_address;
+ }
+ else
+ expansion_failed (loc, NULL_RTX,
+ "constructor of non-record type");
+ }
else
/* We can construct small constants here using int_loc_descriptor. */
expansion_failed (loc, NULL_RTX,
@@ -24177,7 +24260,15 @@ gen_remaining_tmpl_value_param_die_attribute (void)
FOR_EACH_VEC_ELT (*tmpl_value_parm_die_table, i, e)
{
if (!tree_add_const_value_attribute (e->die, e->arg))
- (*tmpl_value_parm_die_table)[j++] = *e;
+ {
+ dw_loc_descr_ref loc = NULL;
+ if (dwarf_version >= 5 || !dwarf_strict)
+ loc = loc_descriptor_from_tree (e->arg, 2, NULL);
+ if (loc)
+ add_AT_loc (e->die, DW_AT_location, loc);
+ else
+ (*tmpl_value_parm_die_table)[j++] = *e;
+ }
}
tmpl_value_parm_die_table->truncate (j);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 26fe157..54939b8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2016-08-12 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/49366
+ * g++.dg/debug/dwarf2/template-params-12.H: New.
+ * g++.dg/debug/dwarf2/template-params-12f.C: New.
+ * g++.dg/debug/dwarf2/template-params-12g.C: New.
+ * g++.dg/debug/dwarf2/template-params-12n.C: New.
+ * g++.dg/debug/dwarf2/template-params-12s.C: New.
+ * g++.dg/debug/dwarf2/template-params-12u.C: New.
+ * g++.dg/debug/dwarf2/template-params-12v.C: New.
+ * g++.dg/debug/dwarf2/template-params-12w.C: New.
+
2016-08-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
PR target/72863
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12.H b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12.H
new file mode 100644
index 0000000..24c26e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12.H
@@ -0,0 +1,17 @@
+// Tests for the fix for PR debug/49366.
+struct B {
+ void g();
+ virtual void v() = 0;
+ virtual void w();
+};
+void B::g() {}
+void B::w() {}
+struct S : B {
+ void f();
+ void v();
+ void u();
+};
+void S::f() {}
+void S::v() {}
+template <void (B::*MF)()> void t() {}
+template <void (S::*MF)()> void t() {}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12f.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12f.C
new file mode 100644
index 0000000..e2da829
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12f.C
@@ -0,0 +1,7 @@
+// { dg-options "-gdwarf-2 -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]*\[^\n\]* DW_AT_location\n\[^\n\]* DW_OP_addr\n\[^\n\]*_ZN1S1fEv\[^\n\]*\n\[^\n\]* DW_OP_stack_value\n\[^\n\]* DW_OP_piece\n\[^\n\]*\n\[^\n\]* DW_OP_lit0\n\[^\n\]* DW_OP_stack_value\n\[^\n\]* DW_OP_piece" 1 } }
+#include "template-params-12.H"
+/* We get a location list with a pair of DW_OP_pieces for pointers to
+ non-virtual member functions. */
+template void t<&S::f>();
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12g.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12g.C
new file mode 100644
index 0000000..813f71d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12g.C
@@ -0,0 +1,7 @@
+// { dg-options "-gdwarf-2 -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]*\[^\n\]* DW_AT_location\n\[^\n\]* DW_OP_addr\n\[^\n\]*_ZN1B1gEv\[^\n\]*\n\[^\n\]* DW_OP_stack_value\n\[^\n\]* DW_OP_piece\n\[^\n\]*\n\[^\n\]* DW_OP_lit0\n\[^\n\]* DW_OP_stack_value\n\[^\n\]* DW_OP_piece" 1 } }
+#include "template-params-12.H"
+/* We get a location list with a pair of DW_OP_pieces for pointers to
+ non-virtual member functions. */
+template void t<&S::g>();
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12n.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12n.C
new file mode 100644
index 0000000..d3c1f58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12n.C
@@ -0,0 +1,10 @@
+// { dg-options "-gdwarf-2 -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]* DW_AT_const_value" 1 } }
+#include "template-params-12.H"
+/* We get const_value for NULL pointers to member functions. */
+#if __cplusplus > 199711L // Ugh, C++98 barfs at both the cast and the overload.
+template void t<static_cast<void (S::*)()>(0)>();
+#else
+template void t<&S::v>();
+#endif
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12s.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12s.C
new file mode 100644
index 0000000..8940eaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12s.C
@@ -0,0 +1,8 @@
+// { dg-options "-gdwarf-4 -gstrict-dwarf -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]* \[^\n\]*DIE" 1 } }
+#include "template-params-12.H"
+/* We do NOT get a value or location for this one, because we've
+ enabled strict DWARF 4, and it could only be emitted as a location,
+ which is DWARF 5 only for template value params. */
+template void t<&S::f>();
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12u.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12u.C
new file mode 100644
index 0000000..f79fa84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12u.C
@@ -0,0 +1,7 @@
+// { dg-options "-gdwarf-2 -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]* \[^\n\]*DIE" 1 } }
+#include "template-params-12.H"
+/* We do NOT get a value or location for this one, because it would
+ require a relocation to an undefined symbol in a debug section. */
+template void t<&S::u>();
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12v.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12v.C
new file mode 100644
index 0000000..11aabae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12v.C
@@ -0,0 +1,6 @@
+// { dg-options "-gdwarf-2 -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]* DW_AT_const_value" 1 } }
+#include "template-params-12.H"
+/* We get const_value for pointers to virtual member functions. */
+template void t<&S::v>();
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12w.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12w.C
new file mode 100644
index 0000000..11aabae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-12w.C
@@ -0,0 +1,6 @@
+// { dg-options "-gdwarf-2 -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_template_value_param\[^\n\]*\n\[^\n\]* DW_AT_name\n\[^\n\]* DW_AT_type\n\[^\n\]* DW_AT_const_value" 1 } }
+#include "template-params-12.H"
+/* We get const_value for pointers to virtual member functions. */
+template void t<&S::v>();