Fix reading several clones of the same member function from DWARF

* include/abg-fwd.h (set_member_function_is_ctor)
	(set_member_function_is_dtor, set_member_function_is_const)
	(set_member_function_vtable_offset): Declare new functions.
	* include/abg-ir.h (class_decl::sort_virtual_mem_fns): Declare new
	member function.
	(mem_fn_context_rel::{vtable_offset, is_constructor is_destructor,
	is_const}): Add these setters.
	(set_member_function_is_ctor, set_member_function_is_dtor)
	(set_member_function_is_static, set_member_function_is_const)
	(set_member_function_vtable_offset)
	(set_member_function_is_virtual): Declare these new friend
	function to class class_decl::method_decl.
	* src/abg-dwarf-reader.cc (finish_member_function_reading): Split
	this out from build_class_type_and_add_to_ir.  Use the new setters
	for member functions properties introduced above.
	(build_class_type_and_add_to_ir): Factorize the creation of member
	function by using build_ir_node_from_die.  Once that function has
	created the member function in a rather generic way, use the new
	finish_member_function_reading to set the remaining specific
	properties for member functions.
	(build_function_decl): When called to read additional properties
	of a function_decl, allow this to read and update the elf symbol
	properties too.  This is useful for building a clone of a function
	that already has an elf symbol.
	(build_ir_node_from_die):  When building a function decl, consider
	the case of a DIE that has both DW_AT_specification and
	DW_AT_abstract_origin set.  That is, DW_AT_abstract_origin is set,
	and the origin has DW_AT_specification set.  This is basically a
	clone of a function that implements an interface (this happens for
	destructors, for instance).  In this case, really do the cloning
	of the interface implementation.  If the cloned function happens
	to be member function, use finish_member_function_reading to read
	the properties relevant to its method-ness.
	* src/abg-ir.cc (set_member_function_is_ctor)
	(set_member_function_is_dtor, set_member_function_is_const)
	(set_member_function_vtable_offset)
	(class_decl::sort_virtual_mem_fns): Define new functions.
	(sort_virtual_member_functions): Define new static function.
	(struct virtual_member_function_less_than): New functor.
	(class_decl::add_member_function): Keep virtual member functions
	vector sorted.
	* data/test-read-dwarf/test1.abi: Adjust.  Now, both the
	cdtor specification and all the clones that implements the
	different are emitted.
	* data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2014-10-01 17:42:45 +02:00
parent 5616233cf8
commit cbf1debeab
6 changed files with 440 additions and 90 deletions

View File

@ -307,24 +307,50 @@ get_member_function_is_ctor(const function_decl&);
bool
get_member_function_is_ctor(const shared_ptr<function_decl>);
void
set_member_function_is_ctor(const function_decl&, bool);
void
set_member_function_is_ctor(const shared_ptr<function_decl>, bool);
bool
get_member_function_is_dtor(const function_decl&);
bool
get_member_function_is_dtor(const shared_ptr<function_decl>);
void
set_member_function_is_dtor(const function_decl&, bool);
void
set_member_function_is_dtor(const shared_ptr<function_decl>, bool);
bool
get_member_function_is_const(const function_decl&);
bool
get_member_function_is_const(const shared_ptr<function_decl>);
void
set_member_function_is_const(const function_decl&, bool);
void
set_member_function_is_const(const shared_ptr<function_decl>, bool);
size_t
get_member_function_vtable_offset(const function_decl&);
size_t
get_member_function_vtable_offset(const shared_ptr<function_decl>);
void
set_member_function_vtable_offset(const function_decl& f,
size_t s);
void
set_member_function_vtable_offset(const shared_ptr<function_decl> f,
size_t s);
bool
get_member_function_is_virtual(const function_decl&);

View File

@ -2488,6 +2488,9 @@ public:
const member_functions&
get_virtual_mem_fns() const;
void
sort_virtual_mem_fns();
void
add_member_function_template(shared_ptr<member_function_template>);
@ -2714,6 +2717,16 @@ public:
vtable_offset() const
{return vtable_offset_in_bits_;}
/// Setter for the vtable offset property.
///
/// This is the vtable offset of the member function of this
/// relation.
///
/// @partam s the new vtable offset.
void
vtable_offset(size_t s)
{vtable_offset_in_bits_ = s;}
/// Getter for the 'is-constructor' property.
///
/// This tells if the member function of this relation is a
@ -2724,6 +2737,14 @@ public:
is_constructor() const
{return is_constructor_;}
/// Setter for the 'is-constructor' property.
///
/// @param f the new value of the the property. Is true if this is
/// for a constructor, false otherwise.
void
is_constructor(bool f)
{is_constructor_ = f;}
/// Getter for the 'is-destructor' property.
///
/// Tells if the member function of this relation is a destructor.
@ -2733,6 +2754,14 @@ public:
is_destructor() const
{return is_destructor_;}
/// Setter for the 'is-destructor' property.
///
/// @param f the new value of the property. Is true if this is for
/// a destructor, false otherwise.
void
is_destructor(bool f)
{is_destructor_ = f;}
/// Getter for the 'is-const' property.
///
/// Tells if the member function of this relation is a const member
@ -2743,6 +2772,14 @@ public:
is_const() const
{return is_const_;}
/// Setter for the 'is-const' property.
///
/// @param f the new value of the property. Is true if this is for
/// a const entity, false otherwise.
void
is_const(bool f)
{is_const_ = f;}
virtual ~mem_fn_context_rel();
}; // end class mem_fn_context_rel
@ -2789,18 +2826,39 @@ public:
friend bool
get_member_function_is_ctor(const function_decl&);
friend void
set_member_function_is_ctor(const function_decl&, bool);
friend bool
get_member_function_is_dtor(const function_decl&);
friend void
set_member_function_is_dtor(const function_decl&, bool);
friend bool
get_member_function_is_static(const function_decl&);
friend void
set_member_function_is_static(const function_decl&, bool);
friend bool
get_member_function_is_const(const function_decl&);
friend void
set_member_function_is_const(const function_decl&, bool);
friend size_t
get_member_function_vtable_offset(const function_decl&);
friend void
set_member_function_vtable_offset(const function_decl&, size_t);
friend bool
get_member_function_is_virtual(const function_decl&);
friend void
set_member_function_is_virtual(const function_decl&, bool);
virtual ~method_decl();
};// end class class_decl::method_decl

View File

@ -43,6 +43,7 @@
#include <ostream>
#include <sstream>
#include "abg-dwarf-reader.h"
#include "abg-sptr-utils.h"
using std::string;
@ -54,6 +55,7 @@ namespace dwarf_reader
{
using std::tr1::dynamic_pointer_cast;
using std::tr1::static_pointer_cast;
using std::tr1::unordered_map;
using std::stack;
using std::deque;
@ -2425,6 +2427,11 @@ build_function_decl(read_context& ctxt,
size_t where_offset,
function_decl_sptr fn);
static void
finish_member_function_reading(Dwarf_Die* die,
function_decl_sptr f,
class_decl_sptr klass);
/// Constructor for a default Dwfl handle that knows how to load debug
/// info from a library or executable elf file.
///
@ -4865,6 +4872,80 @@ build_enum_type(read_context& ctxt, Dwarf_Die* die)
return result;
}
/// Once a function_decl has been built and added to a class as a
/// member function, this function updates the informatikon of the
/// function_decl concerning the properties of its relationship with
/// the member class. That is, it updates properties like
/// virtualness, access, constness, cdtorness, etc ...
///
/// @param die the DIE of the function_decl that has been just built.
///
/// @param f the function_decl that has just been built from @p die.
///
/// @param klass the class_decl that @p f belongs to.
static void
finish_member_function_reading(Dwarf_Die* die,
function_decl_sptr f,
class_decl_sptr klass)
{
assert(klass);
class_decl::method_decl_sptr m =
dynamic_pointer_cast<class_decl::method_decl>(f);
assert(m);
bool is_ctor = (f->get_name() == klass->get_name());
bool is_dtor = (!f->get_name().empty()
&& f->get_name()[0] == '~');
bool is_virtual = die_is_virtual(die);
size_t vindex = 0;
if (is_virtual)
die_virtual_function_index(die, vindex);
access_specifier access =
klass->is_struct()
? public_access
: private_access;
die_access_specifier(die, access);
bool is_static = false;
{
// Let's see if the first parameter has the same class
// type as the current class has a DW_AT_artificial
// attribute flag set. We are not looking at
// DW_AT_object_pointer (for DWARF 3) because it
// wasn't being emitted in GCC 4_4, which was already
// DWARF 3.
function_decl::parameter_sptr first_parm;
if (!f->get_parameters().empty())
first_parm = f->get_parameters()[0];
bool is_artificial =
first_parm && first_parm->get_artificial();;
pointer_type_def_sptr this_ptr_type;
if (is_artificial)
this_ptr_type =
dynamic_pointer_cast<pointer_type_def>
(first_parm->get_type());
if (this_ptr_type && (get_pretty_representation
(this_ptr_type->get_pointed_to_type())
== klass->get_pretty_representation()))
;
else
is_static = true;
}
set_member_access_specifier(m, access);
set_member_function_is_virtual(m, is_virtual);
set_member_function_vtable_offset(m, vindex);
set_member_is_static(m, is_static);
set_member_function_is_ctor(m, is_ctor);
set_member_function_is_dtor(m, is_dtor);
set_member_function_is_const(m, false);
assert(is_member_function(m));
if (is_virtual)
klass->sort_virtual_mem_fns();
}
/// Build a an IR node for class type from a DW_TAG_structure_type or
/// DW_TAG_class_type and
///
@ -5073,68 +5154,21 @@ build_class_type_and_add_to_ir(read_context& ctxt,
// Handle member functions;
else if (tag == DW_TAG_subprogram)
{
if (die_is_artificial(&child))
// For now, let's not consider artificial functions.
// To consider them, we'd need to make the IR now
// about artificial functions and the
// (de)serialization and comparison machineries to
// know how to cope with these.
decl_base_sptr r = build_ir_node_from_die(ctxt, &child,
is_in_alt_di,
result.get(),
called_from_public_decl,
where_offset);
if (!r)
continue;
function_decl_sptr f =
build_function_decl(ctxt, &child, is_in_alt_di,
where_offset, function_decl_sptr());
if (!f)
continue;
class_decl::method_decl_sptr m =
dynamic_pointer_cast<class_decl::method_decl>(f);
assert(m);
function_decl_sptr f = dynamic_pointer_cast<function_decl>(r);
assert(f);
bool is_ctor = (f->get_name() == result->get_name());
bool is_dtor = (!f->get_name().empty()
&& f->get_name()[0] == '~');
bool is_virtual = die_is_virtual(&child);
size_t vindex = 0;
if (is_virtual)
die_virtual_function_index(&child, vindex);
access_specifier access =
is_struct
? public_access
: private_access;
die_access_specifier(&child, access);
bool is_static = false;
{
// Let's see if the first parameter has the same class
// type as the current class has a DW_AT_artificial
// attribute flag set. We are not looking at
// DW_AT_object_pointer (for DWARF 3) because it
// wasn't being emitted in GCC 4_4, which was already
// DWARF 3.
function_decl::parameter_sptr first_parm;
if (!f->get_parameters().empty())
first_parm = f->get_parameters()[0];
finish_member_function_reading(&child, f, result);
bool is_artificial =
first_parm && first_parm->get_artificial();;
pointer_type_def_sptr this_ptr_type;
if (is_artificial)
this_ptr_type =
dynamic_pointer_cast<pointer_type_def>
(first_parm->get_type());
if (this_ptr_type && (get_pretty_representation
(this_ptr_type->get_pointed_to_type())
== result->get_pretty_representation()))
;
else
is_static = true;
}
result->add_member_function(m, access, is_virtual,
vindex, is_static, is_ctor,
is_dtor, /*is_const*/false);
assert(is_member_function(m));
ctxt.associate_die_to_decl(dwarf_dieoffset(&child),
is_in_alt_di,
m);
is_in_alt_di, f);
}
// Handle member types
else if (is_type_die(&child))
@ -5793,20 +5827,17 @@ build_function_decl(read_context& ctxt,
// Check if a function symbol with this name is exported by the elf
// binary.
if (!result->get_symbol())
Dwarf_Addr fn_addr;
if (ctxt.get_function_address(die, fn_addr))
{
Dwarf_Addr fn_addr;
if (ctxt.get_function_address(die, fn_addr))
{
elf_symbol_sptr sym;
if ((sym = ctxt.lookup_elf_fn_symbol_from_address(fn_addr)))
if (sym->is_function() && sym->is_public())
{
result->set_symbol(sym);
result->set_linkage_name(sym->get_name());
result->set_is_in_public_symbol_table(true);
}
}
elf_symbol_sptr sym;
if ((sym = ctxt.lookup_elf_fn_symbol_from_address(fn_addr)))
if (sym->is_function() && sym->is_public())
{
result->set_symbol(sym);
result->set_linkage_name(sym->get_name());
result->set_is_in_public_symbol_table(true);
}
}
return result;
@ -6148,17 +6179,17 @@ build_ir_node_from_die(read_context& ctxt,
break;
function_decl_sptr fn;
bool fn_is_clone = false;
bool is_in_alternate_debug_info = false;
if (die_die_attribute(die, die_is_from_alt_di,
DW_AT_specification,
spec_die, is_in_alternate_debug_info,
true)
|| (fn_is_clone =
die_die_attribute(die, die_is_from_alt_di,
DW_AT_abstract_origin,
spec_die, is_in_alternate_debug_info,
true)))
bool has_spec = die_die_attribute(die, die_is_from_alt_di,
DW_AT_specification,
spec_die, is_in_alternate_debug_info,
true);
bool fn_is_clone = die_die_attribute(die, die_is_from_alt_di,
DW_AT_abstract_origin,
spec_die,
is_in_alternate_debug_info,
true);
if (has_spec || fn_is_clone)
{
scop = get_scope_for_die(ctxt, &spec_die,
is_in_alternate_debug_info,
@ -6186,11 +6217,20 @@ build_ir_node_from_die(read_context& ctxt,
}
ctxt.scope_stack().push(scope);
if ((result = build_function_decl(ctxt, die, die_is_from_alt_di,
where_offset, fn))
&& !fn)
result = build_function_decl(ctxt, die, die_is_from_alt_di,
where_offset, fn);
if (result && !fn)
result = add_decl_to_scope(result, scope);
fn = dynamic_pointer_cast<function_decl>(result);
if (fn && is_member_function(fn))
{
class_decl_sptr klass(static_cast<class_decl*>(scope),
sptr_utils::noop_deleter());
assert(klass);
finish_member_function_reading(die, fn, klass);
}
ctxt.scope_stack().pop();
}
break;

View File

@ -1897,6 +1897,38 @@ bool
get_member_function_is_ctor(const function_decl_sptr f)
{return get_member_function_is_ctor(*f);}
/// Setter for the is_ctor property of the member function.
///
/// @param f the member function to set.
///
/// @param f the new boolean value of the is_ctor property. Is true
/// if @p f is a constructor, false otherwise.
void
set_member_function_is_ctor(const function_decl& f, bool c)
{
assert(is_member_function(f));
const class_decl::method_decl* m =
dynamic_cast<const class_decl::method_decl*>(&f);
assert(m);
mem_fn_context_rel_sptr ctxt =
dynamic_pointer_cast<mem_fn_context_rel>(m->get_context_rel());
ctxt->is_constructor(c);
}
/// Setter for the is_ctor property of the member function.
///
/// @param f the member function to set.
///
/// @param f the new boolean value of the is_ctor property. Is true
/// if @p f is a constructor, false otherwise.
void
set_member_function_is_ctor(const function_decl_sptr f, bool c)
{set_member_function_is_ctor(*f, c);}
/// Test whether a member function is a destructor.
///
/// @param f the function to test.
@ -1926,6 +1958,35 @@ bool
get_member_function_is_dtor(const function_decl_sptr f)
{return get_member_function_is_dtor(*f);}
/// Set the destructor-ness property of a member function.
///
/// @param f the function to set.
///
/// @param d true if @p f is a destructor, false otherwise.
void
set_member_function_is_dtor(const function_decl& f, bool d)
{
assert(is_member_function(f));
const class_decl::method_decl* m =
dynamic_cast<const class_decl::method_decl*>(&f);
assert(m);
mem_fn_context_rel_sptr ctxt =
dynamic_pointer_cast<mem_fn_context_rel>(m->get_context_rel());
ctxt->is_destructor(d);
}
/// Set the destructor-ness property of a member function.
///
/// @param f the function to set.
///
/// @param d true if @p f is a destructor, false otherwise.
void
set_member_function_is_dtor(const function_decl_sptr f, bool d)
{set_member_function_is_dtor(*f, d);}
/// Test whether a member function is const.
///
/// @param f the function to test.
@ -1955,6 +2016,35 @@ bool
get_member_function_is_const(const function_decl_sptr f)
{return get_member_function_is_const(*f);}
/// set the const-ness property of a member function.
///
/// @param f the function to set.
///
/// @param is_const the new value of the const-ness property of @p f
void
set_member_function_is_const(const function_decl& f, bool is_const)
{
assert(is_member_function(f));
const class_decl::method_decl* m =
dynamic_cast<const class_decl::method_decl*>(&f);
assert(m);
mem_fn_context_rel_sptr ctxt =
dynamic_pointer_cast<mem_fn_context_rel>(m->get_context_rel());
ctxt->is_const(is_const);
}
/// set the const-ness property of a member function.
///
/// @param f the function to set.
///
/// @param is_const the new value of the const-ness property of @p f
void
set_member_function_is_const(const function_decl_sptr f, bool is_const)
{set_member_function_is_const(*f, is_const);}
/// Get the vtable offset of a member function.
///
/// @param f the member function to consider.
@ -1984,6 +2074,34 @@ size_t
get_member_function_vtable_offset(const function_decl_sptr f)
{return get_member_function_vtable_offset(*f);}
/// Set the vtable offset of a member function.
///
/// @param f the member function to consider.
///
/// @param s the new vtable offset.
void
set_member_function_vtable_offset(const function_decl& f, size_t s)
{
assert(is_member_function(f));
const class_decl::method_decl* m =
dynamic_cast<const class_decl::method_decl*>(&f);
assert(m);
mem_fn_context_rel_sptr ctxt =
dynamic_pointer_cast<mem_fn_context_rel>(m->get_context_rel());
ctxt->vtable_offset(s);
}
/// Get the vtable offset of a member function.
///
/// @param f the member function to consider.
///
/// @param s the new vtable offset.
void
set_member_function_vtable_offset(const function_decl_sptr f, size_t s)
{return set_member_function_vtable_offset(*f, s);}
/// Test if a given member function is virtual.
///
/// @param mem_fn the member function to consider.
@ -5200,6 +5318,9 @@ function_decl::~function_decl()
// <class_decl definitions>
static void
sort_virtual_member_functions(class_decl::member_functions& mem_fns);
/// The private data for the class_decl type.
struct class_decl::priv
{
@ -5506,6 +5627,10 @@ const class_decl::member_functions&
class_decl::get_virtual_mem_fns() const
{return priv_->virtual_mem_fns_;}
void
class_decl::sort_virtual_mem_fns()
{sort_virtual_member_functions(priv_->virtual_mem_fns_);}
/// Get the member function templates of this class.
///
/// @return a vector of the member function templates of this class.
@ -5905,6 +6030,82 @@ class_decl::method_decl::set_scope(scope_decl* scope)
get_context_rel()->set_scope(scope);
}
/// A "less than" functor to sort a vector of instances of
/// class_decl::method_decl that are virtual.
struct virtual_member_function_less_than
{
/// The less than operator. First, it sorts the methods by their
/// vtable index. If they have the same vtable index, it sorts them
/// by the name of their ELF symbol. If they don't have elf
/// symbols, it sorts them by considering their pretty
/// representation.
///
/// Note that this method expects virtual methods.
///
/// @param f the first method to consider.
///
/// @param s the second method to consider.
bool
operator()(const class_decl::method_decl& f,
const class_decl::method_decl& s)
{
assert(get_member_function_is_virtual(f));
assert(get_member_function_is_virtual(s));
if (get_member_function_vtable_offset(f)
== get_member_function_vtable_offset(s))
{
string fn, sn;
if (f.get_symbol())
fn = f.get_symbol()->get_id_string();
else
fn = f.get_linkage_name();
if (s.get_symbol())
sn = s.get_symbol()->get_id_string();
else
sn = s.get_linkage_name();
if (fn.empty())
fn = f.get_pretty_representation();
if (sn.empty())
sn = s.get_pretty_representation();
return fn < sn;
}
return (get_member_function_vtable_offset(f)
< get_member_function_vtable_offset(s));
}
/// The less than operator. First, it sorts the methods by their
/// vtable index. If they have the same vtable index, it sorts them
/// by the name of their ELF symbol. If they don't have elf
/// symbols, it sorts them by considering their pretty
/// representation.
///
/// Note that this method expects to take virtual methods.
///
/// @param f the first method to consider.
///
/// @param s the second method to consider.
bool
operator()(const class_decl::method_decl_sptr f,
const class_decl::method_decl_sptr s)
{return operator()(*f, *s);}
}; // end struct virtual_member_function_less_than
/// Sort a vector of instances of virtual member functions.
///
/// @param mem_fns the vector of member functions to sort.
static void
sort_virtual_member_functions(class_decl::member_functions& mem_fns)
{
virtual_member_function_less_than lt;
std::sort(mem_fns.begin(), mem_fns.end(), lt);
}
/// Add a member function to the current instance of class_decl.
///
/// @param f a method_decl to add to the current class. This function
@ -5943,7 +6144,10 @@ class_decl::add_member_function(method_decl_sptr f,
priv_->member_functions_.push_back(f);
scope_decl::add_member_decl(f);
if (get_member_function_is_virtual(f))
priv_->virtual_mem_fns_.push_back(f);
{
priv_->virtual_mem_fns_.push_back(f);
sort_virtual_member_functions(priv_->virtual_mem_fns_);
}
}
/// Append a member function template to the class.

View File

@ -65,6 +65,24 @@
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='m1' type-id='type-id-9' visibility='default' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='19' column='1'/>
</data-member>
<member-function access='public' constructor='yes'>
<function-decl name='s0' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='21' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<parameter type-id='type-id-8' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public' destructor='yes'>
<function-decl name='~s0' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='27' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<parameter type-id='type-id-8' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public'>
<function-decl name='mem_fun' mangled-name='_ZN2s07mem_funEv' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='36' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN2s07mem_funEv'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<return type-id='type-id-7'/>
</function-decl>
</member-function>
<member-function access='public' constructor='yes'>
<function-decl name='s0' mangled-name='_ZN2s0C1Ev' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='21' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN2s0C1Ev'>
<parameter type-id='type-id-11' is-artificial='yes'/>
@ -77,12 +95,6 @@
<parameter type-id='type-id-8' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public'>
<function-decl name='mem_fun' mangled-name='_ZN2s07mem_funEv' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test1.cc' line='36' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN2s07mem_funEv'>
<parameter type-id='type-id-11' is-artificial='yes'/>
<return type-id='type-id-7'/>
</function-decl>
</member-function>
</class-decl>
<type-decl name='int' size-in-bits='32' alignment-in-bits='32' id='type-id-8'/>
<type-decl name='unsigned char' size-in-bits='8' alignment-in-bits='8' id='type-id-10'/>

View File

@ -17,6 +17,11 @@
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='member1' type-id='type-id-3' visibility='default' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='7' column='1'/>
</data-member>
<member-function access='public' constructor='yes'>
<function-decl name='first_type' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-4' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public' constructor='yes'>
<function-decl name='first_type' mangled-name='_ZN10first_typeC1Ev' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='9' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN10first_typeC1Ev'>
<parameter type-id='type-id-4' is-artificial='yes'/>
@ -42,6 +47,11 @@
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='member1' type-id='type-id-9' visibility='default' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='15' column='1'/>
</data-member>
<member-function access='public' constructor='yes'>
<function-decl name='second_type' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64'>
<parameter type-id='type-id-10' is-artificial='yes'/>
</function-decl>
</member-function>
<member-function access='public' constructor='yes'>
<function-decl name='second_type' mangled-name='_ZN11second_typeC1Ev' filepath='/home/dodji/git/libabigail/dwarf/tests/data/test-read-dwarf/test2.h' line='17' column='1' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='64' elf-symbol-id='_ZN11second_typeC1Ev'>
<parameter type-id='type-id-10' is-artificial='yes'/>