From 6e36a4381dedd73938271c2294bcce37b7294545 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Sun, 4 Oct 2015 12:08:08 +0200 Subject: [PATCH] Late canonicalize all types that reference classes when reading DWARF Until now, the DWARF reader would late canonicalize typedefs to classes, as well as classes. That is not enough. Let's also late-canonicalize pointers, references and array of classes too. This is because classes that might not be finished yet might be referenced by those types, and so we want to wait until they are finished before we canonicalize them. * include/abg-fwd.h (peel_array_type): Declare new function. * src/abg-ir.cc (peel_array_type): Define it. (peel_typedef_pointer_or_reference_type): Peel arrays too, to get the type of its element. * src/abg-dwarf-reader.cc (maybe_canonicalize_type): If a pointer, reference, array or typedef references a class, then do late-canonicalize this type. Signed-off-by: Dodji Seketeli --- include/abg-fwd.h | 6 ++++++ src/abg-dwarf-reader.cc | 9 +++++++- src/abg-ir.cc | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/include/abg-fwd.h b/include/abg-fwd.h index 50db61ad..9ff0016f 100644 --- a/include/abg-fwd.h +++ b/include/abg-fwd.h @@ -496,6 +496,12 @@ peel_reference_type(const shared_ptr&); const type_base* peel_reference_type(const type_base*); +const shared_ptr +peel_array_type(const shared_ptr&); + +const type_base* +peel_array_type(const type_base*); + shared_ptr peel_typedef_pointer_or_reference_type(const shared_ptr); diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index 9e92e35c..b675ecd7 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -7618,7 +7618,14 @@ maybe_canonicalize_type(Dwarf_Off die_offset, type_base_sptr t = ctxt.lookup_type_from_die_offset(die_offset, in_alt_di); assert(t); - if (class_decl_sptr klass = is_class_type(peel_typedef_type(t))) + if (class_decl_sptr klass = + is_class_type(peel_typedef_pointer_or_reference_type(t))) + // We delay canonicalization of classes or typedef, pointers, + // references and array to classes. This is because the + // (underlying) class might not be finished yet and we might not + // be able to able detect it here (thinking about classes that are + // work-in-progress, or classes that might be later amended by + // some DWARF construct). So we err on the safe side. ctxt.schedule_type_for_late_canonicalization(die_offset, in_alt_di); else if(type_has_non_canonicalized_subtype(t)) ctxt.schedule_type_for_late_canonicalization(die_offset, in_alt_di); diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 9b30959f..eeee1bf6 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -3277,6 +3277,46 @@ peel_reference_type(const type_base* type) return peel_reference_type(t->get_pointed_to_type()).get(); } +/// Return the leaf element type of an array. +/// +/// If the element type is itself an array, then recursively return +/// the element type of that array itself. +/// +/// @param type the array type to consider. If this is not an array +/// type, this type is returned by the function. +/// +/// @return the leaf element type of the array @p type, or, if it's +/// not an array type, then just return @p. +const type_base_sptr +peel_array_type(const type_base_sptr& type) +{ + const array_type_def_sptr t = is_array_type(type); + if (!t) + return type; + + return peel_array_type(t->get_element_type()); +} + +/// Return the leaf element type of an array. +/// +/// If the element type is itself an array, then recursively return +/// the element type of that array itself. +/// +/// @param type the array type to consider. If this is not an array +/// type, this type is returned by the function. +/// +/// @return the leaf element type of the array @p type, or, if it's +/// not an array type, then just return @p. +const type_base* +peel_array_type(const type_base* type) +{ + const array_type_def* t = is_array_type(type); + if (!t) + return type; + + return peel_array_type(t->get_element_type()).get(); +} + /// Return the leaf underlying or pointed-to type node of a @ref /// typedef_decl, @ref pointer_type_def or @ref reference_type_def /// node. @@ -3296,6 +3336,9 @@ peel_typedef_pointer_or_reference_type(const type_base_sptr type) if (reference_type_def_sptr t = is_reference_type(typ)) typ = peel_reference_type(t); + + if (array_type_def_sptr t = is_array_type(typ)) + typ = peel_array_type(t); } return typ; @@ -3319,6 +3362,9 @@ peel_typedef_pointer_or_reference_type(const type_base* type) if (const reference_type_def* t = is_reference_type(type)) type = peel_reference_type(t); + + if (const array_type_def* t = is_array_type(type)) + type = peel_array_type(t); } return const_cast(type);