From patchwork Tue Jun 21 09:40:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manish Goregaokar X-Patchwork-Id: 13269 Received: (qmail 93314 invoked by alias); 21 Jun 2016 09:40:43 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 93297 invoked by uid 89); 21 Jun 2016 09:40:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=discriminant, interpret, H*Ad:U*tom, Optimized X-HELO: mail-lf0-f52.google.com Received: from mail-lf0-f52.google.com (HELO mail-lf0-f52.google.com) (209.85.215.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 21 Jun 2016 09:40:32 +0000 Received: by mail-lf0-f52.google.com with SMTP id q132so14743082lfe.3 for ; Tue, 21 Jun 2016 02:40:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc; bh=yklrMcFFXNoS1h8Cq/3VHIlCkqT09vuBAHJHeAetv3M=; b=ZDJZXlAWxBopzNq5y66LY4UwoGnFIe+hKYOJjbVe60ErnQnBkdvb0zYH9TSiOewaz8 H7rnC1Vwt/ikGvairXbIJCqMHNj0KuooV0t4UXMWzgK1+ienp9AZlP335ZjA7jORK2GX ueWnG1WgBcXDj2Tl+VfeCZ21OdKjFbb+Rs2NSj4oezPkzDhyH2ApdxzpQkswwsexXpb/ P/Sf8rUEKOgWvpIYmLY3IY2awyLan5Q9DcCaGJy+yW7GW3yPKmYX4BQDug6OeGuF6+zL IOaSGON8PubrVW2Z7e/UnbA3AYUPzbrsZ+EJmFfJmKfnhlMcyZXoMx08/JU/fGbCX6+U ednQ== X-Gm-Message-State: ALyK8tLXulx1/YRaBYiMb2Lwh5saxGkVviG5LCS/M7aLbeLOZEGpPgNkTAEXCcHI/Ff+FL2wDSi7Q3/tFp1U1VhJ MIME-Version: 1.0 X-Received: by 10.28.197.132 with SMTP id v126mr2289841wmf.8.1466502028859; Tue, 21 Jun 2016 02:40:28 -0700 (PDT) Received: by 10.28.36.215 with HTTP; Tue, 21 Jun 2016 02:40:28 -0700 (PDT) Date: Tue, 21 Jun 2016 15:10:28 +0530 Message-ID: Subject: [PATCH 1/2][PR gdb/20239] Make evaluation and type-printing of all NonZero-optimized enums work From: Manish Goregaokar To: gdb-patches@sourceware.org Cc: Tom Tromey Moved over from https://sourceware.org/bugzilla/show_bug.cgi?id=20239. Regarding the xstrdup, this is done because strsep edits the string itself. Built and tested on OS X El Capitan. Methods tests fail, but they are a preexisting failure due to Rust's debuginfo changing. gdb/ChangeLog: 2016-06-21 Manish Goregaokar PR gdb/20239 * rust-lang.c (rust_get_disr_info): Correctly interpret NonZero-optimized enums of arbitrary depth. (rust_print_type): Correctly print NonZero-optimized enums. --- gdb/rust-lang.c | 72 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 17 deletions(-) + do_cleanups (cleanup); return ret; } @@ -841,6 +868,7 @@ rust_print_type (struct type *type, const char *varstring, { /* ADT enums */ int i, len = 0; + int skip_to = 1; /* Skip the discriminant field */ fputs_filtered ("enum ", stream); if (TYPE_TAG_NAME (type) != NULL) @@ -849,7 +877,17 @@ rust_print_type (struct type *type, const char *varstring, fputs_filtered (" ", stream); len = strlen (TYPE_TAG_NAME (type)); } - fputs_filtered ("{\n", stream); + fputs_filtered ("{\n", stream); + + if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX, + strlen (RUST_ENUM_PREFIX)) == 0) { + char *zero_field = strrchr (TYPE_FIELD_NAME (type, 0), '$'); + if (zero_field != NULL && strlen (zero_field) > 1) { + fprintfi_filtered (level+2, stream, "%s,\n", zero_field+1); + /* there is no explicit discriminant field, skip nothing */ + skip_to = 0; + } + } for (i = 0; i < TYPE_NFIELDS (type); ++i) { @@ -859,14 +897,14 @@ rust_print_type (struct type *type, const char *varstring, fprintfi_filtered (level + 2, stream, "%s", name); - if (TYPE_NFIELDS (variant_type) > 1) + if (TYPE_NFIELDS (variant_type) > skip_to) { - int first = 1; + int first = 1; int is_tuple = rust_tuple_variant_type_p (variant_type); int j; fputs_filtered (is_tuple ? "(" : "{", stream); - for (j = 1; j < TYPE_NFIELDS (variant_type); j++) + for (j = skip_to; j < TYPE_NFIELDS (variant_type); j++) { if (first) first = 0; diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 5df99ce..baabf76 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -120,42 +120,69 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr, if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX, strlen (RUST_ENUM_PREFIX)) == 0) { - char *tail; + char *name, *tail, *token; unsigned long fieldno; struct type *member_type; LONGEST value; + char *type_name; + ret.is_encoded = 1; if (TYPE_NFIELDS (type) != 1) error (_("Only expected one field in %s type"), RUST_ENUM_PREFIX); - fieldno = strtoul (TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX), - &tail, 10); - if (*tail != '$') + /* Optimized enums have only one field */ + member_type = TYPE_FIELD_TYPE (type, 0); + + name = xstrdup (TYPE_FIELD_NAME (type, 0)); + cleanup = make_cleanup (xfree, name); + tail = name + strlen (RUST_ENUM_PREFIX); + + /* The location of the value that doubles as a discriminant is + stored in the name of the field, as + RUST$ENCODED$ENUM$$$...$ + where the fieldnos are the indices of the fields that should be + traversed in order to find the field (which may be several fields deep) + and the variantname is the name of the variant of the case when the + field is zero */ + while ((token = strsep (&tail, "$")) != NULL) + { + if (sscanf (token, "%lu", &fieldno) != 1) + { + /* We have reached the enum name, which cannot start with a digit */ + break; + } + if (fieldno >= TYPE_NFIELDS (member_type)) + error (_("%s refers to field after end of member type"), + RUST_ENUM_PREFIX); + + embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8; + member_type = TYPE_FIELD_TYPE (member_type, fieldno); + type_name = TYPE_NAME (member_type); + }; + + if (token >= name + strlen (TYPE_FIELD_NAME (type, 0))) error (_("Invalid form for %s"), RUST_ENUM_PREFIX); + value = unpack_long (member_type, + valaddr + embedded_offset); + - member_type = TYPE_FIELD_TYPE (type, 0); - if (fieldno >= TYPE_NFIELDS (member_type)) - error (_("%s refers to field after end of member type"), - RUST_ENUM_PREFIX); - embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8; - value = unpack_long (TYPE_FIELD_TYPE (member_type, fieldno), - valaddr + embedded_offset); if (value == 0) { ret.field_no = RUST_ENCODED_ENUM_HIDDEN; - ret.name = concat (TYPE_NAME (type), "::", tail + 1, (char *) NULL); + ret.name = concat (TYPE_NAME (type), "::", token, (char *) NULL); } else { ret.field_no = RUST_ENCODED_ENUM_REAL; ret.name = concat (TYPE_NAME (type), "::", - rust_last_path_segment (TYPE_NAME (member_type)), + rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))), (char *) NULL); }