mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-19 16:30:04 +00:00
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:
parent
5616233cf8
commit
cbf1debeab
@ -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&);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
206
src/abg-ir.cc
206
src/abg-ir.cc
@ -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.
|
||||
|
@ -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'/>
|
||||
|
@ -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'/>
|
||||
|
Loading…
Reference in New Issue
Block a user