> 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?

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