re PR c++/52637 (ICE producing debug info for c++11 code using local class as template argument)
PR c++/52637 * dwarf2out.c (modified_type_die): Use scope_die_for. (gen_type_die_with_usage, dwarf2out_finish): Likewise. (uses_local_type_r, uses_local_type): New. (scope_die_for): Keep a type that uses a local type in local scope. Use get_context_die for namespace and type scope. From-SVN: r188812
This commit is contained in:
parent
fd72d9c98b
commit
912bc3ba41
|
@ -1,3 +1,12 @@
|
|||
2012-06-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/52637
|
||||
* dwarf2out.c (modified_type_die): Use scope_die_for.
|
||||
(gen_type_die_with_usage, dwarf2out_finish): Likewise.
|
||||
(uses_local_type_r, uses_local_type): New.
|
||||
(scope_die_for): Keep a type that uses a local type in local scope.
|
||||
Use get_context_die for namespace and type scope.
|
||||
|
||||
2012-06-19 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/53470
|
||||
|
|
105
gcc/dwarf2out.c
105
gcc/dwarf2out.c
|
@ -9790,6 +9790,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
|
|||
tree item_type = NULL;
|
||||
tree qualified_type;
|
||||
tree name, low, high;
|
||||
dw_die_ref mod_scope;
|
||||
|
||||
if (code == ERROR_MARK)
|
||||
return NULL;
|
||||
|
@ -9850,6 +9851,8 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
|
|||
/* Else cv-qualified version of named type; fall through. */
|
||||
}
|
||||
|
||||
mod_scope = scope_die_for (type, context_die);
|
||||
|
||||
if (is_const_type
|
||||
/* If both is_const_type and is_volatile_type, prefer the path
|
||||
which leads to a qualified type. */
|
||||
|
@ -9857,17 +9860,17 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
|
|||
|| get_qualified_type (type, TYPE_QUAL_CONST) == NULL_TREE
|
||||
|| get_qualified_type (type, TYPE_QUAL_VOLATILE) != NULL_TREE))
|
||||
{
|
||||
mod_type_die = new_die (DW_TAG_const_type, comp_unit_die (), type);
|
||||
mod_type_die = new_die (DW_TAG_const_type, mod_scope, type);
|
||||
sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
|
||||
}
|
||||
else if (is_volatile_type)
|
||||
{
|
||||
mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die (), type);
|
||||
mod_type_die = new_die (DW_TAG_volatile_type, mod_scope, type);
|
||||
sub_die = modified_type_die (type, is_const_type, 0, context_die);
|
||||
}
|
||||
else if (code == POINTER_TYPE)
|
||||
{
|
||||
mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die (), type);
|
||||
mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type);
|
||||
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
|
||||
simple_type_size_in_bits (type) / BITS_PER_UNIT);
|
||||
item_type = TREE_TYPE (type);
|
||||
|
@ -9878,10 +9881,10 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
|
|||
else if (code == REFERENCE_TYPE)
|
||||
{
|
||||
if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
|
||||
mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die (),
|
||||
mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope,
|
||||
type);
|
||||
else
|
||||
mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die (), type);
|
||||
mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type);
|
||||
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
|
||||
simple_type_size_in_bits (type) / BITS_PER_UNIT);
|
||||
item_type = TREE_TYPE (type);
|
||||
|
@ -16079,10 +16082,36 @@ pop_decl_scope (void)
|
|||
VEC_pop (tree, decl_scope_table);
|
||||
}
|
||||
|
||||
/* walk_tree helper function for uses_local_type, below. */
|
||||
|
||||
static tree
|
||||
uses_local_type_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (!TYPE_P (*tp))
|
||||
*walk_subtrees = 0;
|
||||
else
|
||||
{
|
||||
tree name = TYPE_NAME (*tp);
|
||||
if (name && DECL_P (name) && decl_function_context (name))
|
||||
return *tp;
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* If TYPE involves a function-local type (including a local typedef to a
|
||||
non-local type), returns that type; otherwise returns NULL_TREE. */
|
||||
|
||||
static tree
|
||||
uses_local_type (tree type)
|
||||
{
|
||||
tree used = walk_tree_without_duplicates (&type, uses_local_type_r, NULL);
|
||||
return used;
|
||||
}
|
||||
|
||||
/* Return the DIE for the scope that immediately contains this type.
|
||||
Non-named types get global scope. Named types nested in other
|
||||
types get their containing scope if it's open, or global scope
|
||||
otherwise. All other types (i.e. function-local named types) get
|
||||
Non-named types that do not involve a function-local type get global
|
||||
scope. Named types nested in namespaces or other types get their
|
||||
containing scope. All other types (i.e. function-local named types) get
|
||||
the current active scope. */
|
||||
|
||||
static dw_die_ref
|
||||
|
@ -16090,18 +16119,24 @@ scope_die_for (tree t, dw_die_ref context_die)
|
|||
{
|
||||
dw_die_ref scope_die = NULL;
|
||||
tree containing_scope;
|
||||
int i;
|
||||
|
||||
/* Non-types always go in the current scope. */
|
||||
gcc_assert (TYPE_P (t));
|
||||
|
||||
containing_scope = TYPE_CONTEXT (t);
|
||||
/* Use the scope of the typedef, rather than the scope of the type
|
||||
it refers to. */
|
||||
if (TYPE_NAME (t) && DECL_P (TYPE_NAME (t)))
|
||||
containing_scope = DECL_CONTEXT (TYPE_NAME (t));
|
||||
else
|
||||
containing_scope = TYPE_CONTEXT (t);
|
||||
|
||||
/* Use the containing namespace if it was passed in (for a declaration). */
|
||||
/* Use the containing namespace if there is one. */
|
||||
if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
|
||||
{
|
||||
if (context_die == lookup_decl_die (containing_scope))
|
||||
/* OK */;
|
||||
else if (debug_info_level > DINFO_LEVEL_TERSE)
|
||||
context_die = get_context_die (containing_scope);
|
||||
else
|
||||
containing_scope = NULL_TREE;
|
||||
}
|
||||
|
@ -16113,30 +16148,25 @@ scope_die_for (tree t, dw_die_ref context_die)
|
|||
containing_scope = NULL_TREE;
|
||||
|
||||
if (SCOPE_FILE_SCOPE_P (containing_scope))
|
||||
scope_die = comp_unit_die ();
|
||||
{
|
||||
/* If T uses a local type keep it local as well, to avoid references
|
||||
to function-local DIEs from outside the function. */
|
||||
if (current_function_decl && uses_local_type (t))
|
||||
scope_die = context_die;
|
||||
else
|
||||
scope_die = comp_unit_die ();
|
||||
}
|
||||
else if (TYPE_P (containing_scope))
|
||||
{
|
||||
/* For types, we can just look up the appropriate DIE. But
|
||||
first we check to see if we're in the middle of emitting it
|
||||
so we know where the new DIE should go. */
|
||||
for (i = VEC_length (tree, decl_scope_table) - 1; i >= 0; --i)
|
||||
if (VEC_index (tree, decl_scope_table, i) == containing_scope)
|
||||
break;
|
||||
|
||||
if (i < 0)
|
||||
/* For types, we can just look up the appropriate DIE. */
|
||||
if (debug_info_level > DINFO_LEVEL_TERSE)
|
||||
scope_die = get_context_die (containing_scope);
|
||||
else
|
||||
{
|
||||
gcc_assert (debug_info_level <= DINFO_LEVEL_TERSE
|
||||
|| TREE_ASM_WRITTEN (containing_scope));
|
||||
/*We are not in the middle of emitting the type
|
||||
CONTAINING_SCOPE. Let's see if it's emitted already. */
|
||||
scope_die = lookup_type_die (containing_scope);
|
||||
|
||||
/* If none of the current dies are suitable, we get file scope. */
|
||||
scope_die = lookup_type_die_strip_naming_typedef (containing_scope);
|
||||
if (scope_die == NULL)
|
||||
scope_die = comp_unit_die ();
|
||||
}
|
||||
else
|
||||
scope_die = lookup_type_die_strip_naming_typedef (containing_scope);
|
||||
}
|
||||
else
|
||||
scope_die = context_die;
|
||||
|
@ -18925,12 +18955,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
|
|||
/* Prevent broken recursion; we can't hand off to the same type. */
|
||||
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
|
||||
|
||||
/* Use the DIE of the containing namespace as the parent DIE of
|
||||
the type description DIE we want to generate. */
|
||||
if (DECL_FILE_SCOPE_P (TYPE_NAME (type))
|
||||
|| (DECL_CONTEXT (TYPE_NAME (type))
|
||||
&& TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL))
|
||||
context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
|
||||
/* Give typedefs the right scope. */
|
||||
context_die = scope_die_for (type, context_die);
|
||||
|
||||
TREE_ASM_WRITTEN (type) = 1;
|
||||
|
||||
|
@ -22553,16 +22579,15 @@ dwarf2out_finish (const char *filename)
|
|||
inlined and optimized out. In that case we are lost and
|
||||
assign the empty child. This should not be big issue as
|
||||
the function is likely unreachable too. */
|
||||
tree context = NULL_TREE;
|
||||
|
||||
gcc_assert (node->created_for);
|
||||
|
||||
if (DECL_P (node->created_for))
|
||||
context = DECL_CONTEXT (node->created_for);
|
||||
origin = get_context_die (DECL_CONTEXT (node->created_for));
|
||||
else if (TYPE_P (node->created_for))
|
||||
context = TYPE_CONTEXT (node->created_for);
|
||||
origin = scope_die_for (node->created_for, comp_unit_die ());
|
||||
else
|
||||
origin = comp_unit_die ();
|
||||
|
||||
origin = get_context_die (context);
|
||||
add_child_die (origin, die);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2012-06-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/52637
|
||||
* g++.dg/debug/localclass1.C: New.
|
||||
|
||||
* g++.dg/debug/dwarf2/namespace-2.C: New.
|
||||
* g++.dg/debug/dwarf2/localclass3.C: New.
|
||||
|
||||
2012-06-19 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/53470
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Test that the A* pointer_type is also within the debug info for f.
|
||||
// Currently GCC emits it immediately before A, which is simple to test for.
|
||||
// { dg-options "-g -dA" }
|
||||
|
||||
void f()
|
||||
{
|
||||
struct A { int i; } *ap;
|
||||
ap->i = 42;
|
||||
}
|
||||
|
||||
// { dg-final { scan-assembler "DW_TAG_pointer_type.\[^)\]*. DW_TAG_structure_type" } }
|
|
@ -0,0 +1,10 @@
|
|||
// Test that we define A inside the namespace rather than declaring it
|
||||
// there and then defining it at CU scope.
|
||||
// { dg-options "-g -dA" }
|
||||
// { dg-final { scan-assembler-not "DW_AT_declaration" } }
|
||||
|
||||
namespace N {
|
||||
struct A;
|
||||
}
|
||||
|
||||
struct N::A { } a;
|
|
@ -0,0 +1,21 @@
|
|||
// PR c++/52637
|
||||
// { dg-options "-g -std=c++11" }
|
||||
|
||||
template <typename T>
|
||||
struct C { };
|
||||
|
||||
template <typename V>
|
||||
void f(V v) {
|
||||
struct B {};
|
||||
C<B> c;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void g(T t) {
|
||||
struct A { } a;
|
||||
f (a);
|
||||
}
|
||||
|
||||
struct D {
|
||||
void h() { g(0); }
|
||||
};
|
Loading…
Reference in New Issue