* [PATCH] Add C parser support for "restrict" and "_Atomic" @ 2020-03-01 3:01 Tom Tromey 2020-03-01 16:16 ` Ruslan Kabatsayev 0 siblings, 1 reply; 4+ messages in thread From: Tom Tromey @ 2020-03-01 3:01 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey 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. It is done only for C and Objective C, not C++. I wasn't sure if "restrict" should be marked FLAG_SHADOW to support older dialects of C, where this was not a keyword. gdb/ChangeLog 2020-02-29 Tom Tromey <tom@tromey.com> * type-stack.h (enum type_pieces) <tp_atomic, tp_restrict>: 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) <FLAG_C>: New constant. (ident_tokens): Add "restrict" and "_Atomic". (lex_one_token): Handle FLAG_C. gdb/testsuite/ChangeLog 2020-02-29 Tom Tromey <tom@tromey.com> * gdb.base/cvexpr.exp: Add test for _Atomic and restrict. --- gdb/ChangeLog | 19 ++++++++ gdb/c-exp.y | 52 ++++++++++++++------- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.base/cvexpr.exp | 4 ++ gdb/type-stack.c | 76 +++++++++++++++---------------- gdb/type-stack.h | 2 + 6 files changed, 101 insertions(+), 56 deletions(-) diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 3403a857a83..1b35ef2e60a 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 <sval> 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,6 +2353,10 @@ enum token_flag FLAG_CXX = 1, + /* If this bit is set, the token is C-only. */ + + FLAG_C = 1, + /* 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. */ @@ -2416,6 +2428,8 @@ 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, 0}, + {"_Atomic", ATOMIC, OP_NULL, 0}, {"enum", ENUM, OP_NULL, 0}, {"long", LONG, OP_NULL, 0}, {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX}, @@ -2550,6 +2564,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 +2578,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 +2873,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/testsuite/gdb.base/cvexpr.exp b/gdb/testsuite/gdb.base/cvexpr.exp index 92a073a774e..cf5d2c4a553 100644 --- a/gdb/testsuite/gdb.base/cvexpr.exp +++ b/gdb/testsuite/gdb.base/cvexpr.exp @@ -509,3 +509,7 @@ 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" 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 }; -- 2.17.2 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Add C parser support for "restrict" and "_Atomic" 2020-03-01 3:01 [PATCH] Add C parser support for "restrict" and "_Atomic" Tom Tromey @ 2020-03-01 16:16 ` Ruslan Kabatsayev 2020-03-04 0:39 ` Tom Tromey 0 siblings, 1 reply; 4+ messages in thread From: Ruslan Kabatsayev @ 2020-03-01 16:16 UTC (permalink / raw) To: Tom Tromey; +Cc: GDB Patches On Sun, 1 Mar 2020 at 06:01, Tom Tromey <tom@tromey.com> wrote: > > 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. > It is done only for C and Objective C, not C++. GCC has the keywords __restrict__ and __restrict that work in C++ too. These are also affected, including the use in C++. > > I wasn't sure if "restrict" should be marked FLAG_SHADOW to support > older dialects of C, where this was not a keyword. > > gdb/ChangeLog > 2020-02-29 Tom Tromey <tom@tromey.com> > > * type-stack.h (enum type_pieces) <tp_atomic, tp_restrict>: 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) <FLAG_C>: New constant. > (ident_tokens): Add "restrict" and "_Atomic". > (lex_one_token): Handle FLAG_C. > > gdb/testsuite/ChangeLog > 2020-02-29 Tom Tromey <tom@tromey.com> > > * gdb.base/cvexpr.exp: Add test for _Atomic and restrict. > --- > gdb/ChangeLog | 19 ++++++++ > gdb/c-exp.y | 52 ++++++++++++++------- > gdb/testsuite/ChangeLog | 4 ++ > gdb/testsuite/gdb.base/cvexpr.exp | 4 ++ > gdb/type-stack.c | 76 +++++++++++++++---------------- > gdb/type-stack.h | 2 + > 6 files changed, 101 insertions(+), 56 deletions(-) > > diff --git a/gdb/c-exp.y b/gdb/c-exp.y > index 3403a857a83..1b35ef2e60a 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 <sval> 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,6 +2353,10 @@ enum token_flag > > FLAG_CXX = 1, > > + /* If this bit is set, the token is C-only. */ > + > + FLAG_C = 1, > + > /* 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. */ > @@ -2416,6 +2428,8 @@ 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, 0}, > + {"_Atomic", ATOMIC, OP_NULL, 0}, > {"enum", ENUM, OP_NULL, 0}, > {"long", LONG, OP_NULL, 0}, > {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX}, > @@ -2550,6 +2564,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 +2578,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 +2873,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/testsuite/gdb.base/cvexpr.exp b/gdb/testsuite/gdb.base/cvexpr.exp > index 92a073a774e..cf5d2c4a553 100644 > --- a/gdb/testsuite/gdb.base/cvexpr.exp > +++ b/gdb/testsuite/gdb.base/cvexpr.exp > @@ -509,3 +509,7 @@ 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" > 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 > }; > -- > 2.17.2 > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Add C parser support for "restrict" and "_Atomic" 2020-03-01 16:16 ` Ruslan Kabatsayev @ 2020-03-04 0:39 ` Tom Tromey 2020-03-14 18:30 ` Tom Tromey 0 siblings, 1 reply; 4+ messages in thread From: Tom Tromey @ 2020-03-04 0:39 UTC (permalink / raw) To: Ruslan Kabatsayev; +Cc: Tom Tromey, GDB Patches >>>>> "Ruslan" == Ruslan Kabatsayev <b7.10110111@gmail.com> writes: Ruslan> On Sun, 1 Mar 2020 at 06:01, Tom Tromey <tom@tromey.com> wrote: >> >> 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. >> It is done only for C and Objective C, not C++. Ruslan> GCC has the keywords __restrict__ and __restrict that work in C++ too. Ruslan> These are also affected, including the use in C++. 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. I'll have to check how C++ prints a restrict type. Maybe gdb will need another tweak here. >> + {"restrict", RESTRICT, OP_NULL, 0}, I forgot to actually use FLAG_C here, oops. Tom ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Add C parser support for "restrict" and "_Atomic" 2020-03-04 0:39 ` Tom Tromey @ 2020-03-14 18:30 ` Tom Tromey 0 siblings, 0 replies; 4+ messages in thread From: Tom Tromey @ 2020-03-14 18:30 UTC (permalink / raw) To: Tom Tromey; +Cc: Ruslan Kabatsayev, GDB Patches >>>>> "Tom" == Tom Tromey <tom@tromey.com> 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 <tom@tromey.com> 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 <tom@tromey.com> * 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) <tp_atomic, tp_restrict>: 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) <FLAG_C>: New constant. (ident_tokens): Add "restrict", "__restrict__", "__restrict", and "_Atomic". (lex_one_token): Handle FLAG_C. gdb/testsuite/ChangeLog 2020-03-14 Tom Tromey <tom@tromey.com> * 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 <tom@tromey.com> + + * 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) <tp_atomic, tp_restrict>: 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) <FLAG_C>: New constant. + (ident_tokens): Add "restrict", "__restrict__", "__restrict", and + "_Atomic". + (lex_one_token): Handle FLAG_C. + 2020-03-13 Tom Tromey <tom@tromey.com> * 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 <sval> 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 <tom@tromey.com> + + * gdb.base/cvexpr.exp: Add test for _Atomic and restrict. + 2020-03-13 Tom Tromey <tom@tromey.com> * 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 }; ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-03-14 18:30 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-03-01 3:01 [PATCH] Add C parser support for "restrict" and "_Atomic" Tom Tromey 2020-03-01 16:16 ` Ruslan Kabatsayev 2020-03-04 0:39 ` Tom Tromey 2020-03-14 18:30 ` Tom Tromey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).