From patchwork Tue Apr 16 23:06:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 32315 Received: (qmail 77326 invoked by alias); 16 Apr 2019 23:06:28 -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 77265 invoked by uid 89); 16 Apr 2019 23:06:28 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=Declare X-HELO: mail-wm1-f51.google.com Received: from mail-wm1-f51.google.com (HELO mail-wm1-f51.google.com) (209.85.128.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 16 Apr 2019 23:06:25 +0000 Received: by mail-wm1-f51.google.com with SMTP id a184so1028833wma.2 for ; Tue, 16 Apr 2019 16:06:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=KAlAdg0dpZW09SpIfv+cxKjrTE8EZp8TYw//dF9Y0pw=; b=EklptEXU/2um02b8j7Z/vt0vfUmcLijwAGdN80uA1jE07khKnY8RlthUP2R9IqdeTS odqegkJPjbqjJJaG6n4vJ2gTNZJncCPQxMwBzIh33Fgiix+xjmlt4kEH9YB4PKkvEPpk zViil9P1kZAcVpkqV8ND0uIVzj1cmbX3zJgCjsd1P8ua/tXX7hJYIZatI40kFmCN15c7 JoMOFBl1sjMrFZ+XzCn08JzMB5mWlBLLTXJP6zY0x6a2tXphV3TsKZtRhG/nk4NYBWKs aV+BJfkorFVo9m1l06Vnza3ADYyfi8n8G/klLle0QTsUDz2DP5xAUAvattgOgB8zYcpF VziA== Return-Path: Received: from localhost (host86-164-133-98.range86-164.btcentralplus.com. [86.164.133.98]) by smtp.gmail.com with ESMTPSA id r30sm178569129wrr.46.2019.04.16.16.06.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 16 Apr 2019 16:06:21 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv2 4/5] gdb: Introduce new language field la_is_string_type_p Date: Wed, 17 Apr 2019 00:06:09 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-IsSubscribed: yes This commit is preparation work for the next commit, and by itself makes no user visible change to GDB. I've split this work into a separate commit in order to make code review easier. This commit adds a new field 'la_is_string_type_p' to the language struct, this predicate will return true if a type is a string type for the given language. Some languages already have a "is this a string" predicate that I was able to reuse, while for other languages I've had to add a new predicate. In this case I took inspiration from the value printing code for that language - what different conditions would result in printing something as a string. A default "is this a string" method has also been added that looks for TYPE_CODE_STRING, this is the fallback I've used for a couple of languages. In this commit I add the new field and initialise it for each language, however at this stage the new field is never used. gdb/ChangeLog: * ada-lang.c (ada_language_defn): Initialise new field. * c-lang.c (c_is_string_type_p): New function. (c_language_defn): Initialise new field. (cplus_language_defn): Initialise new field. (asm_language_defn): Initialise new field. (minimal_language_defn): Initialise new field. * c-lang.h (c_is_string_type_p): Declare new function. * d-lang.c (d_language_defn): Initialise new field. * f-lang.c (f_is_string_type_p): New function. (f_language_defn): Initialise new field. * go-lang.c (go_is_string_type_p): New function. (go_language_defn): Initialise new field. * language.c (default_is_string_type_p): New function. (unknown_language_defn): Initialise new field. (auto_language_defn): Initialise new field. * language.h (struct language_defn) : New member variable. (default_is_string_type_p): Declare new function. * m2-lang.c (m2_language_defn): Initialise new field. * objc-lang.c (objc_language_defn): Initialise new field. * opencl-lang.c (opencl_language_defn): Initialise new field. * p-lang.c (pascal_is_string_type_p): New function. (pascal_language_defn): Initialise new field. * rust-lang.c (rust_is_string_type_p): New function. (rust_language_defn): Initialise new field. --- gdb/ChangeLog | 28 ++++++++++++++++++++++++++++ gdb/ada-lang.c | 1 + gdb/c-lang.c | 35 +++++++++++++++++++++++++++++++++++ gdb/c-lang.h | 5 +++++ gdb/d-lang.c | 1 + gdb/f-lang.c | 11 +++++++++++ gdb/go-lang.c | 11 +++++++++++ gdb/language.c | 16 ++++++++++++++++ gdb/language.h | 7 +++++++ gdb/m2-lang.c | 22 ++++++++++++++++++++++ gdb/objc-lang.c | 1 + gdb/opencl-lang.c | 1 + gdb/p-lang.c | 11 +++++++++++ gdb/rust-lang.c | 21 +++++++++++++++++++++ 14 files changed, 171 insertions(+) diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index fddb0d7278c..6184067c805 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -14381,6 +14381,7 @@ extern const struct language_defn ada_language_defn = { &ada_varobj_ops, NULL, NULL, + ada_is_string_type, "(...)" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 3be5ef57252..4d5284e2e80 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -715,6 +715,37 @@ c_watch_location_expression (struct type *type, CORE_ADDR addr) (xstrprintf ("* (%s *) %s", name.c_str (), core_addr_to_string (addr))); } +/* See c-lang.h. */ + +bool +c_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + while (TYPE_CODE (type) == TYPE_CODE_REF) + { + type = TYPE_TARGET_TYPE (type); + type = check_typedef (type); + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + { + /* See if target type looks like a string. */ + struct type *array_target_type = TYPE_TARGET_TYPE (type); + return (TYPE_LENGTH (type) > 0 + && TYPE_LENGTH (array_target_type) > 0 + && c_textual_element_type (array_target_type, 0)); + } + case TYPE_CODE_STRING: + return true; + default: + break; + } + + return false; +} + /* Table mapping opcodes into strings for printing operators and precedences of the operators. */ @@ -874,6 +905,7 @@ extern const struct language_defn c_language_defn = &c_varobj_ops, c_get_compile_context, c_compute_program, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; @@ -1019,6 +1051,7 @@ extern const struct language_defn cplus_language_defn = &cplus_varobj_ops, cplus_get_compile_context, cplus_compute_program, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; @@ -1073,6 +1106,7 @@ extern const struct language_defn asm_language_defn = &default_varobj_ops, NULL, NULL, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; @@ -1127,5 +1161,6 @@ extern const struct language_defn minimal_language_defn = &default_varobj_ops, NULL, NULL, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/c-lang.h b/gdb/c-lang.h index e7b6d5ef737..70a95eadbf8 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -148,6 +148,11 @@ extern int cp_is_vtbl_ptr_type (struct type *); extern int cp_is_vtbl_member (struct type *); +/* Return true if TYPE is a string type. Unlike DEFAULT_IS_STRING_TYPE_P + this will detect arrays of characters not just TYPE_CODE_STRING. */ + +extern bool c_is_string_type_p (struct type *type); + /* These are in c-valprint.c. */ extern int c_textual_element_type (struct type *, char); diff --git a/gdb/d-lang.c b/gdb/d-lang.c index 751c521a75d..0f8f916c9b1 100644 --- a/gdb/d-lang.c +++ b/gdb/d-lang.c @@ -251,6 +251,7 @@ extern const struct language_defn d_language_defn = &default_varobj_ops, NULL, NULL, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 77eb50a0761..b03f1f58b41 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -308,6 +308,16 @@ evaluate_subexp_f (struct type *expect_type, struct expression *exp, return nullptr; } +/* Return true if TYPE is a string. */ +static bool +f_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + return (TYPE_CODE (type) == TYPE_CODE_STRING + || (TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CHAR)); +} + static const char *f_extensions[] = { ".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP", @@ -378,6 +388,7 @@ extern const struct language_defn f_language_defn = &default_varobj_ops, NULL, NULL, + f_is_string_type_p, "(...)" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/go-lang.c b/gdb/go-lang.c index b8617cb162d..6473468d4d9 100644 --- a/gdb/go-lang.c +++ b/gdb/go-lang.c @@ -130,6 +130,16 @@ go_classify_struct_type (struct type *type) return GO_TYPE_NONE; } +/* Return true if TYPE is a string. */ + +static bool +go_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + return (TYPE_CODE (type) == TYPE_CODE_STRUCT + && go_classify_struct_type (type) == GO_TYPE_STRING); +} + /* Subroutine of unpack_mangled_go_symbol to simplify it. Given "[foo.]bar.baz", store "bar" in *PACKAGEP and "baz" in *OBJECTP. We stomp on the last '.' to nul-terminate "bar". @@ -612,6 +622,7 @@ extern const struct language_defn go_language_defn = &default_varobj_ops, NULL, NULL, + go_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/language.c b/gdb/language.c index da8dd1bf7ae..9d0eb03b420 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -723,6 +723,20 @@ default_symbol_name_matcher (const char *symbol_search_name, /* See language.h. */ +bool +default_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + while (TYPE_CODE (type) == TYPE_CODE_REF) + { + type = TYPE_TARGET_TYPE (type); + type = check_typedef (type); + } + return (TYPE_CODE (type) == TYPE_CODE_STRING); +} + +/* See language.h. */ + symbol_name_matcher_ftype * get_symbol_name_matcher (const language_defn *lang, const lookup_name_info &lookup_name) @@ -877,6 +891,7 @@ const struct language_defn unknown_language_defn = &default_varobj_ops, NULL, NULL, + default_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; @@ -928,6 +943,7 @@ const struct language_defn auto_language_defn = &default_varobj_ops, NULL, NULL, + default_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/language.h b/gdb/language.h index 261f5a33cc7..e7446efa07f 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -450,6 +450,9 @@ struct language_defn const struct block *expr_block, CORE_ADDR expr_pc); + /* Return true if TYPE is a string type. */ + bool (*la_is_string_type_p) (struct type *type); + /* This string is used by the 'set print max-depth' setting. When GDB replaces a struct or union (during value printing) that is "too deep" this string is displayed instead. */ @@ -575,6 +578,10 @@ extern enum language set_language (enum language); extern int pointer_type (struct type *); +/* Return true if TYPE is a string type, otherwise return false. This + default implementation only detects TYPE_CODE_STRING. */ +extern bool default_is_string_type_p (struct type *type); + /* Error messages */ extern void range_error (const char *, ...) ATTRIBUTE_PRINTF (1, 2); diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index 9f2a97d54fd..1f7113bd71b 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -174,6 +174,27 @@ m2_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, fputs_filtered ("...", stream); } +/* Return true if TYPE is a string. */ + +static bool +m2_is_string_type_p (struct type *type) +{ + type = check_typedef (type); + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_LENGTH (type) > 0 + && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) + { + struct type *elttype = check_typedef (TYPE_TARGET_TYPE (type)); + + if (TYPE_LENGTH (elttype) == 1 && + (TYPE_CODE (elttype) == TYPE_CODE_INT + || TYPE_CODE (elttype) == TYPE_CODE_CHAR)) + return true; + } + + return false; +} + static struct value * evaluate_subexp_modula2 (struct type *expect_type, struct expression *exp, int *pos, enum noside noside) @@ -399,6 +420,7 @@ extern const struct language_defn m2_language_defn = &default_varobj_ops, NULL, NULL, + m2_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index af92e55a437..b25a98106c1 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -409,6 +409,7 @@ extern const struct language_defn objc_language_defn = { &default_varobj_ops, NULL, NULL, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c index c95bf05a98b..93d8e2f5dd3 100644 --- a/gdb/opencl-lang.c +++ b/gdb/opencl-lang.c @@ -1087,6 +1087,7 @@ extern const struct language_defn opencl_language_defn = &default_varobj_ops, NULL, NULL, + c_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/p-lang.c b/gdb/p-lang.c index 0b85f70dfd2..9b9f19b69cf 100644 --- a/gdb/p-lang.c +++ b/gdb/p-lang.c @@ -150,6 +150,16 @@ is_pascal_string_type (struct type *type,int *length_pos, return 0; } +/* This is a wrapper around IS_PASCAL_STRING_TYPE that returns true if TYPE + is a string. */ + +static bool +pascal_is_string_type_p (struct type *type) +{ + return is_pascal_string_type (type, nullptr, nullptr, nullptr, + nullptr, nullptr) > 0; +} + static void pascal_one_char (int, struct ui_file *, int *); /* Print the character C on STREAM as part of the contents of a literal @@ -460,5 +470,6 @@ extern const struct language_defn pascal_language_defn = &default_varobj_ops, NULL, NULL, + pascal_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ }; diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 8faafd49cdd..d878aec6adc 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -226,6 +226,26 @@ rust_chartype_p (struct type *type) && TYPE_UNSIGNED (type)); } +/* Return true if TYPE is a string type. */ +static bool +rust_is_string_type_p (struct type *type) +{ + LONGEST low_bound, high_bound; + + type = check_typedef (type); + return ((TYPE_CODE (type) == TYPE_CODE_STRING) + || (TYPE_CODE (type) == TYPE_CODE_PTR + && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY + && rust_u8_type_p (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type))) + && get_array_bounds (TYPE_TARGET_TYPE (type), &low_bound, + &high_bound))) + || ((TYPE_CODE (type) == TYPE_CODE_UNION + || (TYPE_CODE (type) == TYPE_CODE_STRUCT + && !rust_enum_p (type))) + && rust_slice_type_p (type) + && strcmp (TYPE_NAME (type), "&str") == 0)); +} + /* If VALUE represents a trait object pointer, return the underlying pointer with the correct (i.e., runtime) type. Otherwise, return NULL. */ @@ -2142,5 +2162,6 @@ extern const struct language_defn rust_language_defn = &default_varobj_ops, NULL, NULL, + rust_is_string_type_p, "{...}" /* la_struct_too_deep_ellipsis */ };