From: Siddhesh Poyarekar <siddhesh@gotplt.org>
To: Qing Zhao <qing.zhao@oracle.com>,
joseph@codesourcery.com, richard.guenther@gmail.com,
jakub@redhat.com, gcc-patches@gcc.gnu.org
Cc: keescook@chromium.org, uecker@tugraz.at, isanbard@gmail.com
Subject: Re: [V3][PATCH 1/3] Provide counted_by attribute to flexible array member field (PR108896)
Date: Thu, 5 Oct 2023 15:31:43 -0400 [thread overview]
Message-ID: <d6753b44-e6ad-bbb5-5e84-74ccf634166c@gotplt.org> (raw)
In-Reply-To: <f65f7b9a-c3d7-fec4-b349-83b9a7c9da1a@gotplt.org>
On 2023-10-05 14:51, Siddhesh Poyarekar 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.
>
>> + /* 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...
>
>> + 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/
>
>> + 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.
>
>> +
>> + 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.
>
>> + {
>> + 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.
>
>> +
>> + DECL_ATTRIBUTES (field_decl)
>> + = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
>> + }
>> + }
>> +
>> + return;
I forgot to mention the redundant return here.
>> +}
>> /* 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...
>
>> +
>> +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.
>
>> +
>> +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.
>
>> @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.
>
>> 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 *);
>
next prev parent reply other threads:[~2023-10-05 19:31 UTC|newest]
Thread overview: 116+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-25 15:24 [V3][PATCH 0/3] New attribute "counted_by" to annotate bounds for C99 FAM(PR108896) Qing Zhao
2023-08-25 15:24 ` [V3][PATCH 1/3] Provide counted_by attribute to flexible array member field (PR108896) Qing Zhao
2023-09-08 14:12 ` Qing Zhao
2023-09-20 13:44 ` Ping * 2: " Qing Zhao
2023-10-05 18:51 ` Siddhesh Poyarekar
2023-10-05 19:31 ` Siddhesh Poyarekar [this message]
2023-10-18 14:51 ` Qing Zhao
2023-10-18 15:18 ` Siddhesh Poyarekar
2023-10-18 15:37 ` Qing Zhao
2023-10-18 14:41 ` Qing Zhao
2023-08-25 15:24 ` [V3][PATCH 2/3] Use the counted_by atribute info in builtin object size [PR108896] Qing Zhao
2023-09-08 14:12 ` Qing Zhao
2023-09-20 13:44 ` PING *2: " Qing Zhao
2023-10-05 20:01 ` Siddhesh Poyarekar
2023-10-18 20:39 ` Qing Zhao
2023-08-25 15:24 ` [V3][PATCH 3/3] Use the counted_by attribute information in bound sanitizer[PR108896] Qing Zhao
2023-09-08 14:12 ` Qing Zhao
2023-09-20 13:45 ` PING * 2: " Qing Zhao
2023-08-25 19:51 ` [V3][PATCH 0/3] New attribute "counted_by" to annotate bounds for C99 FAM(PR108896) Kees Cook
2023-09-08 14:11 ` Qing Zhao
2023-09-20 13:43 ` PING * 2: " Qing Zhao
2023-10-05 20:08 ` Siddhesh Poyarekar
2023-10-05 22:35 ` Kees Cook
2023-10-06 5:11 ` Martin Uecker
2023-10-06 10:50 ` Siddhesh Poyarekar
2023-10-06 20:01 ` Martin Uecker
2023-10-18 15:37 ` Siddhesh Poyarekar
2023-10-18 19:35 ` Qing Zhao
2023-10-18 21:11 ` Qing Zhao
2023-10-19 23:33 ` Kees Cook
2023-10-20 9:50 ` Martin Uecker
2023-10-20 18:34 ` Kees Cook
2023-10-20 18:48 ` Qing Zhao
2023-10-20 19:54 ` Martin Uecker
2023-10-23 18:17 ` Qing Zhao
2023-10-23 19:52 ` Kees Cook
2023-10-23 19:57 ` Martin Uecker
2023-10-23 22:03 ` Kees Cook
2023-10-20 17:08 ` HELP: Will the reordering happen? " Qing Zhao
2023-10-20 18:22 ` Richard Biener
2023-10-20 18:38 ` Qing Zhao
2023-10-20 19:10 ` Siddhesh Poyarekar
2023-10-20 20:41 ` Qing Zhao
2023-10-23 7:57 ` Richard Biener
2023-10-23 11:27 ` Siddhesh Poyarekar
2023-10-23 12:34 ` Richard Biener
2023-10-23 13:23 ` Siddhesh Poyarekar
2023-10-23 15:14 ` Qing Zhao
2023-10-23 14:56 ` Qing Zhao
2023-10-23 15:57 ` Richard Biener
2023-10-23 16:37 ` Qing Zhao
2023-10-23 18:06 ` Martin Uecker
2023-10-23 18:31 ` Martin Uecker
2023-10-23 19:00 ` Qing Zhao
2023-10-23 19:37 ` Martin Uecker
2023-10-23 20:33 ` Qing Zhao
2023-10-23 18:33 ` Qing Zhao
2023-10-23 18:43 ` Siddhesh Poyarekar
2023-10-23 18:55 ` Martin Uecker
2023-10-23 19:43 ` Qing Zhao
2023-10-23 22:48 ` Siddhesh Poyarekar
2023-10-24 20:30 ` Qing Zhao
2023-10-24 20:38 ` Martin Uecker
2023-10-24 21:09 ` Siddhesh Poyarekar
2023-10-24 22:51 ` Qing Zhao
2023-10-24 23:56 ` Siddhesh Poyarekar
2023-10-25 13:27 ` Qing Zhao
2023-10-25 14:50 ` Siddhesh Poyarekar
2023-10-25 15:38 ` Richard Biener
2023-10-25 19:03 ` Qing Zhao
2023-10-26 5:21 ` Jakub Jelinek
2023-10-26 8:56 ` Richard Biener
2023-10-26 14:58 ` Qing Zhao
2023-10-26 15:48 ` Richard Biener
2023-10-26 16:16 ` Martin Uecker
2023-10-26 14:41 ` Qing Zhao
2023-10-25 18:44 ` Qing Zhao
2023-10-25 22:06 ` Kees Cook
2023-10-25 22:27 ` Qing Zhao
2023-10-25 22:32 ` Kees Cook
2023-10-26 8:15 ` Martin Uecker
2023-10-26 16:13 ` Kees Cook
2023-10-26 16:45 ` Martin Uecker
2023-10-26 19:57 ` Qing Zhao
2023-10-27 7:21 ` Martin Uecker
2023-10-27 14:32 ` Qing Zhao
2023-10-27 14:53 ` Martin Uecker
2023-10-27 15:10 ` Qing Zhao
2023-10-27 17:19 ` Kees Cook
2023-10-27 18:13 ` Qing Zhao
2023-10-25 5:26 ` Martin Uecker
2023-10-25 6:43 ` Richard Biener
2023-10-25 8:16 ` Martin Uecker
2023-10-25 10:25 ` Siddhesh Poyarekar
2023-10-25 10:47 ` Martin Uecker
2023-10-25 11:13 ` Richard Biener
2023-10-25 18:16 ` Martin Uecker
2023-10-26 8:45 ` Richard Biener
2023-10-26 9:20 ` Martin Uecker
2023-10-26 10:14 ` Martin Uecker
2023-10-26 14:05 ` Richard Biener
2023-10-26 18:54 ` Qing Zhao
2023-10-27 16:43 ` Qing Zhao
2023-10-26 16:41 ` Qing Zhao
2023-10-26 17:05 ` Martin Uecker
2023-10-26 17:35 ` Richard Biener
2023-10-26 19:20 ` Qing Zhao
2023-10-25 18:17 ` Qing Zhao
2023-10-25 10:25 ` Richard Biener
2023-10-25 10:39 ` Martin Uecker
2023-10-25 18:06 ` Qing Zhao
2023-10-24 21:03 ` Siddhesh Poyarekar
2023-10-24 22:41 ` Qing Zhao
2023-10-24 23:51 ` Siddhesh Poyarekar
2023-10-25 21:59 ` Kees Cook
2023-10-23 18:10 ` Joseph Myers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d6753b44-e6ad-bbb5-5e84-74ccf634166c@gotplt.org \
--to=siddhesh@gotplt.org \
--cc=gcc-patches@gcc.gnu.org \
--cc=isanbard@gmail.com \
--cc=jakub@redhat.com \
--cc=joseph@codesourcery.com \
--cc=keescook@chromium.org \
--cc=qing.zhao@oracle.com \
--cc=richard.guenther@gmail.com \
--cc=uecker@tugraz.at \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).