[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
This commit is contained in:
Alexandre Oliva 2016-08-12 07:11:23 +00:00 committed by Alexandre Oliva
parent df5b19dcc1
commit 8aaf799b00
11 changed files with 181 additions and 1 deletions

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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() {}

View File

@ -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>();

View File

@ -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>();

View File

@ -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

View File

@ -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>();

View File

@ -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>();

View File

@ -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>();

View File

@ -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>();