mirror of
git://sourceware.org/git/libabigail.git
synced 2025-02-23 01:06:56 +00:00
suppression: Factorize out is_data_member_offset_in_range
In preparation of subsequent changes, this patch factorizes a function is_data_member_offset_in_range() out of type_suppression::suppression(). This is useful to determine if a data member offset is within an "offset range" expressed by the type_suppression::insertion_range type. This function is useful to implement the offset_of_first_data_member_regexp and offset_of_last_data_member_regexp properties to come in subsequent patches. Please note that is_data_member_offset_in_range works on data members of unions and classes, not just on classes like what the original code of inside type_suppression::suppresses_diff was doing. This patch should not have any functional impact on the code. * include/abg-fwd.h (get_last_data_member) (get_next_data_member_offset): Declare functions. * src/abg-ir.cc (get_next_data_member): Add an overload for class_or_union and write the overload for class_or_union_sptr in term of the former. (get_last_data_member): Add overloads form class_or_union& and class_or_union*. Write the overload for class_or_union_sptr in terms of the one for class_or_union*. (get_next_data_member_offset): Add an overload for class_or_union* and write the overload for class_or_union_sptr in terms of the former. * include/abg-suppression.h (type_suppression::insertion_range::eval_boundary): Take a class_or_union* for the context, as opposed to a class_decl_sptr. This makes this static function work for unions as well. (is_data_member_offset_in_range): Declare new function. * src/abg-suppression.cc (type_suppression::suppression_diff): Factorize ... (is_data_member_offset_in_range): ... this function out. (type_suppression::insertion_range::eval_boundary): Adjust this to make it take a class_or_union* rather than a class_decl_sptr. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
153b37a164
commit
b1b69abd79
@ -655,6 +655,12 @@ is_data_member(const decl_base *);
|
||||
const var_decl_sptr
|
||||
get_next_data_member(const class_or_union_sptr&, const var_decl_sptr&);
|
||||
|
||||
var_decl_sptr
|
||||
get_last_data_member(const class_or_union&);
|
||||
|
||||
var_decl_sptr
|
||||
get_last_data_member(const class_or_union*);
|
||||
|
||||
var_decl_sptr
|
||||
get_last_data_member(const class_or_union_sptr&);
|
||||
|
||||
@ -740,6 +746,11 @@ get_data_member_offset(const decl_base_sptr);
|
||||
uint64_t
|
||||
get_absolute_data_member_offset(const var_decl&);
|
||||
|
||||
bool
|
||||
get_next_data_member_offset(const class_or_union*,
|
||||
const var_decl_sptr&,
|
||||
uint64_t&);
|
||||
|
||||
bool
|
||||
get_next_data_member_offset(const class_or_union_sptr&,
|
||||
const var_decl_sptr&,
|
||||
|
@ -346,9 +346,9 @@ public:
|
||||
create_fn_call_expr_boundary(const string&);
|
||||
|
||||
static bool
|
||||
eval_boundary(boundary_sptr boundary,
|
||||
class_decl_sptr context,
|
||||
uint64_t& value);
|
||||
eval_boundary(const boundary_sptr boundary,
|
||||
const class_or_union* context,
|
||||
uint64_t& value);
|
||||
|
||||
static bool
|
||||
boundary_value_is_end(uint64_t value);
|
||||
@ -899,6 +899,12 @@ is_type_suppressed(const fe_iface& fe,
|
||||
const location& type_location,
|
||||
bool& type_is_private,
|
||||
bool require_drop_property = false);
|
||||
|
||||
bool
|
||||
is_data_member_offset_in_range(const var_decl_sptr&,
|
||||
const type_suppression::insertion_range_sptr&,
|
||||
const class_or_union*);
|
||||
|
||||
} // end namespace suppr
|
||||
|
||||
|
||||
|
@ -5752,7 +5752,7 @@ get_first_non_anonymous_data_member(const var_decl_sptr anon_dm)
|
||||
/// @return the data member that is located right after @p
|
||||
/// data_member.
|
||||
const var_decl_sptr
|
||||
get_next_data_member(const class_or_union_sptr &klass,
|
||||
get_next_data_member(const class_or_union *klass,
|
||||
const var_decl_sptr &data_member)
|
||||
{
|
||||
if (!klass ||!data_member)
|
||||
@ -5773,12 +5773,40 @@ get_next_data_member(const class_or_union_sptr &klass,
|
||||
return var_decl_sptr();
|
||||
}
|
||||
|
||||
/// In the context of a given class or union, this function returns
|
||||
/// the data member that is located after a given data member.
|
||||
///
|
||||
/// @param klass the class or union to consider.
|
||||
///
|
||||
/// @param the data member to consider.
|
||||
///
|
||||
/// @return the data member that is located right after @p
|
||||
/// data_member.
|
||||
const var_decl_sptr
|
||||
get_next_data_member(const class_or_union_sptr& klass,
|
||||
const var_decl_sptr &data_member)
|
||||
{return get_next_data_member(klass.get(), data_member);}
|
||||
|
||||
/// Get the last data member of a class type.
|
||||
///
|
||||
/// @param klass the class type to consider.
|
||||
var_decl_sptr
|
||||
get_last_data_member(const class_or_union& klass)
|
||||
{return klass.get_non_static_data_members().back();}
|
||||
|
||||
/// Get the last data member of a class type.
|
||||
///
|
||||
/// @param klass the class type to consider.
|
||||
var_decl_sptr
|
||||
get_last_data_member(const class_or_union* klass)
|
||||
{return get_last_data_member(*klass);}
|
||||
|
||||
/// Get the last data member of a class type.
|
||||
///
|
||||
/// @param klass the class type to consider.
|
||||
var_decl_sptr
|
||||
get_last_data_member(const class_or_union_sptr &klass)
|
||||
{return klass->get_non_static_data_members().back();}
|
||||
{return get_last_data_member(klass.get());}
|
||||
|
||||
/// Test if a decl is an anonymous data member.
|
||||
///
|
||||
@ -6062,7 +6090,7 @@ get_data_member_offset(const decl_base_sptr d)
|
||||
/// @return true iff the data member coming right after @p dm was
|
||||
/// found.
|
||||
bool
|
||||
get_next_data_member_offset(const class_or_union_sptr& klass,
|
||||
get_next_data_member_offset(const class_or_union* klass,
|
||||
const var_decl_sptr& dm,
|
||||
uint64_t& offset)
|
||||
{
|
||||
@ -6073,6 +6101,29 @@ get_next_data_member_offset(const class_or_union_sptr& klass,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Get the offset of the non-static data member that comes after a
|
||||
/// given one.
|
||||
///
|
||||
/// If there is no data member after after the one given to this
|
||||
/// function (maybe because the given one is the last data member of
|
||||
/// the class type) then the function return false.
|
||||
///
|
||||
/// @param klass the class to consider.
|
||||
///
|
||||
/// @param dm the data member before the one we want to retrieve.
|
||||
///
|
||||
/// @param offset out parameter. This parameter is set by the
|
||||
/// function to the offset of the data member that comes right after
|
||||
/// the data member @p dm, iff the function returns true.
|
||||
///
|
||||
/// @return true iff the data member coming right after @p dm was
|
||||
/// found.
|
||||
bool
|
||||
get_next_data_member_offset(const class_or_union_sptr& klass,
|
||||
const var_decl_sptr& dm,
|
||||
uint64_t& offset)
|
||||
{return get_next_data_member_offset(klass.get(), dm, offset);}
|
||||
|
||||
/// Get the absolute offset of a data member.
|
||||
///
|
||||
/// If the data member is part of an anonymous data member then this
|
||||
|
@ -865,65 +865,19 @@ type_suppression::suppresses_diff(const diff* diff) const
|
||||
const class_decl_sptr& first_type_decl =
|
||||
klass_diff->first_class_decl();
|
||||
|
||||
for (string_decl_base_sptr_map::const_iterator m =
|
||||
klass_diff->inserted_data_members().begin();
|
||||
m != klass_diff->inserted_data_members().end();
|
||||
++m)
|
||||
// All inserted data members must be in an allowed
|
||||
// insertion range.
|
||||
for (const auto& m : klass_diff->inserted_data_members())
|
||||
{
|
||||
decl_base_sptr member = m->second;
|
||||
size_t dm_offset = get_data_member_offset(member);
|
||||
decl_base_sptr member = m.second;
|
||||
bool matched = false;
|
||||
|
||||
for (insertion_ranges::const_iterator i =
|
||||
get_data_member_insertion_ranges().begin();
|
||||
i != get_data_member_insertion_ranges().end();
|
||||
++i)
|
||||
{
|
||||
type_suppression::insertion_range_sptr range = *i;
|
||||
uint64_t range_begin_val = 0, range_end_val = 0;
|
||||
if (!type_suppression::insertion_range::eval_boundary
|
||||
(range->begin(), first_type_decl, range_begin_val))
|
||||
break;
|
||||
if (!type_suppression::insertion_range::eval_boundary
|
||||
(range->end(), first_type_decl, range_end_val))
|
||||
break;
|
||||
|
||||
uint64_t range_begin = range_begin_val;
|
||||
uint64_t range_end = range_end_val;
|
||||
|
||||
if (insertion_range::boundary_value_is_end(range_begin)
|
||||
&& insertion_range::boundary_value_is_end(range_end))
|
||||
{
|
||||
// This idiom represents the predicate
|
||||
// "has_data_member_inserted_at = end"
|
||||
if (dm_offset >
|
||||
get_data_member_offset(get_last_data_member
|
||||
(first_type_decl)))
|
||||
{
|
||||
// So the data member was added after
|
||||
// last data member of the klass. That
|
||||
// matches the suppr spec
|
||||
// "has_data_member_inserted_at = end".
|
||||
matched = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (range_begin > range_end)
|
||||
// Wrong suppr spec. Ignore it.
|
||||
continue;
|
||||
|
||||
if (dm_offset < range_begin || dm_offset > range_end)
|
||||
// The offset of the added data member doesn't
|
||||
// match the insertion range specified. So
|
||||
// the diff object won't be suppressed.
|
||||
continue;
|
||||
|
||||
// If we reached this point, then all the
|
||||
// insertion range constraints have been
|
||||
// satisfied. So
|
||||
for (const auto& range : get_data_member_insertion_ranges())
|
||||
if (is_data_member_offset_in_range(is_var_decl(member),
|
||||
range,
|
||||
first_type_decl.get()))
|
||||
matched = true;
|
||||
}
|
||||
|
||||
if (!matched)
|
||||
return false;
|
||||
}
|
||||
@ -1404,9 +1358,9 @@ type_suppression::insertion_range::create_fn_call_expr_boundary(const string& s)
|
||||
/// @return true iff the evaluation was successful and @p value
|
||||
/// contains the resulting value.
|
||||
bool
|
||||
type_suppression::insertion_range::eval_boundary(boundary_sptr boundary,
|
||||
class_decl_sptr context,
|
||||
uint64_t& value)
|
||||
type_suppression::insertion_range::eval_boundary(const boundary_sptr boundary,
|
||||
const class_or_union* context,
|
||||
uint64_t& value)
|
||||
{
|
||||
if (integer_boundary_sptr b = is_integer_boundary(boundary))
|
||||
{
|
||||
@ -4962,5 +4916,57 @@ is_type_suppressed(const fe_iface& fe,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Test if a data memer offset is in a given insertion range.
|
||||
///
|
||||
/// @param dm the data member to consider.
|
||||
///
|
||||
/// @param range the insertion range to consider.
|
||||
///
|
||||
/// @param the class (or union) type to consider as the context in
|
||||
/// which to evaluate the insertion range denoted by @p range.
|
||||
///
|
||||
/// @return true iff the offset of the data member @p dm is in the
|
||||
/// insertion range @p range in the context of the type denoted by @p
|
||||
/// context.
|
||||
bool
|
||||
is_data_member_offset_in_range(const var_decl_sptr& dm,
|
||||
const type_suppression::insertion_range_sptr& range,
|
||||
const class_or_union* context)
|
||||
{
|
||||
ABG_ASSERT(dm && range && context);
|
||||
|
||||
uint64_t range_begin = 0, range_end = 0;
|
||||
if (!type_suppression::insertion_range::eval_boundary (range->begin(),
|
||||
context,
|
||||
range_begin))
|
||||
return false;
|
||||
|
||||
if (!type_suppression::insertion_range::eval_boundary (range->end(),
|
||||
context,
|
||||
range_end))
|
||||
return false;
|
||||
|
||||
if (range_begin > range_end)
|
||||
// wrong range, ignore it.
|
||||
return false;
|
||||
|
||||
uint64_t dm_offset = get_data_member_offset(dm);
|
||||
if (type_suppression::insertion_range::boundary_value_is_end(range_begin)
|
||||
&& type_suppression::insertion_range::boundary_value_is_end(range_end))
|
||||
{
|
||||
// This idiom represents the predicate
|
||||
// "has_data_member_inserted_at = end"
|
||||
if (dm_offset > get_data_member_offset(get_last_data_member(context)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dm_offset < range_begin || dm_offset > range_end)
|
||||
// The offset of the data member is outside the range.
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}// end namespace suppr
|
||||
} // end namespace abigail
|
||||
|
Loading…
Reference in New Issue
Block a user