From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 126511 invoked by alias); 22 Feb 2018 20:30:48 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 126293 invoked by uid 89); 22 Feb 2018 20:30:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: gateway22.websitewelcome.com Received: from gateway22.websitewelcome.com (HELO gateway22.websitewelcome.com) (192.185.47.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 22 Feb 2018 20:30:33 +0000 Received: from cm10.websitewelcome.com (cm10.websitewelcome.com [100.42.49.4]) by gateway22.websitewelcome.com (Postfix) with ESMTP id 00F02228C2 for ; Thu, 22 Feb 2018 14:30:22 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id oxVVeX7dzcGlpoxVVeTL7f; Thu, 22 Feb 2018 14:30:21 -0600 Received: from 174-29-60-18.hlrn.qwest.net ([174.29.60.18]:53852 helo=pokyo.Home) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89) (envelope-from ) id 1eoxVV-004J6n-Ns; Thu, 22 Feb 2018 14:30:21 -0600 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [RFA v2 2/4] Initial support for variant parts Date: Thu, 22 Feb 2018 20:30:00 -0000 Message-Id: <20180222203018.23551-3-tom@tromey.com> In-Reply-To: <20180222203018.23551-1-tom@tromey.com> References: <20180222203018.23551-1-tom@tromey.com> X-BWhitelist: no X-Source-L: No X-Exim-ID: 1eoxVV-004J6n-Ns X-Source-Sender: 174-29-60-18.hlrn.qwest.net (pokyo.Home) [174.29.60.18]:53852 X-Source-Auth: tom+tromey.com X-Email-Count: 3 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-SW-Source: 2018-02/txt/msg00326.txt.bz2 This adds some initial support for variant parts to gdbtypes.h. A variant part is represented as a union. The union has a flag indicating that it has a discriminant, and information about the discriminant is attached using the dynamic property system. 2018-02-22 Tom Tromey * value.h (value_union_variant): Declare. * valops.c (value_union_variant): New function. * gdbtypes.h (TYPE_FLAG_DISCRIMINATED_UNION): New macro. (struct discriminant_info): New. (enum dynamic_prop_node_kind) : New enumerator. (struct main_type) : New field. --- gdb/ChangeLog | 10 ++++++++++ gdb/gdbtypes.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/valops.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ gdb/value.h | 8 ++++++++ 4 files changed, 113 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 734bbdf832..2b9d886b76 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 2018-02-22 Tom Tromey + * value.h (value_union_variant): Declare. + * valops.c (value_union_variant): New function. + * gdbtypes.h (TYPE_FLAG_DISCRIMINATED_UNION): New macro. + (struct discriminant_info): New. + (enum dynamic_prop_node_kind) : New + enumerator. + (struct main_type) : New field. + +2018-02-22 Tom Tromey + * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add unittests/unpack-selftests.c. * unittests/unpack-selftests.c: New file. diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 613257c47d..62cd8b6f82 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -304,6 +304,14 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags); #define TYPE_FLAG_ENUM(t) (TYPE_MAIN_TYPE (t)->flag_flag_enum) +/* * True if this type is a discriminated union type. Only valid for + TYPE_CODE_UNION. A discriminated union stores a reference to the + discriminant field along with the discriminator values in a dynamic + property. */ + +#define TYPE_FLAG_DISCRIMINATED_UNION(t) \ + (TYPE_MAIN_TYPE (t)->flag_discriminated_union) + /* * Constant type. If this is set, the corresponding type has a const modifier. */ @@ -373,6 +381,39 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags); #define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \ & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL) +/* * Information needed for a discriminated union. A discriminated + union is handled somewhat differently from an ordinary union. + + One field is designated as the discriminant. Only one other field + is active at a time; which one depends on the value of the + discriminant and the data in this structure. + + Additionally, it is possible to have a univariant discriminated + union. In this case, the union has just a single field, which is + assumed to be the only active variant -- in this case no + discriminant is provided. */ + +struct discriminant_info +{ + /* * The index of the discriminant field. If -1, then this union + must have just a single field. */ + + int discriminant_index; + + /* * The index of the default branch of the union. If -1, then + there is no default branch. */ + + int default_index; + + /* * The discriminant values corresponding to each branch. This has + a number of entries equal to the number of fields in this union. + If discriminant_index is not -1, then that entry in this array is + not used. If default_index is not -1, then that entry in this + array is not used. */ + + ULONGEST discriminants[1]; +}; + enum dynamic_prop_kind { PROP_UNDEFINED, /* Not defined. */ @@ -431,6 +472,9 @@ enum dynamic_prop_node_kind /* A property providing an array's byte stride. */ DYN_PROP_BYTE_STRIDE, + + /* A property holding information about a discriminated union. */ + DYN_PROP_DISCRIMINATED, }; /* * List for dynamic type attributes. */ @@ -650,6 +694,13 @@ struct main_type unsigned int flag_flag_enum : 1; + /* * True if this type is a discriminated union type. Only valid + for TYPE_CODE_UNION. A discriminated union stores a reference to + the discriminant field along with the discriminator values in a + dynamic property. */ + + unsigned int flag_discriminated_union : 1; + /* * A discriminant telling us which field of the type_specific union is being used for this type, if any. */ diff --git a/gdb/valops.c b/gdb/valops.c index e038c04fd1..808a98beb7 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2257,6 +2257,50 @@ value_struct_elt_bitpos (struct value **argp, int bitpos, struct type *ftype, return NULL; } +/* See value.h. */ + +int +value_union_variant (struct type *union_type, const gdb_byte *contents) +{ + gdb_assert (TYPE_CODE (union_type) == TYPE_CODE_UNION + && TYPE_FLAG_DISCRIMINATED_UNION (union_type)); + + struct dynamic_prop *discriminant_prop + = get_dyn_prop (DYN_PROP_DISCRIMINATED, union_type); + gdb_assert (discriminant_prop != nullptr); + + struct discriminant_info *info + = (struct discriminant_info *) discriminant_prop->data.baton; + gdb_assert (info != nullptr); + + /* If this is a univariant union, just return the sole field. */ + if (TYPE_NFIELDS (union_type) == 1) + return 0; + /* This should only happen for univariants, which we already dealt + with. */ + gdb_assert (info->discriminant_index != -1); + + /* Compute the discriminant. Note that unpack_field_as_long handles + sign extension when necessary, as does the DWARF reader -- so + signed discriminants will be handled correct despite the use of + an unsigned type here. */ + ULONGEST discriminant = unpack_field_as_long (union_type, contents, + info->discriminant_index); + + for (int i = 0; i < TYPE_NFIELDS (union_type); ++i) + { + if (i != info->default_index + && i != info->discriminant_index + && discriminant == info->discriminants[i]) + return i; + } + + if (info->default_index == -1) + error (_("Could not find variant corresponding to discriminant %s"), + pulongest (discriminant)); + return info->default_index; +} + /* Search through the methods of an object (and its bases) to find a specified method. Return the pointer to the fn_field list FN_LIST of overloaded instances defined in the source language. If available diff --git a/gdb/value.h b/gdb/value.h index 5676d245b9..0bc51304ea 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1169,4 +1169,12 @@ extern struct type *result_type_of_xmethod (struct value *method, extern struct value *call_xmethod (struct value *method, int argc, struct value **argv); +/* Given a discriminated union type and some corresponding value + contents, this will return the field index of the currently active + variant. This will throw an exception if no active variant can be + found. */ + +extern int value_union_variant (struct type *union_type, + const gdb_byte *contents); + #endif /* !defined (VALUE_H) */ -- 2.13.6