From DWARD, avoid adding IR nodes for member functions twice

* include/abg-fwd.h (as_non_member_class_decl): Declare new overload.
	* src/abg-ir.cc (as_non_member_class_decl): Define new overload.
	* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Add
	member functions to the DIE -> IR Node map.
	(build_ir_node_from_die): Assert that DW_TAG_subprogram cannot be
	for a member function here because getting the scope of the member
	function would have constructed the entire class that contains it,
	including the member function.  Then, calling
	build_ir_node_from_die for the DIE of the member function would
	find the already IR Node in the DIE -> IR Node map.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2014-02-11 16:04:24 +01:00
parent a5b80d8203
commit cc5af46601
3 changed files with 37 additions and 0 deletions

View File

@ -155,6 +155,9 @@ as_non_member_type(const shared_ptr<decl_base>);
shared_ptr<class_decl>
as_non_member_class_decl(const shared_ptr<decl_base>);
const class_decl*
as_non_member_class_decl(const decl_base* t);
bool
is_var_decl(const shared_ptr<decl_base>);

View File

@ -2328,6 +2328,7 @@ build_class_type_and_add_to_ir(read_context& ctxt,
is_dtor,
/*is_const*/false));
result->add_member_function(mem_fun);
ctxt.die_decl_map()[dwarf_dieoffset(&child)] = mem_fun;
}
// Handle member types
else if (is_type_die(&child))
@ -2976,9 +2977,21 @@ build_ir_node_from_die(read_context& ctxt,
return d;
}
}
{
const class_decl* cl = as_non_member_class_decl(scope);
// we shouldn't be in this class b/c, if this DIE is for a
// member function, get_scope_for_die on it (prior to
// calling this function) should have built the member
// function for this DIE, and thus, this function should
// have found the DIE for the member function in its cache.
assert(!cl);
}
ctxt.scope_stack().push(scope);
if ((result = build_function_decl(ctxt, die, called_from_public_decl)))
result = add_decl_to_scope(result, scope);
ctxt.scope_stack().pop();
}
break;

View File

@ -1094,6 +1094,27 @@ as_non_member_class_decl(const decl_base_sptr t)
return dynamic_pointer_cast<class_decl>(t);
}
/// Return the underlying class decl of a member class decl type.
///
/// If a given type is a member class decl, return its underlying
/// class type.
///
/// @param t the member type to consider.
///
/// @return the underlying class decl of the member type given in
/// parameter, if it's a member class decl. If the parameter was a
/// non-member class decl, just return that class decl. Otherwise, it
/// the parameter was not a class decl at all, return nil.
const class_decl*
as_non_member_class_decl(const decl_base* t)
{
const class_decl::member_type* m =
dynamic_cast<const class_decl::member_type*>(t);
if (m)
return dynamic_cast<const class_decl*>(m->get_underlying_type().get());
return dynamic_cast<const class_decl*>(t);
}
/// Tests wheter a declaration is a variable declaration.
///
/// @param decl the decl to test.