On Thu, 13 Aug 2020, Martin Sebor via Gcc-patches wrote:

> > * Maybe cdk_pointer is followed by cdk_attrs before cdk_id.  In this case
> > the code won't return.
> 
> I think I see the problem you're pointing out (I just don't see how
> to trigger it or test that it doesn't happen).  If the tweak in
> the attached update doesn't fix it a test case would be helpful.

I think you need a while loop there, not just an if, to account for the 
case of multiple consecutive cdk_attrs.  At least the GNU attribute syntax

   direct-declarator:
[...]
     ( gnu-attributes[opt] declarator )

should produce multiple consecutive cdk_attrs for each level of 
parentheses with attributes inside.

> > * Maybe the code is correct to continue because we're in the case of an
> > array of pointers (cdk_array follows).  But as I understand it, the intent
> > is to set up an "arg spec" that describes only the (multidimensional)
> > array that is the parameter itself - not any array pointed to.  And it
> > looks to me like, in the case of an array of pointers to arrays, both sets
> > of array bounds would end up in the spec constructed.
> 
> Ideally, I'd like to check even pointers to arrays and so they should
> be recorded somewhere.  The middle end code doesn't do any checking
> of those yet for out-of-bounds accesses.  It wasn't a goal for
> the first iteration so I've tweaked the code to avoid recording them.

Could you expand the comment on get_parm_array_spec to specify exactly 
what you think the function should be putting in the returned attribute, 
in what order, in cases where there are array declarators (constant, 
empty, [*] and VLA) intermixed with other kinds of declarators and the 
type from the type specifiers may or may not be an array type itself?  
That will provide a basis for subsequent rounds of review of whether the 
function is actually behaving as expected.

As far as I can see, the logic

+      if (TREE_CODE (nelts) == INTEGER_CST)
+       {
+         /* Skip all constant bounds except the most significant one.
+            The interior ones are included in the array type.  */
+         if (next && (next->kind == cdk_array || next->kind == cdk_pointer))
+           continue;

will skip constant bounds in an array that's the target of a pointer 
declarator, but not any other kind of bounds.  Is that what you intend - 
that all the other kind of bounds in pointed-to arrays will be recorded in 
this string?

> > Then, the code
> > 
> > +      if (pd->kind == cdk_id)
> > +       {
> > +         /* Extract the upper bound from a parameter of an array type.  */
> > 
> > also seems misplaced.  If the type specifiers for the parameter are a
> > typedef for an array type, that array type should be processed *before*
> > the declarator to get the correct semantics (as if the bounds from those
> > type specifiers were given in the declarator), not at the end which gets
> > that type out of order with respect to array declarators.  (Processing
> > before the declarator also means clearing the results of that processing
> > if a pointer declarator is encountered at any point, because in that case
> > the array type in the type specifiers is irrelevant.)
> 
> I'm not sure I follow you here.  Can you show me what you mean on
> a piece of code?  This test case (which IIUC does what you described)
> works as expected:
> 
> $ cat q.c && gcc -O2 -S -Wall q.c
> typedef int A[7][9];
> 
> void f (A[3][5]);

So this is equivalent to A[3][5][7][9].  The c_declarator structures have 
the one for the [3] (the top-level bound) inside the one for the [5].  
The [5] bound is skipped by the "Skip all constant bounds except the most 
significant one." logic.  When the [3] bound is reached, the "break;" at 
the end of that processing means the "Extract the upper bound from a 
parameter of an array type." never gets executed.  Try replacing the [3] 
bound by a VLA bound.  As I read the code, it will end up generating a 
spec string that records first the VLA, then the [7], when it should be 
first the 9 (skipped), then the 7 (skipped), then the 5 (skipped), then 
the VLA.  Or if it's "void f (A *[variable][5]);", it will do the same 
thing (VLA, then 7, although both the 7 and the 9 are part of the 
pointed-to type).

-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to