Patch: Fix for Bug 26372 [Modula-2] Parsing of multi-subscript arrays

Gaius Mulley gaius.southwales@gmail.com
Tue Aug 25 12:25:57 GMT 2020


Andrew Burgess <andrew.burgess@embecosm.com> writes:

> * Gaius Mulley via Gdb-patches <gdb-patches@sourceware.org> [2020-08-25 03:29:20 +0100]:
>
>> 
>> 
>> Hi Tom,
>> 
>> here is a bugfix for Pr 26372 [Modula-2] Parsing of multi-subscript arrays.
>> Also included is a dejagnu testcase.  No extra regressions are caused on
>> Debian GNU/Linux Buster amd64, is this ok to apply?
>> 
>> regards,
>> Gaius
>> 
>> 
>> gdb/ChangeLog entry
>> ===================
>> 
>> 2020-08-25  Gaius Mulley  <gaiusmod2@gmail.com>
>> 
>> 	* m2-exp.y: Rewrite array subscript rules to support multidimension
>> 	array access.  (ArgumentList) replaces non_empty_arglist.
>> 	* testsuite/gdb.modula2/multidim.y:  (New file).
>> 	* testsuite/gdb.modula2/multidim.c:  (New file).
>
> The testsuite has its own ChangeLog file so the entries for
> testsuite/... should all be placed there.  You wrote 'multidim.y'
> instead of 'multidim.exp', and the style '(New file)' is out of line
> with our existing ChangeLog style.
>
> Additionally, the ChangeLog entry should include the bug number for
> the bug being fixed.
>
>> 
>> Patch
>> =====
>
> You should consider using 'git format-patch' for create patches for
> the mailing list.  If you can get it set up you can even use 'git
> send-email' to make submitting patches really easy.

Hi Andrew,

many thanks for the steer - very useful and will short cut my old workflow.

>> diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
>> index 70a3d9c483..ea5c83e60a 100644
>> --- a/gdb/m2-exp.y
>> +++ b/gdb/m2-exp.y
>> @@ -293,21 +293,18 @@ set	:	'{' arglist '}'
>>  	;
>> 
>> 
>> -/* Modula-2 array subscript notation [a,b,c...] */
>> -exp     :       exp '['
>> -                        /* This function just saves the number of arguments
>> -			   that follow in the list.  It is *not* specific to
>> -			   function types */
>> -                        { pstate->start_arglist(); }
>
> Removing the calls to start_arglist and end_arglist is a bad idea.
> There is only a single pstate, with a single "current" arglist.  These
> calls allow GDB to support nested arglists.
>
> So, with these calls in place we can do this:
>
>   (gdb) print array[ array[1,2], array[3,4] ]
>
> without these calls this will all get very messed up.

yes thanks for spotting this issue.

>> -                non_empty_arglist ']'  %prec DOT
>> -                        { write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
>> -			  write_exp_elt_longcst (pstate,
>> -						 pstate->end_arglist());
>> -			  write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT); }
>> -        ;
>> -
>> -exp	:	exp '[' exp ']'
>> -			{ write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); }
>> +/* Modula-2 array subscript notation [a,b,c...].  */
>> +exp     :       exp '[' ArgumentList ']' %prec DOT
>
> GDB uses snake case, not camel case for new code.  Given the comment
> attached to ArgumentList below I would suggest a suitable name would
> be non_empty_arglist.
>
>> +                {
>> +                    if (pstate->arglist_len > 1)
>> +		      {
>> +			write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
>> +			write_exp_elt_longcst (pstate, pstate->arglist_len);
>> +			write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
>> +		      }
>> +		    else
>> +		      write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT);
>> +		}
>
> So when I saw this my first though was, I wonder why MULTI_SUBSCRIPT
> doesn't support the 1 subscript case.  Looking at other users, and the
> handling of MULTI_SUBSCRIPT I think it actually does.  So this code
> can be simplified.
>
> Given we know the arglist will have 1 or more entries we can just
> assert that an make use of MULTI_SUBSCRIPT in all cases.
>
> But adding back the call to end_arglist for the reasons above.
>
> Once you do this, and restore the formatting you'll notice all we've
> done is remove one of the 'exp' patterns.
>
>>          ;
>> 
>>  exp	:	exp '('
>> @@ -321,24 +318,22 @@ exp	:	exp '('
>>  			  write_exp_elt_opcode (pstate, OP_FUNCALL); }
>>  	;
>> 
>> -arglist	:
>> -	;
>> -
>> -arglist	:	exp
>> +/* Non empty argument list.  */
>> +ArgumentList:
>> +	exp
>>  		{ pstate->arglist_len = 1; }
>> +|	ArgumentList ',' exp
>> +		{ pstate->arglist_len++; }
>>  ;
>> 
>> -arglist	:	arglist ',' exp   %prec ABOVE_COMMA
>> -			{ pstate->arglist_len++; }
>> +arglist	:
>>  	;
>> 
>> -non_empty_arglist
>> -        :       exp
>> +arglist	:	exp
>>  			{ pstate->arglist_len = 1; }
>>  	;
>> 
>> -non_empty_arglist
>> -        :       non_empty_arglist ',' exp %prec ABOVE_COMMA
>> +arglist	:	arglist ',' exp   %prec ABOVE_COMMA
>>  			{ pstate->arglist_len++; }
>>  	;
>
> This feels like unnecessary churn, you rename 'non_empty_arglist' to
> 'ArgumentList' which I don't like, and you reorder things, but I'd
> rather just leave this code unchanged.
>
>> 
>> 
>> 
>> and simple testcase
>> ===================
>
> Should be included in the patch.  Using 'git format-patch' will take
> care of this for you.
>
> There was a small issue when you wrote:
>
>> if ![runto here] then {
>>     perror "couldn't run to breakpoint foo"
>>     continue
>> }
>
> The string passed to 'perror' is not correct.
>
> I took the liberty of putting together the patch below.  This
> addresses the issues I raised above, and includes an extra test case
> that covers the nested array index use example.
>
> If you're happy with this revision then I'll go ahead and merge this.

yes this is really great - thanks for the analysis and also
improving/applying the patch!

regards,
Gaius


>
> Thanks,
> Andrew
>
> ----
>
> commit 807521c52d6c4bfa0dec7b69a779ae25696652d6
> Author: Andrew Burgess <andrew.burgess@embecosm.com>
> Date:   Tue Aug 25 09:39:27 2020 +0100
>
>     gdb/modula-2: parsing of multi-subscript arrays
>     
>     Fix bug PR m2/26372, GDB's inability to parse multi-dimensional
>     modula-2 arrays.
>     
>     We previously had two rules for handling the parsing of array
>     sub-scripts.  I have reproduced them here with the actual handler
>     blocks removed to make the bug clearer:
>     
>       exp     :    exp '[' non_empty_arglist ']'
>               ;
>     
>       exp     :    exp '[' exp ']'
>               ;
>     
>       non_empty_arglist
>               :       exp
>               ;
>     
>       non_empty_arglist
>               :       non_empty_arglist ',' exp
>               ;
>     
>     This is ambiguous as the pattern "exp '[' exp" could match either of
>     the 'exp' rules.  Currently it just so happens that the parser picks
>     the second 'exp' rule which means we can only handle a single array
>     index.
>     
>     As the handler code for the first 'exp' pattern will correctly handle
>     and number of array indexes then lets just remove the second pattern.
>     
>     gdb/ChangeLog:
>     
>             PR m2/26372
>             * m2-exp.y (exp): Improve comment for non_empty_arglist case, add
>             an assert.  Remove single element array indexing pattern as the
>             MULTI_SUBSCRIPT support will handle this case too.
>     
>     gdb/testsuite/ChangeLog:
>     
>             PR m2/26372
>             * gdb.modula2/multidim.c: New file.
>             * gdb.modula2/multidim.exp: New file.
>
> diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
> index 70a3d9c483a..c79c1f25828 100644
> --- a/gdb/m2-exp.y
> +++ b/gdb/m2-exp.y
> @@ -293,21 +293,20 @@ set	:	'{' arglist '}'
>  	;
>  
>  
> -/* Modula-2 array subscript notation [a,b,c...] */
> +/* Modula-2 array subscript notation [a,b,c...].  */
>  exp     :       exp '['
>                          /* This function just saves the number of arguments
>  			   that follow in the list.  It is *not* specific to
>  			   function types */
>                          { pstate->start_arglist(); }
>                  non_empty_arglist ']'  %prec DOT
> -                        { write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
> +			{
> +			  gdb_assert (pstate->arglist_len > 0);
> +			  write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
>  			  write_exp_elt_longcst (pstate,
>  						 pstate->end_arglist());
> -			  write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT); }
> -        ;
> -
> -exp	:	exp '[' exp ']'
> -			{ write_exp_elt_opcode (pstate, BINOP_SUBSCRIPT); }
> +			  write_exp_elt_opcode (pstate, MULTI_SUBSCRIPT);
> +			}
>  	;
>  
>  exp	:	exp '('
> diff --git a/gdb/testsuite/gdb.modula2/multidim.c b/gdb/testsuite/gdb.modula2/multidim.c
> new file mode 100644
> index 00000000000..b0ce8488681
> --- /dev/null
> +++ b/gdb/testsuite/gdb.modula2/multidim.c
> @@ -0,0 +1,39 @@
> +/* This test script is part of GDB, the GNU debugger.
> +
> +   Copyright 2020 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +
> +static int a[10][20];
> +
> +static void
> +here (void)
> +{
> +}
> +
> +int
> +main ()
> +{
> +  int i, j;
> +  int count = 0;
> +
> +  for (i = 0; i < 10; i++)
> +    for (j = 0; j < 20; j++)
> +      {
> +	a[i][j] = count;
> +	count += 1;
> +      }
> +  here ();
> +}
> diff --git a/gdb/testsuite/gdb.modula2/multidim.exp b/gdb/testsuite/gdb.modula2/multidim.exp
> new file mode 100644
> index 00000000000..ccccaa25981
> --- /dev/null
> +++ b/gdb/testsuite/gdb.modula2/multidim.exp
> @@ -0,0 +1,37 @@
> +# Copyright 2020 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# This file is part of the gdb testsuite.  It contains tests for printing
> +# the elements of an unbounded array using the Modula-2 language mode of
> +# gdb.
> +
> +standard_testfile multidim.c
> +
> +if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
> +	 {debug quiet}]} {
> +    return -1
> +}
> +
> +if ![runto here] then {
> +    perror "couldn't run to breakpoint 'here'"
> +    continue
> +}
> +
> +gdb_test "set lang modula-2" ".*does not match.*" "switch to modula-2"
> +
> +gdb_test "print a\[1,2\]" ".*= 22.*" "second row third column"
> +gdb_test "print a\[2,1\]" ".*= 41.*" "fifth row second column"
> +gdb_test "print a\[a\[0,1\],a\[0,2\]\]" ".*= 22.*" \
> +    "second row third column again"


More information about the Gdb mailing list