Hi, Sid, 

Thanks a lot for your time and effort to review this patch set!
And sorry for my late reply due to a long vacation immediately after Cauldron, 
just came back this Monday..

See my reply embedded below:

> On Oct 5, 2023, at 2:51 PM, Siddhesh Poyarekar <siddh...@gotplt.org> wrote:
> 
> On 2023-08-25 11:24, Qing Zhao wrote:
>> Provide a new counted_by attribute to flexible array member field.
> 
> The obligatory "I can't ack the patch but here's a review" disclaimer :)
> 
>> 'counted_by (COUNT)'
>>      The 'counted_by' attribute may be attached to the flexible array
>>      member of a structure.  It indicates that the number of the
>>      elements of the array is given by the field named "COUNT" in the
>>      same structure as the flexible array member.  GCC uses this
>>      information to improve the results of the array bound sanitizer and
>>      the '__builtin_dynamic_object_size'.
>>      For instance, the following code:
>>           struct P {
>>             size_t count;
>>             char other;
>>             char array[] __attribute__ ((counted_by (count)));
>>           } *p;
>>      specifies that the 'array' is a flexible array member whose number
>>      of elements is given by the field 'count' in the same structure.
>>      The field that represents the number of the elements should have an
>>      integer type.  An explicit 'counted_by' annotation defines a
>>      relationship between two objects, 'p->array' and 'p->count', that
>>      'p->array' has _at least_ 'p->count' number of elements available.
>>      This relationship must hold even after any of these related objects
>>      are updated.  It's the user's responsibility to make sure this
>>      relationship to be kept all the time.  Otherwise the results of the
>>      array bound sanitizer and the '__builtin_dynamic_object_size' might
>>      be incorrect.
>>      For instance, in the following example, the allocated array has
>>      less elements than what's specified by the 'sbuf->count', this is
>>      an user error.  As a result, out-of-bounds access to the array
>>      might not be detected.
>>           #define SIZE_BUMP 10
>>           struct P *sbuf;
>>           void alloc_buf (size_t nelems)
>>           {
>>             sbuf = (struct P *) malloc (MAX (sizeof (struct P),
>>                                            (offsetof (struct P, array[0])
>>                                             + nelems * sizeof (char))));
>>             sbuf->count = nelems + SIZE_BUMP;
>>             /* This is invalid when the sbuf->array has less than sbuf->count
>>                elements.  */
>>           }
>>      In the following example, the 2nd update to the field 'sbuf->count'
>>      of the above structure will permit out-of-bounds access to the
>>      array 'sbuf>array' as well.
>>           #define SIZE_BUMP 10
>>           struct P *sbuf;
>>           void alloc_buf (size_t nelems)
>>           {
>>             sbuf = (struct P *) malloc (MAX (sizeof (struct P),
>>                                            (offsetof (struct P, array[0])
>>                                             + (nelems + SIZE_BUMP) * sizeof 
>> (char))));
>>             sbuf->count = nelems;
>>             /* This is valid when the sbuf->array has at least sbuf->count
>>                elements.  */
>>           }
>>           void use_buf (int index)
>>           {
>>             sbuf->count = sbuf->count + SIZE_BUMP + 1;
>>             /* Now the value of sbuf->count is larger than the number
>>                of elements of sbuf->array.  */
>>             sbuf->array[index] = 0;
>>             /* then the out-of-bound access to this array
>>                might not be detected.  */
>>           }
>> gcc/c-family/ChangeLog:
>>      PR C/108896
>>      * c-attribs.cc (handle_counted_by_attribute): New function.
>>      (attribute_takes_identifier_p): Add counted_by attribute to the list.
>>      * c-common.cc (c_flexible_array_member_type_p): ...To this.
>>      * c-common.h (c_flexible_array_member_type_p): New prototype.
>> gcc/c/ChangeLog:
>>      PR C/108896
>>      * c-decl.cc (flexible_array_member_type_p): Renamed and moved to...
>>      (add_flexible_array_elts_to_size): Use renamed function.
>>      (is_flexible_array_member_p): Use renamed function.
>>      (verify_counted_by_attribute): New function.
>>      (finish_struct): Use renamed function and verify counted_by
>>      attribute.
>> gcc/ChangeLog:
>>      PR C/108896
>>      * doc/extend.texi: Document attribute counted_by.
>>      * tree.cc (get_named_field): New function.
>>      * tree.h (get_named_field): New prototype.
>> gcc/testsuite/ChangeLog:
>>      PR C/108896
>>      * gcc.dg/flex-array-counted-by.c: New test.
>> ---
>>  gcc/c-family/c-attribs.cc                    | 54 ++++++++++++-
>>  gcc/c-family/c-common.cc                     | 13 ++++
>>  gcc/c-family/c-common.h                      |  1 +
>>  gcc/c/c-decl.cc                              | 79 +++++++++++++++-----
>>  gcc/doc/extend.texi                          | 77 +++++++++++++++++++
>>  gcc/testsuite/gcc.dg/flex-array-counted-by.c | 40 ++++++++++
>>  gcc/tree.cc                                  | 40 ++++++++++
>>  gcc/tree.h                                   |  5 ++
>>  8 files changed, 291 insertions(+), 18 deletions(-)
>>  create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by.c
>> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
>> index e2792ca6898b..65e4f6639109 100644
>> --- a/gcc/c-family/c-attribs.cc
>> +++ b/gcc/c-family/c-attribs.cc
>> @@ -103,6 +103,8 @@ static tree handle_warn_if_not_aligned_attribute (tree 
>> *, tree, tree,
>>                                                int, bool *);
>>  static tree handle_strict_flex_array_attribute (tree *, tree, tree,
>>                                               int, bool *);
>> +static tree handle_counted_by_attribute (tree *, tree, tree,
>> +                                       int, bool *);
>>  static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
>>  static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
>>  static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
>> @@ -373,6 +375,8 @@ const struct attribute_spec c_common_attribute_table[] =
>>                            handle_warn_if_not_aligned_attribute, NULL },
>>    { "strict_flex_array",      1, 1, true, false, false, false,
>>                            handle_strict_flex_array_attribute, NULL },
>> +  { "counted_by",         1, 1, true, false, false, false,
>> +                          handle_counted_by_attribute, NULL },
>>    { "weak",                   0, 0, true,  false, false, false,
>>                            handle_weak_attribute, NULL },
>>    { "noplt",                   0, 0, true,  false, false, false,
>> @@ -601,7 +605,8 @@ attribute_takes_identifier_p (const_tree attr_id)
>>    else if (!strcmp ("mode", spec->name)
>>         || !strcmp ("format", spec->name)
>>         || !strcmp ("cleanup", spec->name)
>> -       || !strcmp ("access", spec->name))
>> +       || !strcmp ("access", spec->name)
>> +       || !strcmp ("counted_by", spec->name))
>>      return true;
>>    else
>>      return targetm.attribute_takes_identifier_p (attr_id);
>> @@ -2555,6 +2560,53 @@ handle_strict_flex_array_attribute (tree *node, tree 
>> name,
>>    return NULL_TREE;
>>  }
>>  +/* Handle a "counted_by" attribute; arguments as in
>> +   struct attribute_spec.handler.  */
>> +
>> +static tree
>> +handle_counted_by_attribute (tree *node, tree name,
>> +                         tree args, int ARG_UNUSED (flags),
>> +                         bool *no_add_attrs)
>> +{
>> +  tree decl = *node;
>> +  tree argval = TREE_VALUE (args);
>> +
>> +  /* This attribute only applies to field decls of a structure.  */
>> +  if (TREE_CODE (decl) != FIELD_DECL)
>> +    {
>> +      error_at (DECL_SOURCE_LOCATION (decl),
>> +            "%qE attribute may not be specified for non-field"
>> +            " declaration %q+D", name, decl);
>> +      *no_add_attrs = true;
>> +    }
> 
> Applies only to struct fields.  OK.
> 
>> +  /* This attribute only applies to field with array type.  */
>> +  else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
>> +    {
>> +      error_at (DECL_SOURCE_LOCATION (decl),
>> +            "%qE attribute may not be specified for a non-array field",
>> +            name);
>> +      *no_add_attrs = true;
>> +    }
> 
> The struct field should also be an array.  OK.
> 
>> +  /* This attribute only applies to a C99 flexible array member type.  */
>> +  else if (! c_flexible_array_member_type_p (TREE_TYPE (decl)))
>> +    {
>> +      error_at (DECL_SOURCE_LOCATION (decl),
>> +            "%qE attribute may not be specified for a non"
>> +            " flexible array member field",
>> +            name);
>> +      *no_add_attrs = true;
>> +    }
> 
> Additionally, the field should be a *flex* array.  OK.  Could this be 
> reworded to:
> 
>  %qE attribute only applies to C99 flexible array members
> 
> That would make it clear that the GNU extension flex arrays (i.e. any last 
> array member of a struct) don't support this attribute.
Yes, make sense, will update this.
> 
>> +  /* The argument should be an identifier.  */
>> +  else if (TREE_CODE (argval) != IDENTIFIER_NODE)
>> +    {
>> +      error_at (DECL_SOURCE_LOCATION (decl),
>> +            "%<counted_by%> argument not an identifier");
>> +      *no_add_attrs = true;
>> +    }
> 
> Argument should be an identifier, and the check for validity of the 
> identifier comes later in finish_struct.  OK.
> 
>> +
>> +  return NULL_TREE;
>> +}
>> +
>>  /* Handle a "weak" attribute; arguments as in
>>     struct attribute_spec.handler.  */
>>  diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
>> index 9fbaeb437a12..a18937245c2a 100644
>> --- a/gcc/c-family/c-common.cc
>> +++ b/gcc/c-family/c-common.cc
>> @@ -9521,6 +9521,19 @@ c_common_finalize_early_debug (void)
>>        (*debug_hooks->early_global_decl) (cnode->decl);
>>  }
>>  +/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]".  
>> */
>> +bool
>> +c_flexible_array_member_type_p (const_tree type)
>> +{
>> +  if (TREE_CODE (type) == ARRAY_TYPE
>> +      && TYPE_SIZE (type) == NULL_TREE
>> +      && TYPE_DOMAIN (type) != NULL_TREE
>> +      && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
>> +    return true;
>> +
>> +  return false;
>> +}
>> +
> 
> Hoist flexible_array_member_type_p to use more widely.  OK.
> 
>>  /* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the
>>     values of attribute strict_flex_array and the flag_strict_flex_arrays.  
>> */
>>  unsigned int
>> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
>> index 78fc5248ba68..c29bb429062b 100644
>> --- a/gcc/c-family/c-common.h
>> +++ b/gcc/c-family/c-common.h
>> @@ -909,6 +909,7 @@ extern tree fold_for_warn (tree);
>>  extern tree c_common_get_narrower (tree, int *);
>>  extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *);
>>  extern void c_common_finalize_early_debug (void);
>> +extern bool c_flexible_array_member_type_p (const_tree);
>>  extern unsigned int c_strict_flex_array_level_of (tree);
>>  extern bool c_option_is_from_cpp_diagnostics (int);
>>  diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
>> index 1f9eb44dbaa2..e943b49b5230 100644
>> --- a/gcc/c/c-decl.cc
>> +++ b/gcc/c/c-decl.cc
>> @@ -5173,19 +5173,6 @@ set_array_declarator_inner (struct c_declarator *decl,
>>    return decl;
>>  }
>>  -/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]".  
>> */
>> -static bool
>> -flexible_array_member_type_p (const_tree type)
>> -{
>> -  if (TREE_CODE (type) == ARRAY_TYPE
>> -      && TYPE_SIZE (type) == NULL_TREE
>> -      && TYPE_DOMAIN (type) != NULL_TREE
>> -      && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
>> -    return true;
>> -
>> -  return false;
>> -}
>> -
>>  /* Determine whether TYPE is a one-element array type "[1]".  */
>>  static bool
>>  one_element_array_type_p (const_tree type)
>> @@ -5222,7 +5209,7 @@ add_flexible_array_elts_to_size (tree decl, tree init)
>>      elt = CONSTRUCTOR_ELTS (init)->last ().value;
>>    type = TREE_TYPE (elt);
>> -  if (flexible_array_member_type_p (type))
>> +  if (c_flexible_array_member_type_p (type))
>>      {
>>        complete_array_type (&type, elt, false);
>>        DECL_SIZE (decl)
>> @@ -9094,7 +9081,7 @@ is_flexible_array_member_p (bool is_last_field,
>>      bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x));
>>    bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x));
>> -  bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x));
>> +  bool is_flexible_array = c_flexible_array_member_type_p (TREE_TYPE (x));
>>      unsigned int strict_flex_array_level = c_strict_flex_array_level_of (x);
>>  
> 
> Simple refactoring.  OK.
> 
>> @@ -9124,6 +9111,61 @@ is_flexible_array_member_p (bool is_last_field,
>>    return false;
>>  }
>>  +/* Verify the argument of the counted_by attribute of the flexible array
> 
> Verify *that* the argument...

Sure, will update this.

> 
>> +   member FIELD_DECL is a valid field of the containing structure's 
>> fieldlist,
>> +   FIELDLIST, Report error and remove this attribute when it's not.  */
>> +static void
>> +verify_counted_by_attribute (tree fieldlist, tree field_decl)
>> +{
>> +  tree attr_counted_by = lookup_attribute ("counted_by",
>> +                                       DECL_ATTRIBUTES (field_decl));
>> +
>> +  if (!attr_counted_by)
>> +    return;
>> +
>> +  /* If there is an counted_by attribute attached to the field,
>> +     verify it.  */
>> +
>> +  const char *fieldname
>> +    = IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (attr_counted_by)));
>> +
>> +  /* Verify the argument of the attrbute is a valid field of the
> 
> s/attrbute/attribute/

Okay.
> 
>> +     containing structure.  */
>> +
>> +  tree counted_by_field = get_named_field (fieldlist, fieldname);
>> +
>> +  /* Error when the field is not found in the containing structure.  */
>> +  if (!counted_by_field)
>> +    {
>> +      error_at (DECL_SOURCE_LOCATION (field_decl),
>> +            "%qE attribute argument not a field declaration"
>> +            " in the same structure, ignore it",
>> +            (get_attribute_name (attr_counted_by)));
> 
> Probably someone with English as a first language would make a better 
> suggestion, but how about:
> 
>  Argument specified in %qE attribute is not a field declaration in the
>  same structure, ignoring it.

This is better, will update it.

> 
>> +
>> +      DECL_ATTRIBUTES (field_decl)
>> +    = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
>> +    }
>> +  else
>> +  /* Error when the field is not with an integer type.  */
> 
> Suggest: Flag an error when the field is not of an integer type.
Okay. 
> 
>> +    {
>> +      while (TREE_CHAIN (counted_by_field))
>> +    counted_by_field = TREE_CHAIN (counted_by_field);
>> +      tree real_field = TREE_VALUE (counted_by_field);
>> +
>> +      if (TREE_CODE (TREE_TYPE (real_field)) != INTEGER_TYPE)
>> +    {
>> +      error_at (DECL_SOURCE_LOCATION (field_decl),
>> +                 "%qE attribute argument not a field declaration"
>> +                 " with integer type, ignore it",
>> +                 (get_attribute_name (attr_counted_by)));
> 
> Suggest:
> 
>  Argument specified in %qE attribute is not of an integer type,
>  ignoring it.
Will update this.
> 
>> +
>> +      DECL_ATTRIBUTES (field_decl)
>> +        = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
>> +    }
>> +    }
>> +
>> +  return;
>> +}
>>    /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
>>     LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
>> @@ -9244,7 +9286,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
>> tree attributes,
>>      DECL_PACKED (x) = 1;
>>          /* Detect flexible array member in an invalid context.  */
>> -      if (flexible_array_member_type_p (TREE_TYPE (x)))
>> +      if (c_flexible_array_member_type_p (TREE_TYPE (x)))
>>      {
>>        if (TREE_CODE (t) == UNION_TYPE)
>>          {
>> @@ -9265,6 +9307,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
>> tree attributes,
>>                      "members");
>>            TREE_TYPE (x) = error_mark_node;
>>          }
>> +      /* if there is a counted_by attribute attached to this field,
>> +         verify it.  */
>> +      verify_counted_by_attribute (fieldlist, x);
>>      }
>>          if (pedantic && TREE_CODE (t) == RECORD_TYPE
>> @@ -9279,7 +9324,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
>> tree attributes,
>>       when x is an array and is the last field.  */
>>        if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
>>      TYPE_INCLUDES_FLEXARRAY (t)
>> -      = is_last_field && flexible_array_member_type_p (TREE_TYPE (x));
>> +      = is_last_field && c_flexible_array_member_type_p (TREE_TYPE (x));
>>        /* Recursively set TYPE_INCLUDES_FLEXARRAY for the context of x, t
>>       when x is an union or record and is the last field.  */
>>        else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
>> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
>> index 97eaacf8a7ec..ea6240646936 100644
>> --- a/gcc/doc/extend.texi
>> +++ b/gcc/doc/extend.texi
>> @@ -7617,6 +7617,83 @@ When both the attribute and the option present at the 
>> same time, the level of
>>  the strictness for the specific trailing array field is determined by the
>>  attribute.
>>  +@cindex @code{counted_by} variable attribute
>> +@item counted_by (@var{count})
>> +The @code{counted_by} attribute may be attached to the flexible array
>> +member of a structure.  It indicates that the number of the elements of the
>> +array is given by the field named "@var{count}" in the same structure as the
>> +flexible array member.  GCC uses this information to improve the results of
>> +the array bound sanitizer and the @code{__builtin_dynamic_object_size}.
> 
> Maybe specify somehow that this only applies to C99 flexible arrays?  Like:
> 
>  The @code{counted_by} attribute may be attached to the C99 flexible
>  array member of a structure...

Yes, specify that the attribute will be only applied to C99 FMA is necessary, I 
will update this.
> 
>> +
>> +For instance, the following code:
>> +
>> +@smallexample
>> +struct P @{
>> +  size_t count;
>> +  char other;
>> +  char array[] __attribute__ ((counted_by (count)));
>> +@} *p;
>> +@end smallexample
>> +
>> +@noindent
>> +specifies that the @code{array} is a flexible array member whose number of
>> +elements is given by the field @code{count} in the same structure.
>> +
>> +The field that represents the number of the elements should have an integer
>> +type.  An explicit @code{counted_by} annotation defines a relationship 
>> between
>> +two objects, @code{p->array} and @code{p->count}, that @code{p->array} has
>> +@emph{at least} @code{p->count} number of elements available.  This 
>> relationship
>> +must hold even after any of these related objects are updated.  It's the 
>> user's
>> +responsibility to make sure this relationship to be kept all the time.
>> +Otherwise the results of the array bound sanitizer and the
>> +@code{__builtin_dynamic_object_size} might be incorrect.
> 
> Suggest:
> 
>  The field that represents the number of the elements must have an
>  integer type.  An explicit @code{counted_by} annotation defines a
>  relationship between two objects, @code{p->array} and @code{p->count},
>  that @code{p->array} has @emph{at least} @code{p->count} number of
>  elements available.  The user is responsible to ensure that this
>  relationship is consistently maintained during the lifetime of the
>  object. Failure to do so may result in results of the array bound
>  sanitizer and the @code{__builtin_dynamic_object_size} being
>  undefined.

Thanks for the suggestion, will update accordingly.
> 
>> +
>> +For instance, in the following example, the allocated array has less 
>> elements
>> +than what's specified by the @code{sbuf->count}, this is an user error. As a
>> +result, out-of-bounds access to the array might not be detected.
>> +
>> +@smallexample
>> +#define SIZE_BUMP 10
>> +struct P *sbuf;
>> +void alloc_buf (size_t nelems)
>> +@{
>> +  sbuf = (struct P *) malloc (MAX (sizeof (struct P),
>> +                               (offsetof (struct P, array[0])
>> +                                + nelems * sizeof (char))));
>> +  sbuf->count = nelems + SIZE_BUMP;
>> +  /* This is invalid when the sbuf->array has less than sbuf->count
>> +     elements.  */
>> +@}
>> +@end smallexample
>> +
>> +In the following example, the 2nd update to the field @code{sbuf->count} of
>> +the above structure will permit out-of-bounds access to the array
>> +@code{sbuf>array} as well.
>> +
>> +@smallexample
>> +#define SIZE_BUMP 10
>> +struct P *sbuf;
>> +void alloc_buf (size_t nelems)
>> +@{
>> +  sbuf = (struct P *) malloc (MAX (sizeof (struct P),
>> +                               (offsetof (struct P, array[0])
>> +                                + (nelems + SIZE_BUMP) * sizeof (char))));
>> +  sbuf->count = nelems;
>> +  /* This is valid when the sbuf->array has at least sbuf->count
>> +     elements.  */
>> +@}
>> +void use_buf (int index)
>> +@{
>> +  sbuf->count = sbuf->count + SIZE_BUMP + 1;
>> +  /* Now the value of sbuf->count is larger than the number
>> +     of elements of sbuf->array.  */
>> +  sbuf->array[index] = 0;
>> +  /* then the out-of-bound access to this array
>> +     might not be detected.  */
>> +@}
>> +@end smallexample
>> +
>> +
> 
> I'm unsure if we should be demonstrating example code with undefined 
> behaviour.  Maybe the documentation is better off without it.

Good point, will delete the example with undefined behavior from the doc. 
> 
>>  @cindex @code{alloc_size} variable attribute
>>  @item alloc_size (@var{position})
>>  @itemx alloc_size (@var{position-1}, @var{position-2})
>> diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by.c 
>> b/gcc/testsuite/gcc.dg/flex-array-counted-by.c
>> new file mode 100644
>> index 000000000000..f8ce9776bf86
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by.c
>> @@ -0,0 +1,40 @@
>> +/* testing the correct usage of attribute counted_by.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2" } */
>> +
>> +#include <wchar.h>
>> +
>> +int size;
>> +int x __attribute ((counted_by (size))); /* { dg-error "attribute may not 
>> be specified for non-field declaration" } */
>> +
>> +struct trailing {
>> +  int count;
>> +  int field __attribute ((counted_by (count))); /* { dg-error "attribute 
>> may not be specified for a non-array field" } */
>> +};
>> +
>> +struct trailing_1 {
>> +  int count;
>> +  int array_1[0] __attribute ((counted_by (count))); /* { dg-error 
>> "attribute may not be specified for a non flexible array member field" } */
>> +};
>> +
>> +int count;
>> +struct trailing_array_2 {
>> +  int count;
>> +  int array_2[] __attribute ((counted_by ("count"))); /* { dg-error 
>> "argument not an identifier" } */
>> +};
>> +
>> +struct trailing_array_3 {
>> +  int other;
>> +  int array_3[] __attribute ((counted_by (L"count"))); /* { dg-error 
>> "argument not an identifier" } */
>> +};
>> +
>> +struct trailing_array_4 {
>> +  int other;
>> +  int array_4[] __attribute ((counted_by (count))); /* { dg-error 
>> "attribute argument not a field declaration in the same structure, ignore 
>> it" } */
>> +};
>> +
>> +int count;
>> +struct trailing_array_5 {
>> +  float count;
>> +  int array_5[] __attribute ((counted_by (count))); /* { dg-error 
>> "attribute argument not a field declaration with integer type, ignore it" } 
>> */
>> +};
> 
> Tests look OK in principle, but may need updating for the error message.
Okay. 

thanks.

Qing
> 
>> diff --git a/gcc/tree.cc b/gcc/tree.cc
>> index 420857b110c4..fcd36ae0cd74 100644
>> --- a/gcc/tree.cc
>> +++ b/gcc/tree.cc
>> @@ -12745,6 +12745,46 @@ array_ref_element_size (tree exp)
>>      return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
>>  }
>>  +/* Given a field list, FIELDLIST, of a structure/union, return a TREE_LIST,
>> +   with each TREE_VALUE a FIELD_DECL stepping down the chain to the FIELD
>> +   whose name is FIELDNAME, which is the last TREE_VALUE of the list.
>> +   return NULL_TREE if such field is not found.  Normally this list is of
>> +   length one, but if the field is embedded with (nested) anonymous 
>> structures
>> +   or unions, this list steps down the chain to the field.  */
>> +tree
>> +get_named_field (tree fieldlist, const char *fieldname)
>> +{
>> +  tree named_field = NULL_TREE;
>> +  for (tree field = fieldlist; field; field = DECL_CHAIN (field))
>> +    {
>> +      if (TREE_CODE (field) != FIELD_DECL)
>> +    continue;
>> +      if (DECL_NAME (field) != NULL)
>> +    if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), fieldname) == 0)
>> +      {
>> +        named_field = tree_cons (NULL_TREE, field, named_field);
>> +        break;
>> +      }
>> +    else
>> +      continue;
>> +      /* if the field is an anonymous struct/union, we will check the nested
>> +     fields inside it recursively.  */
>> +      else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
>> +      if ((named_field = get_named_field (TYPE_FIELDS (TREE_TYPE (field)),
>> +                                              fieldname)) != NULL_TREE)
>> +        {
>> +          named_field = tree_cons (NULL_TREE, field, named_field);
>> +          break;
>> +        }
>> +      else
>> +        continue;
>> +      else
>> +    continue;
>> +    }
>> +  return named_field;
>> +}
> 
> Descending recursively into the field list of a struct to find an identifier 
> with a matching name.  OK.
> 
>> +
>> +
>>  /* Return a tree representing the lower bound of the array mentioned in
>>     EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
>>  diff --git a/gcc/tree.h b/gcc/tree.h
>> index 4c04245e2b1b..4859becaa1e7 100644
>> --- a/gcc/tree.h
>> +++ b/gcc/tree.h
>> @@ -5619,6 +5619,11 @@ extern tree get_base_address (tree t);
>>     of EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
>>  extern tree array_ref_element_size (tree);
>>  +/* Given a field list, FIELDLIST, of a structure/union, return the FIELD 
>> whose
>> +   name is FIELDNAME, return NULL_TREE if such field is not found.
>> +   searching nested anonymous structure/union recursively.  */
>> +extern tree get_named_field (tree, const char *);
>> +
>>  /* Return a typenode for the "standard" C type with a given name.  */
>>  extern tree get_typenode_from_name (const char *);
>>  


Reply via email to