From patchwork Thu Mar 2 18:57:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 65916 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 F23AD3858410 for ; Thu, 2 Mar 2023 18:57:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F23AD3858410 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1677783452; bh=+hiBGw9obgmdR7yGq5fj8hRZeBQqyY5YRCA7JEzF+94=; h=To:Cc:Subject:References:Date:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Help:List-Subscribe:From: Reply-To:From; b=HSo8afSmslt3eN7PoRryOVxxkog+ZMKUkU3YL5Q33ZxeCsDw0VCDHU+JOd56bxDxW PwSy+Wqm85BekRqAWw5VJwZFHz/71Rz3UiQIEQlDTuPN9utEyRvoyFNH69FK5KSHW3 VYnzTmfiIsv43uaf2YYDeGyFVnPBVgwkk+a1wH78= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id D0D993858D37 for ; Thu, 2 Mar 2023 18:57:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D0D993858D37 Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-662-GlQheoJ6NGyv3IAEPDQR2w-1; Thu, 02 Mar 2023 13:57:22 -0500 X-MC-Unique: GlQheoJ6NGyv3IAEPDQR2w-1 Received: by mail-qv1-f71.google.com with SMTP id jh21-20020a0562141fd500b0053c23b938a0so109557qvb.17 for ; Thu, 02 Mar 2023 10:57:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677783442; h=mime-version:user-agent:message-id:in-reply-to:date:references :organization:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+hiBGw9obgmdR7yGq5fj8hRZeBQqyY5YRCA7JEzF+94=; b=Ngs94zUXk+C/4BXdaCm+LEp/EEKbIhuXdqzT8GzIDwXuzgWmIwz6qQExptA5vWIRjL oOjTt7FSFkfwmXDvp/KSMsAPhMj8R8NYCG4kUMGnzRd/ZbhonfS4OtN4Rr8kSf8BWyX2 zcECObkjcSkWWeK+2yfWpxyhKS0NBfPMQkowDhMwhJmXS5smXperf7/TWqPpXqG/sD95 TOwMOtnf73uIEEc3x01bKIc5CeQW7XA8VEd/snEp/jOkfCxlVGqWFx8I742dTKZb6F5g t8KnkJjAdKMzMKfzwsOIR1HP+ol2raoxnLS4mxM/gq6Mee5Y3A4e+9I0iQOZGxMpoRSh bc0w== X-Gm-Message-State: AO0yUKV6jw7NMOMdpu6rWazEEO577v6ZG4mKXUK/6av4Kkm8yq2lOCL2 +t0P5rnQvCl9szU2wXsHJvSN3efb2i+wRD0P/3A+i0Wfurg3YA63c8UfAVvihCD3fKvQr0Z1i7L 8Pj4B02n86zxdkxWQ0JIv X-Received: by 2002:ad4:5748:0:b0:56e:a05a:2a3a with SMTP id q8-20020ad45748000000b0056ea05a2a3amr20419430qvx.17.1677783441650; Thu, 02 Mar 2023 10:57:21 -0800 (PST) X-Google-Smtp-Source: AK7set9CsGBeKDCL28CbCR5B0yAP1pmrS+l446pJlhjLZcBfmUwSwF2mxMtFKEL9StqQxGGJEAoXLw== X-Received: by 2002:ad4:5748:0:b0:56e:a05a:2a3a with SMTP id q8-20020ad45748000000b0056ea05a2a3amr20419403qvx.17.1677783441309; Thu, 02 Mar 2023 10:57:21 -0800 (PST) Received: from localhost ([88.120.130.27]) by smtp.gmail.com with ESMTPSA id p7-20020ac84087000000b003b62e8b77e7sm185145qtl.68.2023.03.02.10.57.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Mar 2023 10:57:20 -0800 (PST) Received: by localhost (Postfix, from userid 1000) id 1DF8A581C79; Thu, 2 Mar 2023 19:57:19 +0100 (CET) To: Dodji Seketeli Cc: libabigail@sourceware.org, ckalina@redhat.com Subject: [PATCH 03/13] suppression: Factorize out is_data_member_offset_in_range Organization: Red Hat / France References: <877cvzrnws.fsf@redhat.com> <87356nrnmq.fsf@redhat.com> X-Operating-System: Fedora 38 X-URL: http://www.redhat.com Date: Thu, 02 Mar 2023 19:57:18 +0100 In-Reply-To: <87356nrnmq.fsf@redhat.com> (Dodji Seketeli's message of "Thu, 02 Mar 2023 19:53:17 +0100") Message-ID: <87pm9rq8vl.fsf_-_@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: Dodji Seketeli via Libabigail From: Dodji Seketeli Reply-To: Dodji Seketeli Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" Hello, In preparation of subsequent changes, this patch factorizes a function is_data_member_offset_in_range() out of type_suppression::suppression(). This is useful to determine if a data member offset is within an "offset range" expressed by the type_suppression::insertion_range type. This function is useful to implement the offset_of_first_data_member_regexp and offset_of_last_data_member_regexp properties to come in subsequent patches. Please note that is_data_member_offset_in_range works on data members of unions and classes, not just on classes like what the original code of inside type_suppression::suppresses_diff was doing. This patch should not have any functional impact on the code. * include/abg-fwd.h (get_last_data_member) (get_next_data_member_offset): Declare functions. * src/abg-ir.cc (get_next_data_member): Add an overload for class_or_union and write the overload for class_or_union_sptr in term of the former. (get_last_data_member): Add overloads form class_or_union& and class_or_union*. Write the overload for class_or_union_sptr in terms of the one for class_or_union*. (get_next_data_member_offset): Add an overload for class_or_union* and write the overload for class_or_union_sptr in terms of the former. * include/abg-suppression.h (type_suppression::insertion_range::eval_boundary): Take a class_or_union* for the context, as opposed to a class_decl_sptr. This makes this static function work for unions as well. (is_data_member_offset_in_range): Declare new function. * src/abg-suppression.cc (type_suppression::suppression_diff): Factorize ... (is_data_member_offset_in_range): ... this function out. (type_suppression::insertion_range::eval_boundary): Adjust this to make it take a class_or_union* rather than a class_decl_sptr. Signed-off-by: Dodji Seketeli --- include/abg-fwd.h | 11 ++++ include/abg-suppression.h | 12 +++- src/abg-ir.cc | 57 +++++++++++++++++- src/abg-suppression.cc | 122 ++++++++++++++++++++------------------ 4 files changed, 138 insertions(+), 64 deletions(-) diff --git a/include/abg-fwd.h b/include/abg-fwd.h index 155642f0..4051fab5 100644 --- a/include/abg-fwd.h +++ b/include/abg-fwd.h @@ -655,6 +655,12 @@ is_data_member(const decl_base *); const var_decl_sptr get_next_data_member(const class_or_union_sptr&, const var_decl_sptr&); +var_decl_sptr +get_last_data_member(const class_or_union&); + +var_decl_sptr +get_last_data_member(const class_or_union*); + var_decl_sptr get_last_data_member(const class_or_union_sptr&); @@ -740,6 +746,11 @@ get_data_member_offset(const decl_base_sptr); uint64_t get_absolute_data_member_offset(const var_decl&); +bool +get_next_data_member_offset(const class_or_union*, + const var_decl_sptr&, + uint64_t&); + bool get_next_data_member_offset(const class_or_union_sptr&, const var_decl_sptr&, diff --git a/include/abg-suppression.h b/include/abg-suppression.h index 27f52110..b13bb9fb 100644 --- a/include/abg-suppression.h +++ b/include/abg-suppression.h @@ -346,9 +346,9 @@ public: create_fn_call_expr_boundary(const string&); static bool - eval_boundary(boundary_sptr boundary, - class_decl_sptr context, - uint64_t& value); + eval_boundary(const boundary_sptr boundary, + const class_or_union* context, + uint64_t& value); static bool boundary_value_is_end(uint64_t value); @@ -899,6 +899,12 @@ is_type_suppressed(const fe_iface& fe, const location& type_location, bool& type_is_private, bool require_drop_property = false); + +bool +is_data_member_offset_in_range(const var_decl_sptr&, + const type_suppression::insertion_range_sptr&, + const class_or_union*); + } // end namespace suppr diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 321adbf5..ef19eb41 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -5752,7 +5752,7 @@ get_first_non_anonymous_data_member(const var_decl_sptr anon_dm) /// @return the data member that is located right after @p /// data_member. const var_decl_sptr -get_next_data_member(const class_or_union_sptr &klass, +get_next_data_member(const class_or_union *klass, const var_decl_sptr &data_member) { if (!klass ||!data_member) @@ -5773,12 +5773,40 @@ get_next_data_member(const class_or_union_sptr &klass, return var_decl_sptr(); } +/// In the context of a given class or union, this function returns +/// the data member that is located after a given data member. +/// +/// @param klass the class or union to consider. +/// +/// @param the data member to consider. +/// +/// @return the data member that is located right after @p +/// data_member. +const var_decl_sptr +get_next_data_member(const class_or_union_sptr& klass, + const var_decl_sptr &data_member) +{return get_next_data_member(klass.get(), data_member);} + +/// Get the last data member of a class type. +/// +/// @param klass the class type to consider. +var_decl_sptr +get_last_data_member(const class_or_union& klass) +{return klass.get_non_static_data_members().back();} + +/// Get the last data member of a class type. +/// +/// @param klass the class type to consider. +var_decl_sptr +get_last_data_member(const class_or_union* klass) +{return get_last_data_member(*klass);} + /// Get the last data member of a class type. /// /// @param klass the class type to consider. var_decl_sptr get_last_data_member(const class_or_union_sptr &klass) -{return klass->get_non_static_data_members().back();} +{return get_last_data_member(klass.get());} /// Test if a decl is an anonymous data member. /// @@ -6062,7 +6090,7 @@ get_data_member_offset(const decl_base_sptr d) /// @return true iff the data member coming right after @p dm was /// found. bool -get_next_data_member_offset(const class_or_union_sptr& klass, +get_next_data_member_offset(const class_or_union* klass, const var_decl_sptr& dm, uint64_t& offset) { @@ -6073,6 +6101,29 @@ get_next_data_member_offset(const class_or_union_sptr& klass, return true; } +/// Get the offset of the non-static data member that comes after a +/// given one. +/// +/// If there is no data member after after the one given to this +/// function (maybe because the given one is the last data member of +/// the class type) then the function return false. +/// +/// @param klass the class to consider. +/// +/// @param dm the data member before the one we want to retrieve. +/// +/// @param offset out parameter. This parameter is set by the +/// function to the offset of the data member that comes right after +/// the data member @p dm, iff the function returns true. +/// +/// @return true iff the data member coming right after @p dm was +/// found. +bool +get_next_data_member_offset(const class_or_union_sptr& klass, + const var_decl_sptr& dm, + uint64_t& offset) +{return get_next_data_member_offset(klass.get(), dm, offset);} + /// Get the absolute offset of a data member. /// /// If the data member is part of an anonymous data member then this diff --git a/src/abg-suppression.cc b/src/abg-suppression.cc index 5fcdef97..b596e0d5 100644 --- a/src/abg-suppression.cc +++ b/src/abg-suppression.cc @@ -865,65 +865,19 @@ type_suppression::suppresses_diff(const diff* diff) const const class_decl_sptr& first_type_decl = klass_diff->first_class_decl(); - for (string_decl_base_sptr_map::const_iterator m = - klass_diff->inserted_data_members().begin(); - m != klass_diff->inserted_data_members().end(); - ++m) + // All inserted data members must be in an allowed + // insertion range. + for (const auto& m : klass_diff->inserted_data_members()) { - decl_base_sptr member = m->second; - size_t dm_offset = get_data_member_offset(member); + decl_base_sptr member = m.second; bool matched = false; - for (insertion_ranges::const_iterator i = - get_data_member_insertion_ranges().begin(); - i != get_data_member_insertion_ranges().end(); - ++i) - { - type_suppression::insertion_range_sptr range = *i; - uint64_t range_begin_val = 0, range_end_val = 0; - if (!type_suppression::insertion_range::eval_boundary - (range->begin(), first_type_decl, range_begin_val)) - break; - if (!type_suppression::insertion_range::eval_boundary - (range->end(), first_type_decl, range_end_val)) - break; - - uint64_t range_begin = range_begin_val; - uint64_t range_end = range_end_val; - - if (insertion_range::boundary_value_is_end(range_begin) - && insertion_range::boundary_value_is_end(range_end)) - { - // This idiom represents the predicate - // "has_data_member_inserted_at = end" - if (dm_offset > - get_data_member_offset(get_last_data_member - (first_type_decl))) - { - // So the data member was added after - // last data member of the klass. That - // matches the suppr spec - // "has_data_member_inserted_at = end". - matched = true; - continue; - } - } - - if (range_begin > range_end) - // Wrong suppr spec. Ignore it. - continue; - - if (dm_offset < range_begin || dm_offset > range_end) - // The offset of the added data member doesn't - // match the insertion range specified. So - // the diff object won't be suppressed. - continue; - - // If we reached this point, then all the - // insertion range constraints have been - // satisfied. So + for (const auto& range : get_data_member_insertion_ranges()) + if (is_data_member_offset_in_range(is_var_decl(member), + range, + first_type_decl.get())) matched = true; - } + if (!matched) return false; } @@ -1404,9 +1358,9 @@ type_suppression::insertion_range::create_fn_call_expr_boundary(const string& s) /// @return true iff the evaluation was successful and @p value /// contains the resulting value. bool -type_suppression::insertion_range::eval_boundary(boundary_sptr boundary, - class_decl_sptr context, - uint64_t& value) +type_suppression::insertion_range::eval_boundary(const boundary_sptr boundary, + const class_or_union* context, + uint64_t& value) { if (integer_boundary_sptr b = is_integer_boundary(boundary)) { @@ -4962,5 +4916,57 @@ is_type_suppressed(const fe_iface& fe, return false; } +/// Test if a data memer offset is in a given insertion range. +/// +/// @param dm the data member to consider. +/// +/// @param range the insertion range to consider. +/// +/// @param the class (or union) type to consider as the context in +/// which to evaluate the insertion range denoted by @p range. +/// +/// @return true iff the offset of the data member @p dm is in the +/// insertion range @p range in the context of the type denoted by @p +/// context. +bool +is_data_member_offset_in_range(const var_decl_sptr& dm, + const type_suppression::insertion_range_sptr& range, + const class_or_union* context) +{ + ABG_ASSERT(dm && range && context); + + uint64_t range_begin = 0, range_end = 0; + if (!type_suppression::insertion_range::eval_boundary (range->begin(), + context, + range_begin)) + return false; + + if (!type_suppression::insertion_range::eval_boundary (range->end(), + context, + range_end)) + return false; + + if (range_begin > range_end) + // wrong range, ignore it. + return false; + + uint64_t dm_offset = get_data_member_offset(dm); + if (type_suppression::insertion_range::boundary_value_is_end(range_begin) + && type_suppression::insertion_range::boundary_value_is_end(range_end)) + { + // This idiom represents the predicate + // "has_data_member_inserted_at = end" + if (dm_offset > get_data_member_offset(get_last_data_member(context))) + return true; + return false; + } + + if (dm_offset < range_begin || dm_offset > range_end) + // The offset of the data member is outside the range. + return false; + + return true; +} + }// end namespace suppr } // end namespace abigail