From patchwork Wed Jun 10 11:59:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 39555 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3AF0C388F055; Wed, 10 Jun 2020 12:00:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3AF0C388F055 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1591790413; bh=hahTzwAafzfbQD/mR9BtU6O2NLDp2d4QwGk46dDlPXA=; h=Date:In-Reply-To:References:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=ivvrC/jqF8GR4P/JuqmTnSAjrJVypKvVF9moUi1ze+eSgsYKRovomZWQ1hl3insF4 hOvB5s47cPP/iKOoV+edg6XH8NqnJASKC4yGq1uFTogMoc39qMdhQd7S+R/HEeA2ss VSaNVOmdeZNbPRBUMHAni5YDf6uHSLV+dddgfzRs= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by sourceware.org (Postfix) with ESMTPS id D93EC3851C11 for ; Wed, 10 Jun 2020 12:00:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D93EC3851C11 Received: by mail-yb1-xb49.google.com with SMTP id e20so1897122ybc.23 for ; Wed, 10 Jun 2020 05:00:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=hahTzwAafzfbQD/mR9BtU6O2NLDp2d4QwGk46dDlPXA=; b=pQNZ5YADCPvw88TdGRa3SXIyOW1uOhRQW9DKD05/5hkTfm4hbQUIJCxqF6hKDWLOmO PQd3hLtExXUyDkdWvJMAybcc6iMCIxq1qd8KBMlOwYILslmoH7sna1IersrQU5/4SFVJ Ry6pYz4I44w9QSBgo5I+ewRDwBX2BMoMyTK7L81zze1SZrAjzsK8uxx2+GV9U07BJ0db cmTW7dpL7/MgDVeFQvVPIWEvOMOgha4HSMnKtBp/mXtVi1r6f84uU1KSXAeN2ujkDoXk XhrV3BpvglYAiZ5R+N2dD3OD8/pbczFG46c/pZ4QH9v4vyfsffDno5tTLWZlJylNyzea H19Q== X-Gm-Message-State: AOAM532Edbv+quFbspZrGSNqXr9M33hZWnAl8s0PNCVg2tElPA2iZKTi qm2z+YIfISQ++SiTeRPA0Sn9j1ze/cW+bpmKLnqJ/hRhY9xwWWu2tWQKxlM6kevFn2eovc6986U onbZcLSg9/6jQkSYOdpCZKoVBdPgMuWeufiy8Aj87mDVEHCAQGStZkLNbPrbPtwMevqMBOj4= X-Google-Smtp-Source: ABdhPJwFoapdMU/q84M8qH0qUWWunydhlv609fItu+eH6a5fvXuwRkqASic7MssqqePC21oZ5PtSeIaZcFieXA== X-Received: by 2002:a5b:346:: with SMTP id q6mr5231575ybp.472.1591790402328; Wed, 10 Jun 2020 05:00:02 -0700 (PDT) Date: Wed, 10 Jun 2020 12:59:38 +0100 In-Reply-To: <20200610115940.26035-1-gprocida@google.com> Message-Id: <20200610115940.26035-10-gprocida@google.com> Mime-Version: 1.0 References: <20200610115940.26035-1-gprocida@google.com> X-Mailer: git-send-email 2.27.0.278.ge193c7cf3a9-goog Subject: [PATCH 09/11] Support constructing opaque types for enums To: libabigail@sourceware.org X-Spam-Status: No, score=-24.5 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: Giuliano Procida via Libabigail From: Giuliano Procida Reply-To: Giuliano Procida Cc: kernel-team@android.com, Dodji Seketeli , gprocida@google.com Errors-To: libabigail-bounces@sourceware.org Sender: "Libabigail" From: Dodji Seketeli Now that we are to support opaque types for enums, we ought to support building opaque types for enums as well, to mimic the opaque type design pattern used in C, when private types are specified with type suppression specifications. The core of this change is to make get_opaque_version_of_type work for enums as well, just like what it does for classes. Note that that function doesn't support opaque unions yet either. That should be added at a later point in time, I guess. * src/abg-dwarf-reader.cc (build_internal_underlying_enum_type_name) (build_enum_underlying_type): Factorize these functions out of ... (build_enum_type): ... here. (get_opaque_version_of_type): Make this handle enums as well. So make its return type be type_or_decl_base_sptr, rather than just class_or_union_sptr as it used to be. Signed-off-by: Dodji Seketeli Signed-off-by: Giuliano Procida --- src/abg-dwarf-reader.cc | 139 +++++++++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 30 deletions(-) diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index fddfb149..6b71c1ab 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -438,11 +438,14 @@ static string build_internal_anonymous_die_name(const string &base_name, size_t anonymous_type_index); - static string get_internal_anonymous_die_name(Dwarf_Die *die, size_t anonymous_type_index); +static string +build_internal_underlying_enum_type_name(const string &base_name, + bool is_anonymous); + static string die_qualified_type_name(const read_context& ctxt, const Dwarf_Die* die, @@ -10943,6 +10946,29 @@ build_internal_anonymous_die_name(const string &base_name, return name; } +/// Build the internal name of the underlying type of an enum. +/// +/// @param base_name the (unqualified) name of the enum the underlying +/// type is destined to. +/// +/// @param is_anonymous true if the underlying type of the enum is to +/// be anonymous. +static string +build_internal_underlying_enum_type_name(const string &base_name, + bool is_anonymous = true) +{ + std::ostringstream o; + + if (is_anonymous) + o << "unnamed-enum"; + else + o << "enum-" << base_name; + + o << "-underlying-type"; + + return o.str(); +} + /// Build a full internal anonymous type name. /// /// @param die the DIE representing the anonymous type to consider. @@ -13457,6 +13483,39 @@ build_type_decl(read_context& ctxt, Dwarf_Die* die, size_t where_offset) return result; } +/// Construct the type that is to be used as the underlying type of an +/// enum. +/// +/// @param ctxt the read context to use. +/// +/// @param enum_name the name of the enum that this type is going to +/// be the underlying type of. +/// +/// @param enum_size the size of the enum. +/// +/// @param is_anonymous whether the underlying type is anonymous or +/// not. By default, this should be set to true as before c++11 (and +/// in C), it's almost the case. +static type_decl_sptr +build_enum_underlying_type(read_context& ctxt, + string enum_name, + uint64_t enum_size, + bool is_anonymous = true) +{ + string underlying_type_name = + build_internal_underlying_enum_type_name(enum_name, is_anonymous); + + type_decl_sptr result(new type_decl(ctxt.env(), underlying_type_name, + enum_size, enum_size, location())); + result->set_is_anonymous(is_anonymous); + translation_unit_sptr tu = ctxt.cur_transl_unit(); + decl_base_sptr d = add_decl_to_scope(result, tu->get_global_scope().get()); + result = dynamic_pointer_cast(d); + ABG_ASSERT(result); + canonicalize(result); + return result; +} + /// Build an enum_type_decl from a DW_TAG_enumeration_type DIE. /// /// @param ctxt the read context to use. @@ -13543,15 +13602,6 @@ build_enum_type(read_context& ctxt, // for now we consider that underlying types of enums are all anonymous bool enum_underlying_type_is_anonymous= true; - string underlying_type_name; - if (enum_underlying_type_is_anonymous) - { - underlying_type_name = "unnamed-enum"; - enum_underlying_type_is_anonymous = true; - } - else - underlying_type_name = string("enum-") + name; - underlying_type_name += "-underlying-type"; enum_type_decl::enumerators enms; Dwarf_Die child; @@ -13576,16 +13626,10 @@ build_enum_type(read_context& ctxt, // underlying type, so let's create an artificial one here, which // sole purpose is to be passed to the constructor of the // enum_type_decl type. - type_decl_sptr t(new type_decl(ctxt.env(), underlying_type_name, - size, size, location())); - t->set_is_anonymous(enum_underlying_type_is_anonymous); - translation_unit_sptr tu = ctxt.cur_transl_unit(); - decl_base_sptr d = - add_decl_to_scope(t, tu->get_global_scope().get()); - canonicalize(t); + type_decl_sptr t = + build_enum_underlying_type(ctxt, name, size, + enum_underlying_type_is_anonymous); - t = dynamic_pointer_cast(d); - ABG_ASSERT(t); result.reset(new enum_type_decl(name, loc, t, enms, linkage_name)); result->set_is_anonymous(is_anonymous); result->set_is_declaration_only(is_declaration_only); @@ -15858,7 +15902,8 @@ type_is_suppressed(const read_context& ctxt, /// a private type. /// /// The opaque version version of the type is just a declared-only -/// version of the type (class or union type) denoted by @p type_die. +/// version of the type (class, union or enum type) denoted by @p +/// type_die. /// /// @param ctxt the read context in use. /// @@ -15873,13 +15918,13 @@ type_is_suppressed(const read_context& ctxt, /// /// @return the opaque version of the type denoted by @p type_die or /// nil if no opaque version was found. -static class_or_union_sptr +static type_or_decl_base_sptr get_opaque_version_of_type(read_context &ctxt, scope_decl *scope, Dwarf_Die *type_die, size_t where_offset) { - class_or_union_sptr result; + type_or_decl_base_sptr result; if (type_die == 0) return result; @@ -15887,7 +15932,14 @@ get_opaque_version_of_type(read_context &ctxt, unsigned tag = dwarf_tag(type_die); if (tag != DW_TAG_class_type && tag != DW_TAG_structure_type - && tag != DW_TAG_union_type) + && tag != DW_TAG_union_type + && tag != DW_TAG_enumeration_type) + return result; + + if (tag == DW_TAG_union_type) + // TODO: also handle declaration-only unions. To do that, we mostly + // need to adapt add_or_update_union_type to make it schedule + // declaration-only unions for resolution too. return result; string type_name, linkage_name; @@ -15898,17 +15950,19 @@ get_opaque_version_of_type(read_context &ctxt, string qualified_name = build_qualified_name(scope, type_name); + // // TODO: also handle declaration-only unions. To do that, we mostly // need to adapt add_or_update_union_type to make it schedule // declaration-only unions for resolution too. - string_classes_map::const_iterator i = - ctxt.declaration_only_classes().find(qualified_name); - if (i != ctxt.declaration_only_classes().end()) - result = i->second.back(); - - if (!result) + // + if (tag == DW_TAG_structure_type || tag == DW_TAG_class_type) { - if (tag == DW_TAG_class_type || tag == DW_TAG_structure_type) + string_classes_map::const_iterator i = + ctxt.declaration_only_classes().find(qualified_name); + if (i != ctxt.declaration_only_classes().end()) + result = i->second.back(); + + if (!result) { // So we didn't find any pre-existing forward-declared-only // class for the class definition that we could return as an @@ -15928,6 +15982,31 @@ get_opaque_version_of_type(read_context &ctxt, } } + if (tag == DW_TAG_enumeration_type) + { + string_enums_map::const_iterator i = + ctxt.declaration_only_enums().find(qualified_name); + if (i != ctxt.declaration_only_enums().end()) + result = i->second.back(); + + if (!result) + { + uint64_t size = 0; + if (die_unsigned_constant_attribute(type_die, DW_AT_byte_size, size)) + size *= 8; + type_decl_sptr underlying_type = + build_enum_underlying_type(ctxt, type_name, size, + /*anonymous=*/true); + enum_type_decl::enumerators enumeratorz; + enum_type_decl_sptr enum_type (new enum_type_decl(type_name, + type_location, + underlying_type, + enumeratorz, + linkage_name)); + result = enum_type; + } + } + return result; }