From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gateway20.websitewelcome.com (gateway20.websitewelcome.com [192.185.44.20]) by sourceware.org (Postfix) with ESMTPS id 99C3639450F3 for ; Sat, 14 Mar 2020 18:30:09 +0000 (GMT) Received: from cm11.websitewelcome.com (cm11.websitewelcome.com [100.42.49.5]) by gateway20.websitewelcome.com (Postfix) with ESMTP id E4D53400D4CC0 for ; Sat, 14 Mar 2020 12:14:55 -0500 (CDT) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id DBY0j5HGPSl8qDBY0jfFAg; Sat, 14 Mar 2020 13:30:08 -0500 X-Authority-Reason: nr=8 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Content-Type:MIME-Version:Message-ID:In-Reply-To:Date: References:Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=8azFpUK0KNwEVMJweIBrSkyM4rOywsLlEZrAj8CXFHQ=; b=Ozs2nE0JWKg5hdYUUdMaR8G8aQ 7G0A/rBN4JEBSWm3Yge1uzh0HJ6z+yt7gsDgvTDpvf+r94LpYrD2AfisQiaPawgGjsEgz/wYAP5jM ksNj5PASIl+5e3nlGrg+gHNvg; Received: from 184-96-250-69.hlrn.qwest.net ([184.96.250.69]:56902 helo=bapiya) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) (envelope-from ) id 1jDBY0-001B3U-G6; Sat, 14 Mar 2020 12:30:08 -0600 From: Tom Tromey To: Tom Tromey Cc: Ruslan Kabatsayev , GDB Patches Subject: Re: [PATCH] Add C parser support for "restrict" and "_Atomic" References: <20200301030013.4619-1-tom@tromey.com> <87o8td6jhy.fsf@tromey.com> X-Attribution: Tom Date: Sat, 14 Mar 2020 12:30:07 -0600 In-Reply-To: <87o8td6jhy.fsf@tromey.com> (Tom Tromey's message of "Tue, 03 Mar 2020 17:39:37 -0700") Message-ID: <87d09e6b80.fsf@tromey.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 184.96.250.69 X-Source-L: No X-Exim-ID: 1jDBY0-001B3U-G6 X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 184-96-250-69.hlrn.qwest.net (bapiya) [184.96.250.69]:56902 X-Source-Auth: tom+tromey.com X-Email-Count: 2 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-Spam-Status: No, score=-24.2 required=5.0 tests=DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_NEUTRAL autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 14 Mar 2020 18:30:11 -0000 >>>>> "Tom" == Tom Tromey writes: Ruslan> GCC has the keywords __restrict__ and __restrict that work in C++ too. Ruslan> These are also affected, including the use in C++. Tom> Thanks, I'll add those. >>> I wasn't sure if "restrict" should be marked FLAG_SHADOW to support >>> older dialects of C, where this was not a keyword. Tom> I'll have to check how C++ prints a restrict type. Tom> Maybe gdb will need another tweak here. >>> + {"restrict", RESTRICT, OP_NULL, 0}, Tom> I forgot to actually use FLAG_C here, oops. Here's an updated patch. I'm checking this in. Tom commit fd7fda86e41744cd6b052ab63d0496f6208413a1 Author: Tom Tromey Date: Sat Mar 14 12:11:42 2020 -0600 Add C parser support for "restrict" and "_Atomic" A user noticed that "watch -location" would fail with a "restrict" pointer. The issue here is that if the DWARF mentions "restrict", gdb will put this into the type name -- but then the C parser will not be able to parse this type. This patch adds support for "restrict" and "_Atomic" to the C parser. C++ doesn't have "restrict", but does have some GCC extensions. The type printer is changed to handle this difference as well, so that watch expressions will work properly. gdb/ChangeLog 2020-03-14 Tom Tromey * c-typeprint.c (cp_type_print_method_args): Print "__restrict__" for C++. (c_type_print_modifier): Likewise. Add "language" parameter. (c_type_print_varspec_prefix, c_type_print_base_struct_union) (c_type_print_base_1): Update. * type-stack.h (enum type_pieces) : New constants. * type-stack.c (type_stack::insert): Handle tp_atomic and tp_restrict. (type_stack::follow_type_instance_flags): Likewise. (type_stack::follow_types): Likewise. Merge type-following code. * c-exp.y (RESTRICT, ATOMIC): New tokens. (space_identifier, cv_with_space_id) (const_or_volatile_or_space_identifier_noopt) (const_or_volatile_or_space_identifier): Remove. (single_qualifier, qualifier_seq_noopt, qualifier_seq): New rules. (ptr_operator, typebase): Update. (enum token_flag) : New constant. (ident_tokens): Add "restrict", "__restrict__", "__restrict", and "_Atomic". (lex_one_token): Handle FLAG_C. gdb/testsuite/ChangeLog 2020-03-14 Tom Tromey * gdb.base/cvexpr.exp: Add test for _Atomic and restrict. diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a4ed9944407..4869693a341 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,28 @@ +2020-03-14 Tom Tromey + + * c-typeprint.c (cp_type_print_method_args): Print "__restrict__" + for C++. + (c_type_print_modifier): Likewise. Add "language" parameter. + (c_type_print_varspec_prefix, c_type_print_base_struct_union) + (c_type_print_base_1): Update. + * type-stack.h (enum type_pieces) : New + constants. + * type-stack.c (type_stack::insert): Handle tp_atomic and + tp_restrict. + (type_stack::follow_type_instance_flags): Likewise. + (type_stack::follow_types): Likewise. Merge type-following code. + * c-exp.y (RESTRICT, ATOMIC): New tokens. + (space_identifier, cv_with_space_id) + (const_or_volatile_or_space_identifier_noopt) + (const_or_volatile_or_space_identifier): Remove. + (single_qualifier, qualifier_seq_noopt, qualifier_seq): New + rules. + (ptr_operator, typebase): Update. + (enum token_flag) : New constant. + (ident_tokens): Add "restrict", "__restrict__", "__restrict", and + "_Atomic". + (lex_one_token): Handle FLAG_C. + 2020-03-13 Tom Tromey * value.h (val_print): Don't declare. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 3403a857a83..50a2eef98b5 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -237,6 +237,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); /* Special type cases, put in to allow the parser to distinguish different legal basetypes. */ %token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD +%token RESTRICT ATOMIC %token DOLLAR_VARIABLE @@ -1169,36 +1170,43 @@ variable: name_not_typename } ; -space_identifier : '@' NAME - { - cpstate->type_stack.insert (pstate, - copy_name ($2.stoken).c_str ()); - } - ; - const_or_volatile: const_or_volatile_noopt | ; -cv_with_space_id : const_or_volatile space_identifier const_or_volatile +single_qualifier: + CONST_KEYWORD + { cpstate->type_stack.insert (tp_const); } + | VOLATILE_KEYWORD + { cpstate->type_stack.insert (tp_volatile); } + | ATOMIC + { cpstate->type_stack.insert (tp_atomic); } + | RESTRICT + { cpstate->type_stack.insert (tp_restrict); } + | '@' NAME + { + cpstate->type_stack.insert (pstate, + copy_name ($2.stoken).c_str ()); + } ; -const_or_volatile_or_space_identifier_noopt: cv_with_space_id - | const_or_volatile_noopt +qualifier_seq_noopt: + single_qualifier + | qualifier_seq single_qualifier ; -const_or_volatile_or_space_identifier: - const_or_volatile_or_space_identifier_noopt +qualifier_seq: + qualifier_seq_noopt | ; ptr_operator: ptr_operator '*' { cpstate->type_stack.insert (tp_pointer); } - const_or_volatile_or_space_identifier + qualifier_seq | '*' { cpstate->type_stack.insert (tp_pointer); } - const_or_volatile_or_space_identifier + qualifier_seq | '&' { cpstate->type_stack.insert (tp_reference); } | '&' ptr_operator @@ -1472,9 +1480,9 @@ typebase (copy_name($2).c_str (), $4, pstate->expression_context_block); } - | const_or_volatile_or_space_identifier_noopt typebase + | qualifier_seq_noopt typebase { $$ = cpstate->type_stack.follow_types ($2); } - | typebase const_or_volatile_or_space_identifier_noopt + | typebase qualifier_seq_noopt { $$ = cpstate->type_stack.follow_types ($1); } ; @@ -2345,11 +2353,15 @@ enum token_flag FLAG_CXX = 1, + /* If this bit is set, the token is C-only. */ + + FLAG_C = 2, + /* If this bit is set, the token is conditional: if there is a symbol of the same name, then the token is a symbol; otherwise, the token is a keyword. */ - FLAG_SHADOW = 2 + FLAG_SHADOW = 4 }; DEF_ENUM_FLAGS_TYPE (enum token_flag, token_flags); @@ -2416,6 +2428,10 @@ static const struct token ident_tokens[] = {"union", UNION, OP_NULL, 0}, {"short", SHORT, OP_NULL, 0}, {"const", CONST_KEYWORD, OP_NULL, 0}, + {"restrict", RESTRICT, OP_NULL, FLAG_C | FLAG_SHADOW}, + {"__restrict__", RESTRICT, OP_NULL, 0}, + {"__restrict", RESTRICT, OP_NULL, 0}, + {"_Atomic", ATOMIC, OP_NULL, 0}, {"enum", ENUM, OP_NULL, 0}, {"long", LONG, OP_NULL, 0}, {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX}, @@ -2550,6 +2566,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if ((tokentab3[i].flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + gdb_assert ((tokentab3[i].flags & FLAG_C) == 0); pstate->lexptr += 3; yylval.opcode = tokentab3[i].opcode; @@ -2563,6 +2580,7 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if ((tokentab2[i].flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + gdb_assert ((tokentab3[i].flags & FLAG_C) == 0); pstate->lexptr += 2; yylval.opcode = tokentab2[i].opcode; @@ -2857,6 +2875,10 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if ((ident_tokens[i].flags & FLAG_CXX) != 0 && par_state->language ()->la_language != language_cplus) break; + if ((ident_tokens[i].flags & FLAG_C) != 0 + && par_state->language ()->la_language != language_c + && par_state->language ()->la_language != language_objc) + break; if ((ident_tokens[i].flags & FLAG_SHADOW) != 0) { diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 1f27b566467..50d0eaa2dde 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -58,7 +58,7 @@ static void c_type_print_varspec_prefix (struct type *, /* Print "const", "volatile", or address space modifiers. */ static void c_type_print_modifier (struct type *, struct ui_file *, - int, int); + int, int, enum language); static void c_type_print_base_1 (struct type *type, struct ui_file *stream, int show, int level, enum language language, @@ -337,7 +337,9 @@ cp_type_print_method_args (struct type *mtype, const char *prefix, fprintf_filtered (stream, " volatile"); if (TYPE_RESTRICT (domain)) - fprintf_filtered (stream, " restrict"); + fprintf_filtered (stream, (language == language_cplus + ? " __restrict__" + : " restrict")); if (TYPE_ATOMIC (domain)) fprintf_filtered (stream, " _Atomic"); @@ -383,7 +385,7 @@ c_type_print_varspec_prefix (struct type *type, stream, show, 1, 1, language, flags, podata); fprintf_filtered (stream, "*"); - c_type_print_modifier (type, stream, 1, need_post_space); + c_type_print_modifier (type, stream, 1, need_post_space, language); break; case TYPE_CODE_MEMBERPTR: @@ -420,7 +422,7 @@ c_type_print_varspec_prefix (struct type *type, stream, show, 1, 0, language, flags, podata); fprintf_filtered (stream, TYPE_CODE(type) == TYPE_CODE_REF ? "&" : "&&"); - c_type_print_modifier (type, stream, 1, need_post_space); + c_type_print_modifier (type, stream, 1, need_post_space, language); break; case TYPE_CODE_METHOD: @@ -481,7 +483,8 @@ c_type_print_varspec_prefix (struct type *type, static void c_type_print_modifier (struct type *type, struct ui_file *stream, - int need_pre_space, int need_post_space) + int need_pre_space, int need_post_space, + enum language language) { int did_print_modifier = 0; const char *address_space_id; @@ -509,7 +512,9 @@ c_type_print_modifier (struct type *type, struct ui_file *stream, { if (did_print_modifier || need_pre_space) fprintf_filtered (stream, " "); - fprintf_filtered (stream, "restrict"); + fprintf_filtered (stream, (language == language_cplus + ? "__restrict__" + : "restrict")); did_print_modifier = 1; } @@ -1050,7 +1055,7 @@ c_type_print_base_struct_union (struct type *type, struct ui_file *stream, hash_holder.reset (local_flags.local_typedefs); } - c_type_print_modifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1, language); if (TYPE_CODE (type) == TYPE_CODE_UNION) fprintf_filtered (stream, "union "); else if (TYPE_DECLARED_CLASS (type)) @@ -1477,7 +1482,7 @@ c_type_print_base_1 (struct type *type, struct ui_file *stream, if (show <= 0 && TYPE_NAME (type) != NULL) { - c_type_print_modifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1, language); /* If we have "typedef struct foo {. . .} bar;" do we want to print it as "struct foo" or as "bar"? Pick the latter for @@ -1542,7 +1547,7 @@ c_type_print_base_1 (struct type *type, struct ui_file *stream, break; case TYPE_CODE_ENUM: - c_type_print_modifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1, language); fprintf_filtered (stream, "enum "); if (TYPE_DECLARED_CLASS (type)) fprintf_filtered (stream, "class "); @@ -1615,7 +1620,7 @@ c_type_print_base_1 (struct type *type, struct ui_file *stream, local_flags.local_typedefs = NULL; - c_type_print_modifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1, language); fprintf_filtered (stream, "flag "); print_name_maybe_canonical (TYPE_NAME (type), flags, stream); if (show > 0) @@ -1689,7 +1694,7 @@ c_type_print_base_1 (struct type *type, struct ui_file *stream, type name, then complain. */ if (TYPE_NAME (type) != NULL) { - c_type_print_modifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1, language); print_name_maybe_canonical (TYPE_NAME (type), flags, stream); } else diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ec22de89d57..1f16e344563 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-03-14 Tom Tromey + + * gdb.base/cvexpr.exp: Add test for _Atomic and restrict. + 2020-03-13 Tom Tromey * gdb.base/printcmds.exp (test_print_strings): Add regression diff --git a/gdb/testsuite/gdb.base/cvexpr.exp b/gdb/testsuite/gdb.base/cvexpr.exp index 92a073a774e..d905198a72c 100644 --- a/gdb/testsuite/gdb.base/cvexpr.exp +++ b/gdb/testsuite/gdb.base/cvexpr.exp @@ -509,3 +509,14 @@ foreach testspec $specs { do_test $prefix $opts } } + +# These tests don't rely on the debug format. +gdb_test "ptype _Atomic int" "type = _Atomic int" +gdb_test "ptype int * restrict" "type = int \\* restrict" + +# C++ does not have "restrict". +gdb_test_no_output "set lang c++" +gdb_test "ptype int * restrict" "A syntax error in expression.*" + +# There is a GCC extension for __restrict__, though. +gdb_test "ptype int * __restrict__" "type = int \\* __restrict__" diff --git a/gdb/type-stack.c b/gdb/type-stack.c index ab7e0261cad..73b7d5a8dfc 100644 --- a/gdb/type-stack.c +++ b/gdb/type-stack.c @@ -33,12 +33,14 @@ type_stack::insert (enum type_pieces tp) gdb_assert (tp == tp_pointer || tp == tp_reference || tp == tp_rvalue_reference || tp == tp_const - || tp == tp_volatile); + || tp == tp_volatile || tp == tp_restrict + || tp == tp_atomic); /* If there is anything on the stack (we know it will be a tp_pointer), insert the qualifier above it. Otherwise, simply push this on the top of the stack. */ - if (!m_elements.empty () && (tp == tp_const || tp == tp_volatile)) + if (!m_elements.empty () && (tp == tp_const || tp == tp_volatile + || tp == tp_restrict)) slot = 1; else slot = 0; @@ -88,6 +90,12 @@ type_stack::follow_type_instance_flags () case tp_volatile: flags |= TYPE_INSTANCE_FLAG_VOLATILE; break; + case tp_atomic: + flags |= TYPE_INSTANCE_FLAG_ATOMIC; + break; + case tp_restrict: + flags |= TYPE_INSTANCE_FLAG_RESTRICT; + break; default: gdb_assert_not_reached ("unrecognized tp_ value in follow_types"); } @@ -102,6 +110,8 @@ type_stack::follow_types (struct type *follow_type) int make_const = 0; int make_volatile = 0; int make_addr_space = 0; + bool make_restrict = false; + bool make_atomic = false; int array_size; while (!done) @@ -109,19 +119,7 @@ type_stack::follow_types (struct type *follow_type) { case tp_end: done = 1; - if (make_const) - follow_type = make_cv_type (make_const, - TYPE_VOLATILE (follow_type), - follow_type, 0); - if (make_volatile) - follow_type = make_cv_type (TYPE_CONST (follow_type), - make_volatile, - follow_type, 0); - if (make_addr_space) - follow_type = make_type_with_address_space (follow_type, - make_addr_space); - make_const = make_volatile = 0; - make_addr_space = 0; + goto process_qualifiers; break; case tp_const: make_const = 1; @@ -132,41 +130,39 @@ type_stack::follow_types (struct type *follow_type) case tp_space_identifier: make_addr_space = pop_int (); break; + case tp_atomic: + make_atomic = true; + break; + case tp_restrict: + make_restrict = true; + break; case tp_pointer: follow_type = lookup_pointer_type (follow_type); + goto process_qualifiers; + case tp_reference: + follow_type = lookup_lvalue_reference_type (follow_type); + goto process_qualifiers; + case tp_rvalue_reference: + follow_type = lookup_rvalue_reference_type (follow_type); + process_qualifiers: if (make_const) - follow_type = make_cv_type (make_const, - TYPE_VOLATILE (follow_type), + follow_type = make_cv_type (make_const, + TYPE_VOLATILE (follow_type), follow_type, 0); if (make_volatile) - follow_type = make_cv_type (TYPE_CONST (follow_type), - make_volatile, + follow_type = make_cv_type (TYPE_CONST (follow_type), + make_volatile, follow_type, 0); if (make_addr_space) - follow_type = make_type_with_address_space (follow_type, + follow_type = make_type_with_address_space (follow_type, make_addr_space); + if (make_restrict) + follow_type = make_restrict_type (follow_type); + if (make_atomic) + follow_type = make_atomic_type (follow_type); make_const = make_volatile = 0; make_addr_space = 0; - break; - case tp_reference: - follow_type = lookup_lvalue_reference_type (follow_type); - goto process_reference; - case tp_rvalue_reference: - follow_type = lookup_rvalue_reference_type (follow_type); - process_reference: - if (make_const) - follow_type = make_cv_type (make_const, - TYPE_VOLATILE (follow_type), - follow_type, 0); - if (make_volatile) - follow_type = make_cv_type (TYPE_CONST (follow_type), - make_volatile, - follow_type, 0); - if (make_addr_space) - follow_type = make_type_with_address_space (follow_type, - make_addr_space); - make_const = make_volatile = 0; - make_addr_space = 0; + make_restrict = make_atomic = false; break; case tp_array: array_size = pop_int (); diff --git a/gdb/type-stack.h b/gdb/type-stack.h index ee004d1be8d..8060f2fea78 100644 --- a/gdb/type-stack.h +++ b/gdb/type-stack.h @@ -40,6 +40,8 @@ enum type_pieces tp_const, tp_volatile, tp_space_identifier, + tp_atomic, + tp_restrict, tp_type_stack, tp_kind };