From patchwork Fri Jul 22 23:31:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 56277 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 2C30D3857C5D for ; Fri, 22 Jul 2022 23:31:08 +0000 (GMT) X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by sourceware.org (Postfix) with ESMTPS id 3F1313858C50 for ; Fri, 22 Jul 2022 23:31:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3F1313858C50 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=seketeli.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=seketeli.org Received: (Authenticated sender: dodji@seketeli.org) by mail.gandi.net (Postfix) with ESMTPSA id 945321BF206; Fri, 22 Jul 2022 23:31:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=seketeli.org; s=gm1; t=1658532662; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=+UT5PCoL8uucg+LtGPhgOAFy23aTu184dMqFxjBhKWU=; b=mR0oL/j2BRLG/XwFgpDbiGaJv/WT5i2X8CIVRAZX3TwzV3AGcqtkxLvTL4YpMGon8ciH/D EMKQQfJERc/GAxY8EY8XaJIW0f2rCvygLiy4O81SQjYyTbEKNmKFwgLWN+tI8wita43YCe FUoTwcq9Ssn/Ta4jX2bYlfoZiIuHxEOFaIY79nqtE28Gt/YrQ56RU+ekvnjanQu6OnacOR PGp6ellbV2Nym/xaQy7Tz15S2KPenWZ4X1spI4IOA4oCxmlaggf/qiEN+pXD4jP7JFpTwy ig64C7BkkG9qc9vieWOgJ0HfEJuGT+KmG/tavKX8JNpiArUrwWIQqlkv8aLhVw== Received: by localhost (Postfix, from userid 1000) id E4978581C2F; Sat, 23 Jul 2022 01:31:00 +0200 (CEST) From: Dodji Seketeli To: Dodji Seketeli via Libabigail Subject: [PATCH 2/3] dwarf-reader: Remove redundant qualifiers from qualified types Organization: Me, myself and I References: <87sfms91n0.fsf@redhat.com> X-Operating-System: Fedora 37 X-URL: http://www.seketeli.net/~dodji Date: Sat, 23 Jul 2022 01:31:00 +0200 In-Reply-To: <87sfms91n0.fsf@redhat.com> (Dodji Seketeli via Libabigail's message of "Sat, 23 Jul 2022 01:19:15 +0200") Message-ID: <87h738913f.fsf@seketeli.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, JMQ_SPF_NEUTRAL, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, 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: , Cc: Dodji Seketeli Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" Hello, While looking at something else, I noticed that there are some qualified types built from the DWARF debug info that read: const volatile const int m[5] That's a tree of (chained) qualified types that end up having some redundant qualifiers. That IR tree might look like: [C] --> [C|V] --> [int] We want to edit that IR tree to make it look like: [C] --> [V] --> [int] And that would serialize as const volatile int m[5] This patch introduces the editing of the qualified type IR tree to remove the redundant qualifiers, right after the IR is built from DWARF. * include/abg-fwd.h (strip_redundant_quals_from_underyling_types): Declare new function. * include/abg-ir.h (operator&=): Declare new binary operator for qualified_type_def::CV and ... * src/abg-ir.cc (+operator&=): ... define it here. (strip_redundant_quals_from_underyling_types): Define new function and ... * src/abg-dwarf-reader.cc (maybe_strip_qualification): ... Use it here. * tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt: Adjust. Signed-off-by: Dodji Seketeli Applied to master. --- include/abg-fwd.h | 3 + include/abg-ir.h | 3 + src/abg-dwarf-reader.cc | 5 +- src/abg-ir.cc | 115 ++++++++++++++++++ .../qualifier-typedef-array-report-1.txt | 40 +++--- 5 files changed, 145 insertions(+), 21 deletions(-) diff --git a/include/abg-fwd.h b/include/abg-fwd.h index d32e226a..e84e8a85 100644 --- a/include/abg-fwd.h +++ b/include/abg-fwd.h @@ -827,6 +827,9 @@ strip_typedef(const type_base_sptr); decl_base_sptr strip_useless_const_qualification(const qualified_type_def_sptr t); +void +strip_redundant_quals_from_underyling_types(const qualified_type_def_sptr&); + type_base_sptr peel_typedef_type(const type_base_sptr&); diff --git a/include/abg-ir.h b/include/abg-ir.h index 86a6ce27..2d4b1006 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -2243,6 +2243,9 @@ operator|(qualified_type_def::CV, qualified_type_def::CV); qualified_type_def::CV& operator|=(qualified_type_def::CV&, qualified_type_def::CV); +qualified_type_def::CV& +operator&=(qualified_type_def::CV&, qualified_type_def::CV); + qualified_type_def::CV operator&(qualified_type_def::CV, qualified_type_def::CV); diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index 0c34f617..e5159c89 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -13544,6 +13544,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, decl_base_sptr result = t; type_base_sptr u = t->get_underlying_type(); + strip_redundant_quals_from_underyling_types(t); result = strip_useless_const_qualification(t); if (result.get() != t.get()) return result; @@ -13590,6 +13591,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, qualified_type_def::CV quals = qualified->get_cv_quals(); quals |= t->get_cv_quals(); qualified->set_cv_quals(quals); + strip_redundant_quals_from_underyling_types(qualified); result = is_decl(u); } else @@ -13598,6 +13600,7 @@ maybe_strip_qualification(const qualified_type_def_sptr t, (new qualified_type_def(element_type, t->get_cv_quals(), t->get_location())); + strip_redundant_quals_from_underyling_types(qual_type); add_decl_to_scope(qual_type, is_decl(element_type)->get_scope()); array->set_element_type(qual_type); ctxt.schedule_type_for_late_canonicalization(is_type(qual_type)); @@ -15584,7 +15587,7 @@ build_ir_node_from_die(read_context& ctxt, ctxt.associate_die_to_type(die, ty, where_offset); result = add_decl_to_scope(d, ctxt.cur_transl_unit()->get_global_scope()); - maybe_canonicalize_type(die, ctxt); + maybe_canonicalize_type(is_type(result), ctxt); } } break; diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 5c1ac35b..988b8005 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -6715,6 +6715,113 @@ strip_useless_const_qualification(const qualified_type_def_sptr t) return result; } +/// Merge redundant qualifiers from a tree of qualified types. +/// +/// Suppose a tree of qualified types leads to: +/// +/// const virtual const restrict const int; +/// +/// Suppose the IR tree of qualified types ressembles (with C meaning +/// const, V meaning virtual and R meaning restrict): +/// +/// [C|V]-->[C|R] -->[C] --> [int]. +/// +/// This function walks the IR and remove the redundant CV qualifiers +/// so the IR becomes: +/// +/// [C|V] --> [R] --> [] -->[int]. +/// +/// Note that the empty qualified type (noted []) represents a +/// qualified type with no qualifier. It's rare, but it can exist. +/// I've put it here just for the sake of example. +/// +/// The resulting IR thus represents the (merged) type: +/// +/// const virtual restrict int. +/// +/// This function is a sub-routine of the overload @ref +/// strip_useless_const_qualification which doesn't return any value. +/// +/// @param t the qualified type to consider. +/// +/// @param redundant_quals the (redundant) qualifiers to be removed +/// from the qualifiers of the underlying types of @p t. +/// +/// @return the underlying type of @p t which might have had its +/// redundant qualifiers removed. +static qualified_type_def_sptr +strip_redundant_quals_from_underyling_types(const qualified_type_def_sptr& t, + qualified_type_def::CV redundant_quals) +{ + if (!t) + return t; + + // We must NOT edit canonicalized types. + ABG_ASSERT(!t->get_canonical_type()); + + qualified_type_def_sptr underlying_qualified_type = + is_qualified_type(t->get_underlying_type()); + + // Let's build 'currated qualifiers' that are the qualifiers of the + // current type from which redundant qualifiers are removed. + qualified_type_def::CV currated_quals = t->get_cv_quals(); + + // Remove the redundant qualifiers from these currated qualifiers + currated_quals &= ~redundant_quals; + t->set_cv_quals(currated_quals); + + // The redundant qualifiers, moving forward, is now the union of the + // previous set of redundant qualifiers and the currated qualifiers. + redundant_quals |= currated_quals; + + qualified_type_def_sptr result = t; + if (underlying_qualified_type) + // Now remove the redundant qualifiers from the qualified types + // potentially carried by the underlying type. + result = + strip_redundant_quals_from_underyling_types(underlying_qualified_type, + redundant_quals); + + return result; +} + +/// Merge redundant qualifiers from a tree of qualified types. +/// +/// Suppose a tree of qualified types leads to: +/// +/// const virtual const restrict const int; +/// +/// Suppose the IR tree of qualified types ressembles (with C meaning +/// const, V meaning virtual and R meaning restrict): +/// +/// [C|V]-->[C|R] -->[C] --> [int]. +/// +/// This function walks the IR and remove the redundant CV qualifiers +/// so the IR becomes: +/// +/// [C|V] --> [R] --> [] -->[int]. +/// +/// Note that the empty qualified type (noted []) represents a +/// qualified type with no qualifier. It's rare, but it can exist. +/// I've put it here just for the sake of example. +/// +/// The resulting IR thus represents the (merged) type: +/// +/// const virtual restrict int. +/// +/// @param t the qualified type to consider. The IR below the +/// argument to this parameter will be edited to remove redundant +/// qualifiers where applicable. +void +strip_redundant_quals_from_underyling_types(const qualified_type_def_sptr& t) +{ + if (!t) + return; + + qualified_type_def::CV redundant_quals = qualified_type_def::CV_NONE; + strip_redundant_quals_from_underyling_types(t, redundant_quals); +} + /// Return the leaf underlying type node of a @ref typedef_decl node. /// /// If the underlying type of a @ref typedef_decl node is itself a @@ -15653,6 +15760,14 @@ operator|=(qualified_type_def::CV& l, qualified_type_def::CV r) return l; } +/// Overloaded bitwise &= operator for cv qualifiers. +qualified_type_def::CV& +operator&=(qualified_type_def::CV& l, qualified_type_def::CV r) +{ + l = l & r; + return l; +} + /// Overloaded bitwise AND operator for CV qualifiers. qualified_type_def::CV operator&(qualified_type_def::CV lhs, qualified_type_def::CV rhs) diff --git a/tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt b/tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt index 13949efc..d45c9c6c 100644 --- a/tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt +++ b/tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt @@ -47,39 +47,39 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable underlying type 'typedef A' at qualifier-typedef-array-v0.c:1:1 changed: entity changed from 'typedef A' to compatible type 'void*[7]' type of 'C v_c' changed: - entity changed from 'typedef C' to compatible type 'const volatile void* const[7]' + entity changed from 'typedef C' to compatible type 'const volatile void*[7]' array element type 'void* const' changed: - 'void* const' changed to 'const volatile void* const' - type name changed from 'void* const[7]' to 'const volatile void* const[7]' + 'void* const' changed to 'const volatile void*' + type name changed from 'void* const[7]' to 'const volatile void*[7]' type size hasn't changed type of 'C r_c' changed: - entity changed from 'typedef C' to compatible type 'restrict const void* const[7]' + entity changed from 'typedef C' to compatible type 'restrict const void*[7]' array element type 'void* const' changed: - 'void* const' changed to 'restrict const void* const' - type name changed from 'void* const[7]' to 'restrict const void* const[7]' + 'void* const' changed to 'restrict const void*' + type name changed from 'void* const[7]' to 'restrict const void*[7]' type size hasn't changed type of 'D v_d' changed: - entity changed from 'typedef D' to compatible type 'const volatile void* const[7]' + entity changed from 'typedef D' to compatible type 'const volatile void*[7]' array element type 'void* const' changed: - 'void* const' changed to 'const volatile void* const' - type name changed from 'void* const[7]' to 'const volatile void* const[7]' + 'void* const' changed to 'const volatile void*' + type name changed from 'void* const[7]' to 'const volatile void*[7]' type size hasn't changed type of 'D r_d' changed: - entity changed from 'typedef D' to compatible type 'restrict const void* const[7]' + entity changed from 'typedef D' to compatible type 'restrict const void*[7]' array element type 'void* const' changed: - 'void* const' changed to 'restrict const void* const' - type name changed from 'void* const[7]' to 'restrict const void* const[7]' + 'void* const' changed to 'restrict const void*' + type name changed from 'void* const[7]' to 'restrict const void*[7]' type size hasn't changed type of 'E r_e' changed: - entity changed from 'typedef E' to compatible type 'restrict const volatile volatile void* const[7]' - array element type 'const volatile void* const' changed: - 'const volatile void* const' changed to 'restrict const volatile volatile void* const' - type name changed from 'const volatile void* const[7]' to 'restrict const volatile volatile void* const[7]' + entity changed from 'typedef E' to compatible type 'restrict const volatile void*[7]' + array element type 'const volatile void*' changed: + 'const volatile void*' changed to 'restrict const volatile void*' + type name changed from 'const volatile void*[7]' to 'restrict const volatile void*[7]' type size hasn't changed type of 'F r_f' changed: - entity changed from 'typedef F' to compatible type 'restrict const volatile volatile void* const[7]' - array element type 'const volatile void* const' changed: - 'const volatile void* const' changed to 'restrict const volatile volatile void* const' - type name changed from 'const volatile void* const[7]' to 'restrict const volatile volatile void* const[7]' + entity changed from 'typedef F' to compatible type 'restrict const volatile void*[7]' + array element type 'const volatile void*' changed: + 'const volatile void*' changed to 'restrict const volatile void*' + type name changed from 'const volatile void*[7]' to 'restrict const volatile void*[7]' type size hasn't changed