> On Dec 2, 2024, at 16:00, Martin Uecker <uec...@tugraz.at> wrote:
> 
> Am Montag, dem 02.12.2024 um 16:31 +0000 schrieb Qing Zhao:
>> 
>>> On Nov 30, 2024, at 07:10, Martin Uecker <uec...@tugraz.at> wrote:
>>> 
>>> Am Dienstag, dem 26.11.2024 um 15:15 +0000 schrieb Qing Zhao:
>>>> 
>>>>> On Nov 25, 2024, at 16:46, Martin Uecker <uec...@tugraz.at> wrote:
>>>>> 
>>>>> 
>>>>> Hi Qing,
>>>>> 
>>>>> Am Montag, dem 25.11.2024 um 17:40 +0000 schrieb Qing Zhao:
>>>>>> Hi, Martin,
>>>>>> 
>>>>>> I didn’t go through all the details of your patch.
>>>>>> 
>>>>>> But I have one question:
>>>>>> 
>>>>>> Did you consider the effect of the option -fstrict-flex-array 
>>>>>> (https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/C-Dialect-Options.html#index-fstrict-flex-arrays)
>>>>>>  on how gcc treats the zero size trailing array, 1-element trailing 
>>>>>> array as flexible array member in the patch?
>>>>> 
>>>>> I used the function which was already there which
>>>>> does not take this into account.  For the new version
>>>>> of the patch this should not matter anymore.
>>>> 
>>>> Why it’s not matter anymore?
>>>> 
>>>> For the following testing case:
>>>> 
>>>> struct S{int x,y[1];}*a;
>>>> int main(void){
>>>> struct S{int x,y[];};
>>>> }
>>>> 
>>>> With your latest patch,  the two structures are considered as compatible 
>>>> with -g;
>>>> However, if we add -fstrict-flex-array=2 or -fstrict-flex-array=3,  the 
>>>> trailing array y[1] is NOT treated
>>>> as FAM anymore, as a result, these two structure are NOT compatible too. 
>>>> 
>>>> Do I miss anything obvious?
>>> 
>>> It is not about compatibility from a language semantic point of you
>>> but for TBAA-compatibility which needs to be consistent with it but
>>> can (and must be) more general.
>>> 
>>> For TBAA, I think we want 
>>> 
>>> struct foo { int x; int y[]; };
>>> 
>>> to be TBAA-compatible to
>>> 
>>> struct foo { int x; int y[3]; };
>> 
>> Okay, I see now.  Thank you for the explanation.
>> (Now I also see this from the comments of the routine 
>> gimple_canonical_types_compatible_p -:)
>> 
>> 
>> Though, what confused me is the testing case in your patch:
>> 
>> diff --git a/gcc/testsuite/gcc.dg/pr114014.c 
>> b/gcc/testsuite/gcc.dg/pr114014.c
>> new file mode 100644
>> index 00000000000..ab783f4f85d
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/pr114014.c
>> @@ -0,0 +1,14 @@
>> +/* PR c/114014
>> + * { dg-do compile }
>> + * { dg-options "-std=c23 -g" } */
>> +
>> +struct r {
>> +  int a;
>> +  char b[];
>> +};
>> +struct r {
>> +  int a;
>> +  char b[0];
>> +}; /* { dg-error "redefinition" } */
>> +
>> +
>> 
>> Is the above testing case claiming that b[] and b[0] are compatible from a 
>> language semantic point of view?
> 
> It would test that we do not crash with checking.
> 
> Semantically, in c23 if you redeclare a type in the same scope then
> it must not only be compatible but is also not allowed to differ.
> So a redeclaration in the same scope has stricter requirements than
> compatibility (this also true for typedefs for example).

So, here does the “compatibility” mean “compatibility from a language semantic 
point of view” or TBAA-compability? 
> 
> Whether we allow
> 
> struct r {
>  int a;
>  char b[];
> };
> 
> struct r {
>  int a;
>  char b[0];
> };
> 
> depends on us because the [0] is an extension.

[0] is an extension for representing FAM ONLY when -fstrict-flex-array<3, when 
-fstrict-flex-array=3 specified, [0] is NOT considered as an extension for FAM 
anymore. 
For [1], only when -fstrict-flex-array<2 spedified, it’s considered as an 
extension for FAM.

So, I still think that we should consider -fstrict-flex-array and its impact on 
the GCC extensions [0] and [1]. 

Qing
>  I would make it
> compatible but not allow redefinition as the types are different.


> 
> 
> Martin
> 
> 
>> 
>> thanks.
>> 
>> Qing
>>> even when we do not treat the later as FAM (i.e. still forbid
>>> out-of-bounds accesses).
>>> 
>>> E.g. see Richard's comment: 
>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114713#c2
>>> 
>>> 
>>> Martin
>>> 
>>>> Thanks.
>>>> 
>>>> Qing
>>>>> 
>>>>> Martin
>>>>> 
>>>>> 
>>>>>> 
>>>>>> thanks.
>>>>>> 
>>>>>> Qing
>>>>>>> On Nov 23, 2024, at 14:45, Martin Uecker <uec...@tugraz.at> wrote:
>>>>>>> 
>>>>>>> 
>>>>>>> This patch tries fixes the errors we have because of
>>>>>>> flexible array members.  I am bit unsure about the exception
>>>>>>> for the mode. 
>>>>>>> 
>>>>>>> Bootstrapped and regression tested on x86_64.
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> Fix type compatibility for types with flexible array member 
>>>>>>> [PR113688,PR114014,PR117724]
>>>>>>> 
>>>>>>> verify_type checks the compatibility of TYPE_CANONICAL using
>>>>>>> gimple_canonical_types_compatible_p.   But it is stricter than what the
>>>>>>> C standard requires and therefor inconsistent with how TYPE_CANONICAL 
>>>>>>> is set
>>>>>>> in the C FE.  Here, the logic is changed to ignore array size when one 
>>>>>>> of the
>>>>>>> types is a flexible array member.  To not get errors because of 
>>>>>>> inconsistent
>>>>>>> number of members, zero-sized arrays are not ignored anymore when 
>>>>>>> checking
>>>>>>> fields of a struct (which is stricter than what was done before).
>>>>>>> Finally, a exception is added that allows the TYPE_MODE of a type with
>>>>>>> flexible array member to differ from another compatible type.
>>>>>>> 
>>>>>>>         PR c/113688
>>>>>>>         PR c/114014
>>>>>>>         PR c/117724
>>>>>>> 
>>>>>>> gcc/ChangeLog:
>>>>>>>         * tree.cc (gimple_canonical_types_compatible_p): Revise
>>>>>>>         logic for types with FAM.
>>>>>>>         (verify_type): Add exception for mode for types with FAM.
>>>>>>> 
>>>>>>> gcc/testsuite/ChangeLog:
>>>>>>>         * gcc.dg/pr113688.c: New test.
>>>>>>>         * gcc.dg/pr114014.c: New test.
>>>>>>>         * gcc.dg/pr117724.c: New test.
>>>>>>> 
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/pr113688.c 
>>>>>>> b/gcc/testsuite/gcc.dg/pr113688.c
>>>>>>> new file mode 100644
>>>>>>> index 00000000000..8dee8c86f1b
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.dg/pr113688.c
>>>>>>> @@ -0,0 +1,8 @@
>>>>>>> +/* { dg-do compile } */
>>>>>>> +/* { dg-options "-g" } */
>>>>>>> +
>>>>>>> +struct S{int x,y[1];}*a;
>>>>>>> +int main(void){
>>>>>>> + struct S{int x,y[];};
>>>>>>> +}
>>>>>>> +
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/pr114014.c 
>>>>>>> b/gcc/testsuite/gcc.dg/pr114014.c
>>>>>>> new file mode 100644
>>>>>>> index 00000000000..ab783f4f85d
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.dg/pr114014.c
>>>>>>> @@ -0,0 +1,14 @@
>>>>>>> +/* PR c/114014
>>>>>>> + * { dg-do compile }
>>>>>>> + * { dg-options "-std=c23 -g" } */
>>>>>>> +
>>>>>>> +struct r {
>>>>>>> +  int a;
>>>>>>> +  char b[];
>>>>>>> +};
>>>>>>> +struct r {
>>>>>>> +  int a;
>>>>>>> +  char b[0];
>>>>>>> +}; /* { dg-error "redefinition" } */
>>>>>>> +
>>>>>>> +
>>>>>>> diff --git a/gcc/testsuite/gcc.dg/pr117724.c 
>>>>>>> b/gcc/testsuite/gcc.dg/pr117724.c
>>>>>>> new file mode 100644
>>>>>>> index 00000000000..d631daeb644
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/gcc.dg/pr117724.c
>>>>>>> @@ -0,0 +1,16 @@
>>>>>>> +/* { dg-do compile } */
>>>>>>> +/* { dg-options "-g" } */
>>>>>>> +
>>>>>>> +struct {
>>>>>>> +  unsigned long len;
>>>>>>> +  unsigned long size;
>>>>>>> +  char data[];
>>>>>>> +}; /* { dg-warning "unnamed struct" } */
>>>>>>> +struct {
>>>>>>> +  struct {
>>>>>>> +    unsigned long len;
>>>>>>> +    unsigned long size;
>>>>>>> +    char data[6];
>>>>>>> +  };
>>>>>>> +}; /* { dg-warning "unnamed struct" } */
>>>>>>> +
>>>>>>> diff --git a/gcc/tree.cc b/gcc/tree.cc
>>>>>>> index 1da06c7d4e9..dbf6b180496 100644
>>>>>>> --- a/gcc/tree.cc
>>>>>>> +++ b/gcc/tree.cc
>>>>>>> @@ -13900,8 +13900,11 @@ gimple_canonical_types_compatible_p 
>>>>>>> (const_tree t1, const_tree t2,
>>>>>>>    || TREE_CODE (t1) == NULLPTR_TYPE)
>>>>>>>  return true;
>>>>>>> 
>>>>>>> -  /* Can't be the same type if they have different mode.  */
>>>>>>> -  if (TYPE_MODE (t1) != TYPE_MODE (t2))
>>>>>>> +  /* Can't be compatible types if they have different mode.  We allow
>>>>>>> +     mismatching modes for types with flexible array member.  */
>>>>>>> +  if (!flexible_array_type_p (t1)
>>>>>>> +      && !flexible_array_type_p (t2)
>>>>>>> +      && (TYPE_MODE (t1) != TYPE_MODE (t2)))
>>>>>>>  return false;
>>>>>>> 
>>>>>>> /* Non-aggregate types can be handled cheaply.  */
>>>>>>> @@ -13952,7 +13955,7 @@ gimple_canonical_types_compatible_p (const_tree 
>>>>>>> t1, const_tree t2,
>>>>>>>  {
>>>>>>>  case ARRAY_TYPE:
>>>>>>>    /* Array types are the same if the element types are the same and
>>>>>>> - the number of elements are the same.  */
>>>>>>> + minimum and maximum index are the same.  */
>>>>>>>    if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE 
>>>>>>> (t2),
>>>>>>> trust_type_canonical)
>>>>>>>>> TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
>>>>>>> @@ -14046,23 +14049,35 @@ gimple_canonical_types_compatible_p 
>>>>>>> (const_tree t1, const_tree t2,
>>>>>>>  f1 || f2;
>>>>>>>  f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
>>>>>>> {
>>>>>>> -    /* Skip non-fields and zero-sized fields.  */
>>>>>>> -    while (f1 && (TREE_CODE (f1) != FIELD_DECL
>>>>>>> -  || (DECL_SIZE (f1)
>>>>>>> -      && integer_zerop (DECL_SIZE (f1)))))
>>>>>>> +    /* Skip non-fields.  */
>>>>>>> +    while (f1 && (TREE_CODE (f1) != FIELD_DECL))
>>>>>>>   f1 = TREE_CHAIN (f1);
>>>>>>> -    while (f2 && (TREE_CODE (f2) != FIELD_DECL
>>>>>>> -  || (DECL_SIZE (f2)
>>>>>>> -      && integer_zerop (DECL_SIZE (f2)))))
>>>>>>> +    while (f2 && (TREE_CODE (f2) != FIELD_DECL))
>>>>>>>   f2 = TREE_CHAIN (f2);
>>>>>>> if (!f1 || !f2)
>>>>>>>   break;
>>>>>>> +
>>>>>>> +    tree t1 = TREE_TYPE (f1);
>>>>>>> +    tree t2 = TREE_TYPE (f2);
>>>>>>> +
>>>>>>> +    /* Special case for flexible array members.  */
>>>>>>> +    if (TREE_CHAIN (f1) == NULL_TREE
>>>>>>> + && TREE_CHAIN (f2) == NULL_TREE
>>>>>>> + && TREE_CODE (t1) == ARRAY_TYPE
>>>>>>> + && TREE_CODE (t2) == ARRAY_TYPE
>>>>>>> + && (!DECL_NOT_FLEXARRAY (f1)
>>>>>>> +    || !DECL_NOT_FLEXARRAY (f2))
>>>>>>> + && TYPE_REVERSE_STORAGE_ORDER (t1) == TYPE_REVERSE_STORAGE_ORDER (t2)
>>>>>>> + && TYPE_NONALIASED_COMPONENT (t1) == TYPE_NONALIASED_COMPONENT (t2)
>>>>>>> + && gimple_canonical_types_compatible_p
>>>>>>> + (TREE_TYPE (t1), TREE_TYPE (t2),
>>>>>>> + trust_type_canonical))
>>>>>>> +      ;
>>>>>>> /* The fields must have the same name, offset and type.  */
>>>>>>> -    if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
>>>>>>> +    else if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
>>>>>>>>> !gimple_compare_field_offset (f1, f2)
>>>>>>>>> !gimple_canonical_types_compatible_p
>>>>>>> -      (TREE_TYPE (f1), TREE_TYPE (f2),
>>>>>>> -       trust_type_canonical))
>>>>>>> +      (t1, t2, trust_type_canonical))
>>>>>>>   return false;
>>>>>>> }
>>>>>>> 
>>>>>>> @@ -14206,6 +14221,9 @@ verify_type (const_tree t)
>>>>>>>  }
>>>>>>> 
>>>>>>> if (COMPLETE_TYPE_P (t) && TYPE_CANONICAL (t)
>>>>>>> +      /* We allow a mismatch for flexible array members.  */
>>>>>>> +      && !flexible_array_type_p (t)
>>>>>>> +      && !flexible_array_type_p (TYPE_CANONICAL (t))
>>>>>>>    && TYPE_MODE (t) != TYPE_MODE (TYPE_CANONICAL (t)))
>>>>>>>  {
>>>>>>>    error ("%<TYPE_MODE%> of %<TYPE_CANONICAL%> is not compatible");
>> 
>> 
> 

Reply via email to