mirror of
git://sourceware.org/git/libabigail.git
synced 2025-03-05 06:07:49 +00:00
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:#️⃣: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>
This commit is contained in:
parent
401e3cded9
commit
dbef379a96
@ -64,13 +64,27 @@ is_decl_only_class_with_size_change(const class_or_union_sptr& first,
|
||||
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 *);
|
||||
|
||||
|
@ -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;
|
||||
@ -423,6 +429,12 @@ is_typedef(const type_base*);
|
||||
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&);
|
||||
|
||||
@ -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&);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
473
src/abg-ir.cc
473
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,83 @@ 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)
|
||||
{
|
||||
if (!klass)
|
||||
return klass;
|
||||
{return is_class_or_union_type(look_through_decl_only(klass));}
|
||||
|
||||
class_or_union_sptr result = look_through_decl_only_class(*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();
|
||||
|
||||
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 = klass;
|
||||
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 (!d)
|
||||
return d;
|
||||
|
||||
decl_base_sptr result = look_through_decl_only(*d);
|
||||
if (!result)
|
||||
result = d;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -8784,7 +8967,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 +8985,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 +10187,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 +10286,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 +10349,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 +10981,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 +11898,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 +12292,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 +15208,6 @@ class enum_type_decl::priv
|
||||
priv();
|
||||
|
||||
public:
|
||||
|
||||
priv(type_base_sptr underlying_type,
|
||||
enumerators& enumerators)
|
||||
: underlying_type_(underlying_type),
|
||||
@ -17987,9 +18216,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 +18227,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 +18245,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 +18460,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 +18683,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 +18699,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 +18715,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 +18731,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 +18768,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 +19215,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 +19295,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 +19918,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 +21048,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 +23147,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
|
||||
|
Loading…
Reference in New Issue
Block a user