[PATCH 06/11] Support incomplete enums in core and diff code.
Giuliano Procida
gprocida@google.com
Wed Jul 8 10:39:56 GMT 2020
On Wed, 8 Jul 2020 at 10:22, Dodji Seketeli <dodji@seketeli.org> wrote:
>
> Hello Giuliano,
>
> Giuliano Procida <gprocida@google.com> a écrit:
>
> > Hi Dodji.
> >
> > Overall this looks like an excellent compromise. In terms of the
> > surgery on the type hierarchy, my main concerns would be that
> >
> > 1. things that are not class/union/enum but which fall under decl_base
> > continue to get the same treatment
>
> Agreed.
>
> > 2. old places where class/union had declaration-only manipulation and
> > new places where enums have the same both get the right down-casting
>
> Yes.
>
> > It looks like these are there. I have some further comments in-line,
> > nothing significant.
>
> Thanks.
>
> [...]
>
> >> +bool
> >> +has_decl_only_def_change(const decl_base_sptr& first,
> >> + const decl_base_sptr& second)
> >> +{
> >> + if (!first || !second)
> >> + return false;
> >> +
> >> + decl_base_sptr f =
> >> + look_through_decl_only(first);
> >> + decl_base_sptr s =
> >> + look_through_decl_only(second);
> >> +
> >> + if (f->get_qualified_name() != s->get_qualified_name())
> >> + return false;
> >> +
> >> + return (f->get_is_declaration_only() != s->get_is_declaration_only());
> >
> > This return statement doesn't need the outer ( ).
>
> Fixed.
>
> [...]
>
> >> /// Test if two @ref class_or_union_sptr are different just by the
> >> /// fact that one is decl-only and the other one is defined.
> >> ///
> >> @@ -956,6 +1026,31 @@ has_class_decl_only_def_change(const class_or_union_sptr& first,
> >> return (f->get_is_declaration_only() != s->get_is_declaration_only());
> >
> > Same here on the return statement.
>
> Fixed.
>
> [...]
>
> >> +bool
> >> +has_enum_decl_only_def_change(const enum_type_decl_sptr& first,
> >> + const enum_type_decl_sptr& second)
> >> +{
> >> + if (!first || !second)
> >> + return false;
> >> +
> >> + enum_type_decl_sptr f = look_through_decl_only_enum(first);
> >> + enum_type_decl_sptr s = look_through_decl_only_enum(second);
> >> +
> >> + if (f->get_qualified_name() != s->get_qualified_name())
> >> + return false;
> >> +
> >> + return (f->get_is_declaration_only() != s->get_is_declaration_only());
> >
> > And again.
>
> Fixed.
>
> [...]
>
> >> @@ -3423,7 +3427,9 @@ struct decl_base::priv
> >> is_artificial_(false),
> >> has_anonymous_parent_(false),
> >> context_(),
> >> - visibility_(VISIBILITY_DEFAULT)
> >> + visibility_(VISIBILITY_DEFAULT),
> >> + naked_definition_of_declaration_(),
> >> + is_declaration_only_()
> >
> > Would be clearer to say (false).
>
> Fixed.
>
> >> {}
> >>
> >> priv(interned_string name, const location& locus,
> >> @@ -3434,7 +3440,9 @@ struct decl_base::priv
> >> name_(name),
> >> qualified_name_(name),
> >> linkage_name_(linkage_name),
> >> - visibility_(vis)
> >> + visibility_(vis),
> >> + naked_definition_of_declaration_(),
> >> + is_declaration_only_()
> >
> > Same here.
>
> Fixed.
>
> >> {
> >> is_anonymous_ = name_.empty();
> >> has_anonymous_parent_ = false;
> >> @@ -3446,7 +3454,9 @@ struct decl_base::priv
> >> has_anonymous_parent_(false),
> >> location_(l),
> >> context_(),
> >> - visibility_(VISIBILITY_DEFAULT)
> >> + visibility_(VISIBILITY_DEFAULT),
> >> + naked_definition_of_declaration_(),
> >> + is_declaration_only_()
> >
> > And again.
>
> Fixed.
>
> [...]
>
> >> +/// Set a flag saying if the @ref enum_type_decl is a declaration-only
> >> +/// @ref enum_type_decl.
> >> +///
> >> +/// @param f true if the @ref enum_type_decl is a decalaration-only
> >
> > Typo: decalaration / declaration.
>
> Fixed.
>
> [...]
>
> >> +/// Test if a type is a enum. This function looks through typedefs.
> >
> > Typo: a enum / an enum.
>
> Fixed.
>
> [...]
>
> >> +/// Test if a type is a enum. This function looks through typedefs.
> >
> > Same typo.
>
> Fixed.
>
> >> +///
> >> +/// @parm t the type to consider.
> >> +///
> >> +/// @return the enum_decl if @p t is a enum_decl or null otherwise.
> >
> > Technically a typo: a enum_decl / an enum_decl.
> > I'm not sure how it will render if you @ref the types.
>
> Fixed.
>
> >> +enum_type_decl_sptr
> >> +is_compatible_with_enum_type(const decl_base_sptr& t)
> >> +{return is_compatible_with_enum_type(is_type(t));}
> >> +
> >> /// Test if a decl is an enum_type_decl
> >> ///
> >> /// @param d the decl to test for.
> >> @@ -8270,24 +8386,19 @@ is_method_type(type_or_decl_base* t)
> >> /// @param the_klass the class (or union) to consider.
> >
> > Parameter is the_class.
>
> Fixed.
>
> >> ///
> >> /// @return either the definition of the class, or the class itself.
> >> +class_or_union*
> >> +look_through_decl_only_class(class_or_union* the_class)
> >> +{return is_class_or_union_type(look_through_decl_only(the_class));}
> >> +
> >> +/// If a class (or union) is a decl-only class, get its definition.
> >> +/// Otherwise, just return the initial class.
> >> +///
> >> +/// @param the_klass the class (or union) to consider.
> >
> > Same here.
>
> Fixed.
>
> [...]
>
>
> >> +decl_base_sptr
> >> +look_through_decl_only(const decl_base& d)
> >> +{
> >> + decl_base_sptr decl;
> >> + if (d.get_is_declaration_only())
> >> + decl = d.get_definition_of_declaration();
> >> +
> >> + if (!decl)
> >> + return decl;
> >> +
> >> + while (decl
> >> + && decl->get_is_declaration_only()
> >> + && decl->get_definition_of_declaration())
> >> + decl = decl->get_definition_of_declaration();
> >> +
> >> + ABG_ASSERT(decl);
> >> + return decl;
> >
> > I had a suspicion that this code could be simplified a while ago.
> >
> > You should be able to simplify it to (something like):
> >
> > look_through_decl_only_class(class_or_union_sptr klass)
> > {
> > if (!klass)
> > return klass;
> > while (klass->get_is_declaration_only()
> > && klass->get_definition_of_declaration())
> > klass = klass->get_definition_of_declaration();
> > return klass;
> > }
> >
> > This is two things:
> > 1. The function is simpler if it takes a (shared) pointer argument.
> > You probably don't need the other overload.
>
> Actually, I prefer keeping the function that takes reference. It's
> reused in the overload that takes a pointer. Also, I have some
> test/play programs on the side that use types instantiated on the stack
> etc and that make use of these. So they are useful in general, I think.
>
> > 2. You don't need to retest decl on every loop or assert it at the
> > end, just check once at the top as the loop condition preserves the
> > invariant.
>
> Yes, you are correct. I have made this change in the updated patch.
> Thanks.
>
> [...]
>
> [...]
>
> >> +/// Look into a given corpus to find the enum type*s* that have a
> >> +/// given qualified name.
> >> +///
> >> +/// @param qualified_name the qualified name of the type to look for.
> >> +///
> >> +/// @param corp the corpus to look into.
> >> +///
> >> +/// @return the vector of enum types that which name is @p qualified_name.
> >
> > Suggest: "that which name is" -> "named" (or "which have the name")
> > (and again, below)
>
> Of course. Fixed.
>
> [...]
>
> Please find below an updated patch that is present in my updated
> dodji/incomp-enum branch.
>
> Thanks.
>
>
> From 377b577cbbdc313e78b58631f5fb9bcc2c913a25 Mon Sep 17 00:00:00 2001
> From: Giuliano Procida <gprocida@google.com>
> Date: Wed, 10 Jun 2020 12:59:35 +0100
> Subject: [PATCH 1/4] Support incomplete enums in core and diff code.
>
> This is an initial implementation of the support for incomplete, also
> known as forward-declared, enum types. I've not made any attempt to
> refactor or share logic with the struct/union code.
>
> * include/abg-comp-filter.h (has_decl_only_def_change) : Declare
> New function.
> * src/abg-comp-filter.cc (there_is_a_decl_only_enum): Define new
> static function and ...
> (type_size_changed): ... use it here.
> (has_decl_only_def_change): Define new function and ...
> (categorize_harm{less, ful}_diff_node): ... use it here.
> * include/abg-fwd.h (enums_type, decl_base_wptr): Declare new
> typedefs.
> (look_through_decl_only_class): Declare new overload for
> class_or_union*.
> (is_compatible_with_enum_type, is_compatible_with_enum_type)
> (look_through_decl_only, lookup_enum_types, lookup_enum_types):
> Declare new functions.
> * include/abg-ir.h (decl_base::{get_is_declaration_only,
> set_is_declaration_only, set_definition_of_declaration,
> get_definition_of_declaration,
> get_naked_definition_of_declaration}): Declare new member
> functions. They were moved here from the class_or_union class.
> (class_or_union::{get_earlier_declaration,
> set_earlier_declaration, get_definition_of_declaration,
> set_definition_of_declaration,
> get_naked_definition_of_declaration, get_is_declaration_only,
> set_is_declaration_only}): Remove these member functions.
> * src/abg-ir.cc (decl_base::priv::{declaration_,
> definition_of_declaration_, naked_definition_of_declaration_,
> is_declaration_only_}): Define data members. Moved here from
> class_or_union.
> (decl_base::priv::priv): Adjust to initialize the new data
> members.
> (decl_base::{get_earlier_declaration, set_earlier_declaration,
> get_definition_of_declaration,
> get_naked_definition_of_declaration, get_is_declaration_only,
> set_is_declaration_only, set_definition_of_declaration}): Define
> member functions.
> (operator|): In the overload for (change_kind, change_kind),
> adjust the return type of the call to
> decl_base::get_definition_of_declaration.
> (look_through_decl_only): Define new function.
> (look_through_decl_only_class): Adjust.
> (look_through_decl_only_enum): Likewise.
> (maybe_update_types_lookup_map<class_decl>): Adjust return type of
> call to decl_base::get_definition_of_declaration.
> (types_defined_same_linux_kernel_corpus_public): Use
> look_through_decl_only_class rather than open coding it.
> (class_or_union::priv::{declaration_, definition_of_declaration_,
> naked_definition_of_declaration_, is_declaration_only_}): Remove
> these data members. They are now carried by decl_base::priv.
> (class_or_union::{g,s}et_alignment_in_bits): Adjust.
> (class_or_union::{g,s}et_size_in_bits): Likewise.
> (class_or_union::operator==): Likewise.
> (equals): Adjust the overload for class_or_union.
> (is_compatible_with_enum_type)
> * src/abg-comparison.cc (try_to_diff<class_decl>): Adjust the
> return type of decl_base::get_definition_of_declaration.
> (leaf_diff_node_marker_visitor::visit_begin): Use
> filtering::has_decl_only_def_change rather than
> filtering::has_class_decl_only_def_change. Decl-only changes to
> enums (or any other type really) will thus not be recorded as leaf
> changes.
> * src/abg-dwarf-reader.cc (get_scope_for_die): Adjust return type
> of decl_base::get_definition_of_declaration.
> * src/abg-default-reporter.cc (default_reporter::report): Report
> enum decl-only <-> definition changes.
> * src/abg-hash.cc (class_or_union::hash::operator()): In the
> overload for class_or_union& adjust the return type for
> decl_base::get_definition_of_declaration.
>
> Signed-off-by: Giuliano Procida <gprocida@google.com>
> Signed-off-by: Dodji Seketeli <dodji@redhat.com>
> ---
> include/abg-comp-filter.h | 14 ++
> include/abg-fwd.h | 36 ++++
> include/abg-ir.h | 48 ++---
> src/abg-comp-filter.cc | 133 ++++++++++++-
> src/abg-comparison.cc | 10 +-
> src/abg-default-reporter.cc | 19 ++
> src/abg-dwarf-reader.cc | 3 +-
> src/abg-hash.cc | 3 +-
> src/abg-ir.cc | 472 +++++++++++++++++++++++++++-----------------
> 9 files changed, 519 insertions(+), 219 deletions(-)
>
> diff --git a/include/abg-comp-filter.h b/include/abg-comp-filter.h
> index 8113003..556bad4 100644
> --- a/include/abg-comp-filter.h
> +++ b/include/abg-comp-filter.h
> @@ -65,13 +65,27 @@ bool
> is_decl_only_class_with_size_change(const diff *diff);
>
> bool
> +has_decl_only_def_change(const decl_base_sptr& first,
> + const decl_base_sptr& second);
> +
> +bool
> +has_decl_only_def_change(const diff *d);
> +
> +bool
> has_class_decl_only_def_change(const class_or_union_sptr& first,
> const class_or_union_sptr& second);
>
> bool
> +has_enum_decl_only_def_change(const enum_type_decl_sptr& first,
> + const enum_type_decl_sptr& second);
> +
> +bool
> has_class_decl_only_def_change(const diff *diff);
>
> bool
> +has_enum_decl_only_def_change(const diff *diff);
> +
> +bool
> has_basic_type_name_change(const diff *);
>
> bool
> diff --git a/include/abg-fwd.h b/include/abg-fwd.h
> index f23f4a4..bfd9f88 100644
> --- a/include/abg-fwd.h
> +++ b/include/abg-fwd.h
> @@ -155,6 +155,12 @@ class enum_type_decl;
> /// Convenience typedef for shared pointer to a @ref enum_type_decl.
> typedef shared_ptr<enum_type_decl> enum_type_decl_sptr;
>
> +/// Convenience typedef for a vector of @ref enum_type_decl_sptr
> +typedef vector<enum_type_decl_sptr> enums_type;
> +
> +/// Convenience typedef for a weak pointer to a @ref decl_base.
> +typedef weak_ptr<decl_base> decl_base_wptr;
> +
> class class_or_union;
>
> typedef shared_ptr<class_or_union> class_or_union_sptr;
> @@ -424,6 +430,12 @@ typedef_decl*
> is_typedef(type_base*);
>
> enum_type_decl_sptr
> +is_compatible_with_enum_type(const type_base_sptr&);
> +
> +enum_type_decl_sptr
> +is_compatible_with_enum_type(const decl_base_sptr&);
> +
> +enum_type_decl_sptr
> is_enum_type(const type_or_decl_base_sptr&);
>
> const enum_type_decl*
> @@ -513,6 +525,24 @@ look_through_decl_only_class(const class_or_union&);
> class_or_union_sptr
> look_through_decl_only_class(class_or_union_sptr);
>
> +class_or_union*
> +look_through_decl_only_class(class_or_union*);
> +
> +enum_type_decl_sptr
> +look_through_decl_only_enum(const enum_type_decl&);
> +
> +enum_type_decl_sptr
> +look_through_decl_only_enum(enum_type_decl_sptr);
> +
> +decl_base_sptr
> +look_through_decl_only(const decl_base&);
> +
> +decl_base*
> +look_through_decl_only(decl_base*);
> +
> +decl_base_sptr
> +look_through_decl_only(const decl_base_sptr&);
> +
> var_decl*
> is_var_decl(const type_or_decl_base*);
>
> @@ -1085,6 +1115,12 @@ lookup_enum_type(const string&, const corpus&);
> enum_type_decl_sptr
> lookup_enum_type(const interned_string&, const corpus&);
>
> +const type_base_wptrs_type*
> +lookup_enum_types(const interned_string&, const corpus&);
> +
> +const type_base_wptrs_type*
> +lookup_enum_types(const string&, const corpus&);
> +
> enum_type_decl_sptr
> lookup_enum_type_per_location(const interned_string&, const corpus&);
>
> diff --git a/include/abg-ir.h b/include/abg-ir.h
> index c2b66c4..5b13dc9 100644
> --- a/include/abg-ir.h
> +++ b/include/abg-ir.h
> @@ -1553,6 +1553,27 @@ public:
> void
> set_visibility(visibility v);
>
> + const decl_base_sptr
> + get_earlier_declaration() const;
> +
> + void
> + set_earlier_declaration(const decl_base_sptr&);
> +
> + const decl_base_sptr
> + get_definition_of_declaration() const;
> +
> + void
> + set_definition_of_declaration(const decl_base_sptr&);
> +
> + const decl_base*
> + get_naked_definition_of_declaration() const;
> +
> + bool
> + get_is_declaration_only() const;
> +
> + void
> + set_is_declaration_only(bool f);
> +
> friend type_base_sptr
> canonicalize(type_base_sptr);
>
> @@ -3776,27 +3797,6 @@ public:
> void
> set_naming_typedef(const typedef_decl_sptr&);
>
> - bool
> - get_is_declaration_only() const;
> -
> - void
> - set_is_declaration_only(bool f);
> -
> - void
> - set_definition_of_declaration(class_or_union_sptr);
> -
> - const class_or_union_sptr
> - get_definition_of_declaration() const;
> -
> - const class_or_union*
> - get_naked_definition_of_declaration() const;
> -
> - decl_base_sptr
> - get_earlier_declaration() const;
> -
> - void
> - set_earlier_declaration(decl_base_sptr declaration);
> -
> void
> insert_member_type(type_base_sptr t,
> declarations::iterator before);
> @@ -4020,12 +4020,6 @@ public:
> class_decl(const environment* env, const string& name, bool is_struct,
> bool is_declaration_only = true);
>
> - const class_decl_sptr
> - get_definition_of_declaration() const;
> -
> - const class_decl*
> - get_naked_definition_of_declaration() const;
> -
> virtual string
> get_pretty_representation(bool internal = false,
> bool qualified_name = true) const;
> diff --git a/src/abg-comp-filter.cc b/src/abg-comp-filter.cc
> index 702d223..0b0fbe4 100644
> --- a/src/abg-comp-filter.cc
> +++ b/src/abg-comp-filter.cc
> @@ -118,6 +118,25 @@ there_is_a_decl_only_class(const class_decl_sptr& class1,
> return false;
> }
>
> +/// Test if there is a enum that is declaration-only among the two
> +/// enums in parameter.
> +///
> +/// @param enum1 the first enum to consider.
> +///
> +/// @param enum2 the second enum to consider.
> +///
> +/// @return true if either enums are declaration-only, false
> +/// otherwise.
> +static bool
> +there_is_a_decl_only_enum(const enum_type_decl_sptr& enum1,
> + const enum_type_decl_sptr& enum2)
> +{
> + if ((enum1 && enum1->get_is_declaration_only())
> + || (enum2 && enum2->get_is_declaration_only()))
> + return true;
> + return false;
> +}
> +
> /// Test if the diff involves a declaration-only class.
> ///
> /// @param diff the class diff to consider.
> @@ -146,7 +165,9 @@ type_size_changed(const type_base_sptr f, const type_base_sptr s)
> || f->get_size_in_bits() == 0
> || s->get_size_in_bits() == 0
> || there_is_a_decl_only_class(is_compatible_with_class_type(f),
> - is_compatible_with_class_type(s)))
> + is_compatible_with_class_type(s))
> + || there_is_a_decl_only_enum(is_compatible_with_enum_type(f),
> + is_compatible_with_enum_type(s)))
> return false;
>
> return f->get_size_in_bits() != s->get_size_in_bits();
> @@ -893,10 +914,8 @@ is_decl_only_class_with_size_change(const class_or_union_sptr& first,
> if (!first || !second)
> return false;
>
> - class_or_union_sptr f =
> - look_through_decl_only_class(first);
> - class_or_union_sptr s =
> - look_through_decl_only_class(second);
> + class_or_union_sptr f = look_through_decl_only_class(first);
> + class_or_union_sptr s = look_through_decl_only_class(second);
>
> return is_decl_only_class_with_size_change(*f, *s);
> }
> @@ -929,6 +948,57 @@ is_decl_only_class_with_size_change(const diff *diff)
> return is_decl_only_class_with_size_change(f, s);
> }
>
> +/// Test if two @ref decl_base_sptr are different just by the
> +/// fact that one is decl-only and the other one is defined.
> +///
> +/// @param first the first decl to consider.
> +///
> +/// @param second the second decl to consider.
> +///
> +/// @return true iff the two arguments are different just by the fact
> +/// that one is decl-only and the other one is defined.
> +bool
> +has_decl_only_def_change(const decl_base_sptr& first,
> + const decl_base_sptr& second)
> +{
> + if (!first || !second)
> + return false;
> +
> + decl_base_sptr f =
> + look_through_decl_only(first);
> + decl_base_sptr s =
> + look_through_decl_only(second);
> +
> + if (f->get_qualified_name() != s->get_qualified_name())
> + return false;
> +
> + return f->get_is_declaration_only() != s->get_is_declaration_only();
> +}
> +
> +/// Test if a diff carries a change in which the two decls are
> +/// different by the fact that one is a decl-only and the other one is
> +/// defined.
> +///
> +/// @param diff the diff node to consider.
> +///
> +/// @return true if the diff carries a change in which the two decls
> +/// are different by the fact that one is a decl-only and the other
> +/// one is defined.
> +bool
> +has_decl_only_def_change(const diff *d)
> +{
> + if (!d)
> + return false;
> +
> + decl_base_sptr f =
> + look_through_decl_only(is_decl(d->first_subject()));
> + decl_base_sptr s =
> + look_through_decl_only(is_decl(d->second_subject()));
> +
> + return has_decl_only_def_change(f, s);
> +}
> +
> +
> /// Test if two @ref class_or_union_sptr are different just by the
> /// fact that one is decl-only and the other one is defined.
> ///
> @@ -953,7 +1023,32 @@ has_class_decl_only_def_change(const class_or_union_sptr& first,
> if (f->get_qualified_name() != s->get_qualified_name())
> return false;
>
> - return (f->get_is_declaration_only() != s->get_is_declaration_only());
> + return f->get_is_declaration_only() != s->get_is_declaration_only();
> +}
> +
> +/// Test if two @ref enum_sptr are different just by the
> +/// fact that one is decl-only and the other one is defined.
> +///
> +/// @param first the first enum to consider.
> +///
> +/// @param second the second enum to consider.
> +///
> +/// @return true iff the two arguments are different just by the fact
> +/// that one is decl-only and the other one is defined.
> +bool
> +has_enum_decl_only_def_change(const enum_type_decl_sptr& first,
> + const enum_type_decl_sptr& second)
> +{
> + if (!first || !second)
> + return false;
> +
> + enum_type_decl_sptr f = look_through_decl_only_enum(first);
> + enum_type_decl_sptr s = look_through_decl_only_enum(second);
> +
> + if (f->get_qualified_name() != s->get_qualified_name())
> + return false;
> +
> + return f->get_is_declaration_only() != s->get_is_declaration_only();
> }
>
> /// Test if a class_or_union_diff carries a change in which the two
> @@ -980,6 +1075,28 @@ has_class_decl_only_def_change(const diff *diff)
> return has_class_decl_only_def_change(f, s);
> }
>
> +/// Test if a enum_diff carries a change in which the two enums are
> +/// different by the fact that one is a decl-only and the other one is
> +/// defined.
> +///
> +/// @param diff the diff node to consider.
> +///
> +/// @return true if the enum_diff carries a change in which the two
> +/// enums are different by the fact that one is a decl-only and the
> +/// other one is defined.
> +bool
> +has_enum_decl_only_def_change(const diff *diff)
> +{
> + const enum_diff *d = dynamic_cast<const enum_diff*>(diff);
> + if (!d)
> + return false;
> +
> + enum_type_decl_sptr f = look_through_decl_only_enum(d->first_enum());
> + enum_type_decl_sptr s = look_through_decl_only_enum(d->second_enum());
> +
> + return has_enum_decl_only_def_change(f, s);
> +}
> +
> /// Test if a diff node carries a basic type name change.
> ///
> /// @param d the diff node to consider.
> @@ -1517,7 +1634,8 @@ categorize_harmless_diff_node(diff *d, bool pre)
> decl_base_sptr f = is_decl(d->first_subject()),
> s = is_decl(d->second_subject());
>
> - if (has_class_decl_only_def_change(d))
> + if (has_class_decl_only_def_change(d)
> + || has_enum_decl_only_def_change(d))
> category |= TYPE_DECL_ONLY_DEF_CHANGE_CATEGORY;
>
> if (access_changed(f, s))
> @@ -1608,6 +1726,7 @@ categorize_harmful_diff_node(diff *d, bool pre)
> //
> // TODO: be more specific -- not all size changes are harmful.
> if (!has_class_decl_only_def_change(d)
> + && !has_enum_decl_only_def_change(d)
> && (type_size_changed(f, s)
> || data_member_offset_changed(f, s)
> || non_static_data_member_type_size_changed(f, s)
> diff --git a/src/abg-comparison.cc b/src/abg-comparison.cc
> index d0f1d21..b6f065f 100644
> --- a/src/abg-comparison.cc
> +++ b/src/abg-comparison.cc
> @@ -2827,13 +2827,15 @@ try_to_diff<class_decl>(const type_or_decl_base_sptr first,
>
> if (f->get_is_declaration_only())
> {
> - class_decl_sptr f2 = f->get_definition_of_declaration();
> + class_decl_sptr f2 =
> + is_class_type (f->get_definition_of_declaration());
> if (f2)
> f = f2;
> }
> if (s->get_is_declaration_only())
> {
> - class_decl_sptr s2 = s->get_definition_of_declaration();
> + class_decl_sptr s2 =
> + is_class_type(s->get_definition_of_declaration());
> if (s2)
> s = s2;
> }
> @@ -10953,8 +10955,8 @@ struct leaf_diff_node_marker_visitor : public diff_node_visitor
> // typedef change which underlying type is an anonymous
> // struct/union.
> && !is_anonymous_class_or_union_diff(d)
> - // Don't show decl-only-ness changes of classes either.
> - && !filtering::has_class_decl_only_def_change(d)
> + // Don't show decl-only-ness changes either.
> + && !filtering::has_decl_only_def_change(d)
> // Sometime, we can encounter artifacts of bogus DWARF that
> // yield a diff node for a decl-only class (and empty class
> // with the is_declaration flag set) that carries a non-zero
> diff --git a/src/abg-default-reporter.cc b/src/abg-default-reporter.cc
> index 2acb695..cbf8c2b 100644
> --- a/src/abg-default-reporter.cc
> +++ b/src/abg-default-reporter.cc
> @@ -99,6 +99,25 @@ default_reporter::report(const enum_diff& d, ostream& out,
> enum_type_decl_sptr first = d.first_enum(), second = d.second_enum();
>
> const diff_context_sptr& ctxt = d.context();
> +
> + // Report enum decl-only <-> definition changes.
> + if (ctxt->get_allowed_category() & TYPE_DECL_ONLY_DEF_CHANGE_CATEGORY)
> + if (filtering::has_enum_decl_only_def_change(first, second))
> + {
> + string was =
> + first->get_is_declaration_only()
> + ? " was a declaration-only enum type"
> + : " was a defined enum type";
> +
> + string is_now =
> + second->get_is_declaration_only()
> + ? " and is now a declaration-only enum type"
> + : " and is now a defined enum type";
> +
> + out << indent << "enum type " << name << was << is_now << "\n";
> + return;
> + }
> +
> report_name_size_and_alignment_changes(first, second, ctxt,
> out, indent);
> maybe_report_diff_for_member(first, second, ctxt, out, indent);
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
> index ba4e750..db43aa7 100644
> --- a/src/abg-dwarf-reader.cc
> +++ b/src/abg-dwarf-reader.cc
> @@ -12315,7 +12315,8 @@ get_scope_for_die(read_context& ctxt,
> class_decl_sptr cl = dynamic_pointer_cast<class_decl>(d);
> if (cl && cl->get_is_declaration_only())
> {
> - scope_decl_sptr scop (cl->get_definition_of_declaration());
> + scope_decl_sptr scop =
> + dynamic_pointer_cast<scope_decl>(cl->get_definition_of_declaration());
> if (scop)
> s = scop;
> else
> diff --git a/src/abg-hash.cc b/src/abg-hash.cc
> index c1cdc57..5d2861f 100644
> --- a/src/abg-hash.cc
> +++ b/src/abg-hash.cc
> @@ -635,7 +635,8 @@ class_or_union::hash::operator()(const class_or_union& t) const
> if (t.get_is_declaration_only())
> {
> ABG_ASSERT(t.get_definition_of_declaration());
> - size_t v = operator()(*t.get_definition_of_declaration());
> + size_t v = operator()
> + (*is_class_or_union_type(t.get_definition_of_declaration()));
> return v;
> }
>
> diff --git a/src/abg-ir.cc b/src/abg-ir.cc
> index a434ec6..15bf124 100644
> --- a/src/abg-ir.cc
> +++ b/src/abg-ir.cc
> @@ -3416,6 +3416,10 @@ struct decl_base::priv
> interned_string scoped_name_;
> interned_string linkage_name_;
> visibility visibility_;
> + decl_base_sptr declaration_;
> + decl_base_wptr definition_of_declaration_;
> + decl_base* naked_definition_of_declaration_;
> + bool is_declaration_only_;
>
> priv()
> : in_pub_sym_tab_(false),
> @@ -3423,7 +3427,9 @@ struct decl_base::priv
> is_artificial_(false),
> has_anonymous_parent_(false),
> context_(),
> - visibility_(VISIBILITY_DEFAULT)
> + visibility_(VISIBILITY_DEFAULT),
> + naked_definition_of_declaration_(),
> + is_declaration_only_(false)
> {}
>
> priv(interned_string name, const location& locus,
> @@ -3434,7 +3440,9 @@ struct decl_base::priv
> name_(name),
> qualified_name_(name),
> linkage_name_(linkage_name),
> - visibility_(vis)
> + visibility_(vis),
> + naked_definition_of_declaration_(),
> + is_declaration_only_(false)
> {
> is_anonymous_ = name_.empty();
> has_anonymous_parent_ = false;
> @@ -3446,7 +3454,9 @@ struct decl_base::priv
> has_anonymous_parent_(false),
> location_(l),
> context_(),
> - visibility_(VISIBILITY_DEFAULT)
> + visibility_(VISIBILITY_DEFAULT),
> + naked_definition_of_declaration_(),
> + is_declaration_only_(false)
> {}
>
> ~priv()
> @@ -3881,6 +3891,80 @@ const interned_string&
> decl_base::get_scoped_name() const
> {return priv_->scoped_name_;}
>
> +/// If this @ref decl_base is a definition, get its earlier
> +/// declaration.
> +///
> +/// @return the earlier declaration of the class, if any.
> +const decl_base_sptr
> +decl_base::get_earlier_declaration() const
> +{return priv_->declaration_;}
> +
> +/// set the earlier declaration of this @ref decl_base definition.
> +///
> +/// @param d the earlier declaration to set. Note that it's set only
> +/// if it's a pure declaration.
> +void
> +decl_base::set_earlier_declaration(const decl_base_sptr& d)
> +{
> + if (d && d->get_is_declaration_only())
> + priv_->declaration_ = d;
> +}
> +
> +
> +/// If this @ref decl_base is declaration-only, get its definition, if
> +/// any.
> +///
> +/// @return the definition of this decl-only @ref decl_base.
> +const decl_base_sptr
> +decl_base::get_definition_of_declaration() const
> +{return priv_->definition_of_declaration_.lock();}
> +
> +/// If this @ref decl_base is declaration-only, get its definition,
> +/// if any.
> +///
> +/// Note that this function doesn't return a smart pointer, but rather
> +/// the underlying pointer managed by the smart pointer. So it's as
> +/// fast as possible. This getter is to be used in code paths that
> +/// are proven to be performance hot spots; especially, when comparing
> +/// sensitive types like enums, classes or unions. Those are compared
> +/// extremely frequently and thus, their access to the definition of
> +/// declaration must be fast.
> +///
> +/// @return the definition of the declaration.
> +const decl_base*
> +decl_base::get_naked_definition_of_declaration() const
> +{return priv_->naked_definition_of_declaration_;}
> +
> +/// Test if a @ref decl_base is a declaration-only decl.
> +///
> +/// @return true iff the current @ref decl_base is declaration-only.
> +bool
> +decl_base::get_is_declaration_only() const
> +{return priv_->is_declaration_only_;}
> +
> +/// Set a flag saying if the @ref enum_type_decl is a declaration-only
> +/// @ref enum_type_decl.
> +///
> +/// @param f true if the @ref enum_type_decl is a declaration-only
> +/// @ref enum_type_decl.
> +void
> +decl_base::set_is_declaration_only(bool f)
> +{
> + bool update_types_lookup_map = !f && priv_->is_declaration_only_;
> +
> + priv_->is_declaration_only_ = f;
> +
> + if (update_types_lookup_map)
> + if (scope_decl* s = get_scope())
> + {
> + scope_decl::declarations::iterator i;
> + if (s->find_iterator_for_member(this, i))
> + maybe_update_types_lookup_map(*i);
> + else
> + ABG_ASSERT_NOT_REACHED;
> + }
> +}
> +
> change_kind
> operator|(change_kind l, change_kind r)
> {
> @@ -4236,7 +4320,7 @@ operator!=(const type_base_sptr& l, const type_base_sptr& r)
>
> /// Tests if a declaration has got a scope.
> ///
> -/// @param d the decalaration to consider.
> +/// @param d the declaration to consider.
> ///
> /// @return true if the declaration has got a scope, false otherwise.
> bool
> @@ -4245,7 +4329,7 @@ has_scope(const decl_base& d)
>
> /// Tests if a declaration has got a scope.
> ///
> -/// @param d the decalaration to consider.
> +/// @param d the declaration to consider.
> ///
> /// @return true if the declaration has got a scope, false otherwise.
> bool
> @@ -6686,7 +6770,7 @@ get_location(const decl_base_sptr& decl)
> if (class_or_union_sptr c = is_class_or_union_type(decl))
> if (c->get_is_declaration_only() && c->get_definition_of_declaration())
> {
> - c = c->get_definition_of_declaration();
> + c = is_class_or_union_type(c->get_definition_of_declaration());
> loc = c->get_location();
> }
> }
> @@ -7925,6 +8009,40 @@ typedef_decl*
> is_typedef(type_base* t)
> {return dynamic_cast<typedef_decl*>(t);}
>
> +/// Test if a type is an enum. This function looks through typedefs.
> +///
> +/// @parm t the type to consider.
> +///
> +/// @return the enum_decl if @p t is an @ref enum_decl or null
> +/// otherwise.
> +enum_type_decl_sptr
> +is_compatible_with_enum_type(const type_base_sptr& t)
> +{
> + if (!t)
> + return enum_type_decl_sptr();
> +
> + // Normally we should strip typedefs entirely, but this is
> + // potentially costly, especially on binaries with huge changesets
> + // like the Linux Kernel. So we just get the leaf types for now.
> + //
> + // Maybe there should be an option by which users accepts to pay the
> + // CPU usage toll in exchange for finer filtering?
> +
> + // type_base_sptr ty = strip_typedef(t);
> + type_base_sptr ty = peel_typedef_type(t);;
> + return is_enum_type(ty);
> +}
> +
> +/// Test if a type is an enum. This function looks through typedefs.
> +///
> +/// @parm t the type to consider.
> +///
> +/// @return the enum_decl if @p t is an @ref enum_decl or null
> +/// otherwise.
> +enum_type_decl_sptr
> +is_compatible_with_enum_type(const decl_base_sptr& t)
> +{return is_compatible_with_enum_type(is_type(t));}
> +
> /// Test if a decl is an enum_type_decl
> ///
> /// @param d the decl to test for.
> @@ -8267,27 +8385,22 @@ is_method_type(type_or_decl_base* t)
> /// If a class (or union) is a decl-only class, get its definition.
> /// Otherwise, just return the initial class.
> ///
> -/// @param the_klass the class (or union) to consider.
> +/// @param the_class the class (or union) to consider.
> +///
> +/// @return either the definition of the class, or the class itself.
> +class_or_union*
> +look_through_decl_only_class(class_or_union* the_class)
> +{return is_class_or_union_type(look_through_decl_only(the_class));}
> +
> +/// If a class (or union) is a decl-only class, get its definition.
> +/// Otherwise, just return the initial class.
> +///
> +/// @param the_class the class (or union) to consider.
> ///
> /// @return either the definition of the class, or the class itself.
> class_or_union_sptr
> look_through_decl_only_class(const class_or_union& the_class)
> -{
> - class_or_union_sptr klass;
> - if (the_class.get_is_declaration_only())
> - klass = the_class.get_definition_of_declaration();
> -
> - if (!klass)
> - return klass;
> -
> - while (klass
> - && klass->get_is_declaration_only()
> - && klass->get_definition_of_declaration())
> - klass = klass->get_definition_of_declaration();
> -
> - ABG_ASSERT(klass);
> - return klass;
> -}
> +{return is_class_or_union_type(look_through_decl_only(the_class));}
>
> /// If a class (or union) is a decl-only class, get its definition.
> /// Otherwise, just return the initial class.
> @@ -8297,13 +8410,84 @@ look_through_decl_only_class(const class_or_union& the_class)
> /// @return either the definition of the class, or the class itself.
> class_or_union_sptr
> look_through_decl_only_class(class_or_union_sptr klass)
> +{return is_class_or_union_type(look_through_decl_only(klass));}
> +
> +/// If an enum is a decl-only enum, get its definition.
> +/// Otherwise, just return the initial enum.
> +///
> +/// @param the_enum the enum to consider.
> +///
> +/// @return either the definition of the enum, or the enum itself.
> +enum_type_decl_sptr
> +look_through_decl_only_enum(const enum_type_decl& the_enum)
> +{return is_enum_type(look_through_decl_only(the_enum));}
> +
> +/// If an enum is a decl-only enum, get its definition.
> +/// Otherwise, just return the initial enum.
> +///
> +/// @param enom the enum to consider.
> +///
> +/// @return either the definition of the enum, or the enum itself.
> +enum_type_decl_sptr
> +look_through_decl_only_enum(enum_type_decl_sptr enom)
> +{return is_enum_type(look_through_decl_only(enom));}
> +
> +/// If a decl is decl-only get its definition. Otherwise, just return nil.
> +///
> +/// @param d the decl to consider.
> +///
> +/// @return either the definition of the decl, or nil.
> +decl_base_sptr
> +look_through_decl_only(const decl_base& d)
> +{
> + decl_base_sptr decl;
> + if (d.get_is_declaration_only())
> + decl = d.get_definition_of_declaration();
> +
> + if (!decl)
> + return decl;
> +
> + while (decl->get_is_declaration_only()
> + && decl->get_definition_of_declaration())
> + decl = decl->get_definition_of_declaration();
> +
> + ABG_ASSERT(decl);
The assert is still here (and redundant - to be honest, the compiler
may be able to work this out for itself).
I didn't spot anything else, so all good.
Regards,
Giuliano.
> + return decl;
> +}
> +
> +/// If a decl is decl-only enum, get its definition. Otherwise, just
> +/// return the initial decl.
> +///
> +/// @param d the decl to consider.
> +///
> +/// @return either the definition of the enum, or the decl itself.
> +decl_base*
> +look_through_decl_only(decl_base* d)
> +{
> + if (!d)
> + return d;
> +
> + decl_base* result = look_through_decl_only(*d).get();
> + if (!result)
> + result = d;
> +
> + return result;
> +}
> +
> +/// If a decl is decl-only get its definition. Otherwise, just return nil.
> +///
> +/// @param d the decl to consider.
> +///
> +/// @return either the definition of the decl, or nil.
> +decl_base_sptr
> +look_through_decl_only(const decl_base_sptr& d)
> {
> - if (!klass)
> - return klass;
> + if (!d)
> + return d;
>
> - class_or_union_sptr result = look_through_decl_only_class(*klass);
> + decl_base_sptr result = look_through_decl_only(*d);
> if (!result)
> - result = klass;
> + result = d;
>
> return result;
> }
> @@ -8784,7 +8968,7 @@ lookup_union_type_per_location(const string& loc, const corpus& corp)
> return lookup_union_type_per_location(env->intern(loc), corp);
> }
>
> -/// Lookup a enum type from a translation unit.
> +/// Lookup an enum type from a translation unit.
> ///
> /// This is done by looking the type up in the type map that is
> /// maintained in the translation unit. So this is as fast as
> @@ -8802,7 +8986,7 @@ lookup_enum_type(const interned_string& type_name, const translation_unit& tu)
> tu.get_types().enum_types());
> }
>
> -/// Lookup a enum type from a translation unit.
> +/// Lookup an enum type from a translation unit.
> ///
> /// This is done by looking the type up in the type map that is
> /// maintained in the translation unit. So this is as fast as
> @@ -10004,7 +10188,7 @@ lookup_class_type(const interned_string& qualified_name, const corpus& corp)
> ///
> /// @param corp the corpus to look into.
> ///
> -/// @return the vector of class types that which name is @p qualified_name.
> +/// @return the vector of class types named @p qualified_name.
> const type_base_wptrs_type *
> lookup_class_types(const interned_string& qualified_name, const corpus& corp)
> {
> @@ -10103,7 +10287,7 @@ lookup_union_type(const string& type_name, const corpus& corp)
> return lookup_union_type(s, corp);
> }
>
> -/// Look into a given corpus to find a enum type which has the same
> +/// Look into a given corpus to find an enum type which has the same
> /// qualified name as a given enum type.
> ///
> /// If the per-corpus type map is non-empty (because the corpus allows
> @@ -10166,6 +10350,37 @@ lookup_enum_type(const interned_string& qualified_name, const corpus& corp)
> return result;
> }
>
> +/// Look into a given corpus to find the enum type*s* that have a
> +/// given qualified name.
> +///
> +/// @param qualified_name the qualified name of the type to look for.
> +///
> +/// @param corp the corpus to look into.
> +///
> +/// @return the vector of enum types that which name is @p qualified_name.
> +const type_base_wptrs_type *
> +lookup_enum_types(const interned_string& qualified_name, const corpus& corp)
> +{
> + const istring_type_base_wptrs_map_type& m = corp.get_types().enum_types();
> +
> + return lookup_types_in_map(qualified_name, m);
> +}
> +
> +/// Look into a given corpus to find the enum type*s* that have a
> +/// given qualified name.
> +///
> +/// @param qualified_name the qualified name of the type to look for.
> +///
> +/// @param corp the corpus to look into.
> +///
> +/// @return the vector of enum types that which name is @p qualified_name.
> +const type_base_wptrs_type*
> +lookup_enum_types(const string& qualified_name, const corpus& corp)
> +{
> + interned_string s = corp.get_environment()->intern(qualified_name);
> + return lookup_enum_types(s, corp);
> +}
> +
> /// Look up an @ref enum_type_decl from a given corpus, by its location.
> ///
> /// @param loc the location to consider.
> @@ -10767,7 +10982,8 @@ maybe_update_types_lookup_map<class_decl>(const class_decl_sptr& class_type,
> bool update_qname_map = true;
> if (type->get_is_declaration_only())
> {
> - if (class_decl_sptr def = class_type->get_definition_of_declaration())
> + if (class_decl_sptr def =
> + is_class_type(class_type->get_definition_of_declaration()))
> type = def;
> else
> update_qname_map = false;
> @@ -11683,10 +11899,8 @@ types_defined_same_linux_kernel_corpus_public(const type_base& t1,
>
> // Look through declaration-only types. That is, get the associated
> // definition type.
> - if (c1 && c1->get_is_declaration_only())
> - c1 = c1->get_definition_of_declaration().get();
> - if (c2 && c2->get_is_declaration_only())
> - c2 = c2->get_definition_of_declaration().get();
> + c1 = look_through_decl_only_class(c1);
> + c2 = look_through_decl_only_class(c2);
>
> if (c1 && c2)
> {
> @@ -12079,6 +12293,23 @@ canonicalize(type_base_sptr t)
> return canonical;
> }
>
> +
> +/// Set the definition of this declaration-only @ref decl_base.
> +///
> +/// @param d the new definition to set.
> +void
> +decl_base::set_definition_of_declaration(const decl_base_sptr& d)
> +{
> + ABG_ASSERT(get_is_declaration_only());
> + priv_->definition_of_declaration_ = d;
> + priv_->definition_of_declaration_ = d;
> + if (type_base *t = is_type(this))
> + if (type_base_sptr canonical_type = is_type(d)->get_canonical_type())
> + t->priv_->canonical_type = canonical_type;
> +
> + priv_->naked_definition_of_declaration_ = const_cast<decl_base*>(d.get());
> +}
> +
> /// The constructor of @ref type_base.
> ///
> /// @param s the size of the type, in bits.
> @@ -14978,7 +15209,6 @@ class enum_type_decl::priv
> priv();
>
> public:
> -
> priv(type_base_sptr underlying_type,
> enumerators& enumerators)
> : underlying_type_(underlying_type),
> @@ -17987,9 +18217,6 @@ function_decl::parameter::get_pretty_representation(bool internal,
> struct class_or_union::priv
> {
> typedef_decl_wptr naming_typedef_;
> - decl_base_sptr declaration_;
> - class_or_union_wptr definition_of_declaration_;
> - class_or_union* naked_definition_of_declaration_;
> member_types member_types_;
> data_members data_members_;
> data_members non_static_data_members_;
> @@ -18001,21 +18228,16 @@ struct class_or_union::priv
> string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
> member_function_templates member_function_templates_;
> member_class_templates member_class_templates_;
> - bool is_declaration_only_;
>
> priv()
> - : naked_definition_of_declaration_(),
> - is_declaration_only_(false)
> {}
>
> priv(class_or_union::member_types& mbr_types,
> class_or_union::data_members& data_mbrs,
> class_or_union::member_functions& mbr_fns)
> - : naked_definition_of_declaration_(),
> - member_types_(mbr_types),
> + : member_types_(mbr_types),
> data_members_(data_mbrs),
> - member_functions_(mbr_fns),
> - is_declaration_only_(false)
> + member_functions_(mbr_fns)
> {
> for (data_members::const_iterator i = data_members_.begin();
> i != data_members_.end();
> @@ -18024,11 +18246,6 @@ struct class_or_union::priv
> non_static_data_members_.push_back(*i);
> }
>
> - priv(bool is_declaration_only)
> - : naked_definition_of_declaration_(),
> - is_declaration_only_(is_declaration_only)
> - {}
> -
> /// Mark a class or union or union as being currently compared using
> /// the class_or_union== operator.
> ///
> @@ -18244,8 +18461,10 @@ class_or_union::class_or_union(const environment* env, const string& name,
> decl_base(env, name, location(), name),
> type_base(env, 0, 0),
> scope_type_decl(env, name, 0, 0, location()),
> - priv_(new priv(is_declaration_only))
> -{}
> + priv_(new priv)
> +{
> + set_is_declaration_only(is_declaration_only);
> +}
>
> /// This implements the ir_traversable_base::traverse pure virtual
> /// function.
> @@ -18465,7 +18684,8 @@ size_t
> class_or_union::get_alignment_in_bits() const
> {
> if (get_is_declaration_only() && get_definition_of_declaration())
> - return get_definition_of_declaration()->get_alignment_in_bits();
> + return is_class_or_union_type
> + (get_definition_of_declaration())->get_alignment_in_bits();
>
> return type_base::get_alignment_in_bits();
> }
> @@ -18480,7 +18700,8 @@ void
> class_or_union::set_alignment_in_bits(size_t a)
> {
> if (get_is_declaration_only() && get_definition_of_declaration())
> - get_definition_of_declaration()->set_alignment_in_bits(a);
> + is_class_or_union_type
> + (get_definition_of_declaration()) ->set_alignment_in_bits(a);
> else
> type_base::set_alignment_in_bits(a);
> }
> @@ -18495,7 +18716,8 @@ void
> class_or_union::set_size_in_bits(size_t s)
> {
> if (get_is_declaration_only() && get_definition_of_declaration())
> - get_definition_of_declaration()->set_size_in_bits(s);
> + is_class_or_union_type
> + (get_definition_of_declaration())->set_size_in_bits(s);
> else
> type_base::set_size_in_bits(s);
> }
> @@ -18510,42 +18732,12 @@ size_t
> class_or_union::get_size_in_bits() const
> {
> if (get_is_declaration_only() && get_definition_of_declaration())
> - return get_definition_of_declaration()->get_size_in_bits();
> + return is_class_or_union_type
> + (get_definition_of_declaration())->get_size_in_bits();
>
> return type_base::get_size_in_bits();
> }
>
> -/// Test if a @ref class_or_union is a declaration-only @ref
> -/// class_or_union.
> -///
> -/// @return true iff the current @ref class_or_union is a
> -/// declaration-only @ref class_or_union.
> -bool
> -class_or_union::get_is_declaration_only() const
> -{return priv_->is_declaration_only_;}
> -
> -/// Set a flag saying if the @ref class_or_union is a declaration-only
> -/// @ref class_or_union.
> -///
> -/// @param f true if the @ref class_or_union is a decalaration-only
> -/// @ref class_or_union.
> -void
> -class_or_union::set_is_declaration_only(bool f)
> -{
> - bool update_types_lookup_map = !f && priv_->is_declaration_only_;
> -
> - priv_->is_declaration_only_ = f;
> -
> - if (update_types_lookup_map)
> - if (scope_decl* s = get_scope())
> - {
> - declarations::iterator i;
> - if (s->find_iterator_for_member(this, i))
> - maybe_update_types_lookup_map(*i);
> - else
> - ABG_ASSERT_NOT_REACHED;
> - }
> -}
>
> /// Getter for the naming typedef of the current class.
> ///
> @@ -18577,64 +18769,6 @@ class_or_union::set_naming_typedef(const typedef_decl_sptr& typedef_type)
> priv_->naming_typedef_ = typedef_type;
> }
>
> -/// Set the definition of this declaration-only @ref class_or_union.
> -///
> -/// @param d the new definition to set.
> -void
> -class_or_union::set_definition_of_declaration(class_or_union_sptr d)
> -{
> - ABG_ASSERT(get_is_declaration_only());
> - priv_->definition_of_declaration_ = d;
> - if (d->get_canonical_type())
> - type_base::priv_->canonical_type = d->get_canonical_type();
> -
> - priv_->naked_definition_of_declaration_ = d.get();
> -}
> -
> -/// If this @ref class_or_union_sptr is declaration-only, get its
> -/// definition, if any.
> -///
> -/// @return the definition of this decl-only class.
> -const class_or_union_sptr
> -class_or_union::get_definition_of_declaration() const
> -{return priv_->definition_of_declaration_.lock();}
> -
> -/// If this @ref class_or_union is declaration-only, get its
> -/// definition, if any.
> -///
> -/// Note that this function doesn't return a smart pointer, but rather
> -/// the underlying pointer managed by the smart pointer. So it's as
> -/// fast as possible. This getter is to be used in code paths that
> -/// are proven to be performance hot spots; especially, when comparing
> -/// sensitive types like class or unions. Those are compared
> -/// extremely frequently and thus, their access to the definition of
> -/// declaration must be fast.
> -///
> -/// @return the definition of the class.
> -const class_or_union*
> -class_or_union::get_naked_definition_of_declaration() const
> -{return priv_->naked_definition_of_declaration_;}
> -
> -/// If this @ref class_or_union_sptr is a definitin, get its earlier
> -/// declaration.
> -///
> -/// @return the earlier declaration of the class, if any.
> -decl_base_sptr
> -class_or_union::get_earlier_declaration() const
> -{return priv_->declaration_;}
> -
> -/// set the earlier declaration of this @ref class_or_union definition.
> -///
> -/// @param declaration the earlier declaration to set. Note that it's
> -/// set only if it's a pure declaration.
> -void
> -class_or_union::set_earlier_declaration(decl_base_sptr declaration)
> -{
> - class_or_union_sptr cl = dynamic_pointer_cast<class_or_union>(declaration);
> - if (cl && cl->get_is_declaration_only())
> - priv_->declaration_ = declaration;
> -}
> -
> /// Get the member types of this @ref class_or_union.
> ///
> /// @return a vector of the member types of this ref class_or_union.
> @@ -19082,15 +19216,16 @@ class_or_union::operator==(const decl_base& other) const
> if (!canonical_type
> && get_is_declaration_only()
> && get_naked_definition_of_declaration())
> - canonical_type =
> - get_naked_definition_of_declaration()->get_naked_canonical_type();
> + canonical_type = is_class_or_union_type
> + (get_naked_definition_of_declaration())->get_naked_canonical_type();
>
> // Likewise for the other class.
> if (!other_canonical_type
> && op->get_is_declaration_only()
> && op->get_naked_definition_of_declaration())
> other_canonical_type =
> - op->get_naked_definition_of_declaration()->get_naked_canonical_type();
> + is_class_or_union_type
> + (op->get_naked_definition_of_declaration())->get_naked_canonical_type();
>
> if (canonical_type && other_canonical_type)
> return canonical_type == other_canonical_type;
> @@ -19161,11 +19296,11 @@ equals(const class_or_union& l, const class_or_union& r, change_kind* k)
> if (l_is_decl_only || r_is_decl_only)
> {
> const class_or_union* def1 = l_is_decl_only
> - ? l.get_naked_definition_of_declaration()
> + ? is_class_or_union_type(l.get_naked_definition_of_declaration())
> : &l;
>
> const class_or_union* def2 = r_is_decl_only
> - ? r.get_naked_definition_of_declaration()
> + ? is_class_or_union_type(r.get_naked_definition_of_declaration())
> : &r;
>
> if (!def1 || !def2)
> @@ -19784,30 +19919,6 @@ class_decl::on_canonical_type_set()
> sort_virtual_member_functions(i->second);
> }
>
> -/// If this @ref class_decl is declaration-only, get its definition,
> -/// if any.
> -///
> -/// @return the definition of the class.
> -const class_decl_sptr
> -class_decl::get_definition_of_declaration() const
> -{return is_class_type(class_or_union::get_definition_of_declaration());}
> -
> -/// If this @ref class_decl is declaration-only, get its definition,
> -/// if any.
> -///
> -/// Note that this function doesn't return a smart pointer, but rather
> -/// the underlying pointer managed by the smart pointer. So it's as
> -/// fast as possible. This getter is to be used in code paths that
> -/// are proven to be performance hot spots; especially, when comparing
> -/// sensitive types like class or unions. Those are compared
> -/// extremely frequently and thus, their access to the definition of
> -/// declaration must be fast.
> -///
> -/// @return the definition of the class.
> -const class_decl*
> -class_decl::get_naked_definition_of_declaration() const
> -{return is_class_type(class_or_union::get_naked_definition_of_declaration());}
> -
> /// Set the "is-struct" flag of the class.
> ///
> /// @param f the new value of the flag.
> @@ -20938,14 +21049,16 @@ class_decl::operator==(const decl_base& other) const
> && get_is_declaration_only()
> && get_naked_definition_of_declaration())
> canonical_type =
> - get_naked_definition_of_declaration()->get_naked_canonical_type();
> + is_class_type
> + (get_naked_definition_of_declaration())->get_naked_canonical_type();
>
> // Likewise for the other class.
> if (!other_canonical_type
> && op->get_is_declaration_only()
> && op->get_naked_definition_of_declaration())
> other_canonical_type =
> - op->get_naked_definition_of_declaration()->get_naked_canonical_type();
> + is_class_type
> + (op->get_naked_definition_of_declaration())->get_naked_canonical_type();
>
> if (canonical_type && other_canonical_type)
> return canonical_type == other_canonical_type;
> @@ -23035,7 +23148,8 @@ hash_type(const type_base *t)
> // The is a declaration-only class, so it has no canonical
> // type; but then it's class definition has one. Let's
> // use that one.
> - return hash_type(cl->get_naked_definition_of_declaration());
> + return hash_type
> + (is_class_type(cl->get_naked_definition_of_declaration()));
> else
> {
> // The class really has no canonical type, let's use the
> --
> 1.8.3.1
>
>
> --
> Dodji
More information about the Libabigail
mailing list