> On Dec 3, 2024, at 01:25, Martin Uecker <uec...@tugraz.at> wrote:
> 
> Am Montag, dem 02.12.2024 um 22:33 +0000 schrieb Qing Zhao:
> 
> ....
> 
>>>> 
>>>> 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? 
> 
> When we talk about what is allowed to be used and what warnings/errors
> appear in the test, it is about language semantics.   What made the
> compiler crash was related to the TBAA semantics.

Okay. 
> 
>>> 
>>> 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]. 
> 
> I do not understand what you mean by "consider
> -fstrict-flex-array" 

So, my question is: what’s the behavior of compiling the following :

+struct r {
+  int a;
+  char b[];
+};
+struct r {
+  int a;
+  char b[0];

With "std=c23 -g -fstrict-flex-array=3"? 

> 
> Independent from this option, the types are always different
> types, e.g. sizeof(x->b) would still not be allowed for the
> first type because x->b is incomplete but allowed for the
> second, and return 1 if it were declared with char b[1].  

Okay. 

thanks.

Qing
> 
> 
> Martin
> 
>> 
>> 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