https://gcc.gnu.org/g:9a17e6d03c6ed53e3b2dfd2c3ff9b1066ffa97b9

commit r15-4122-g9a17e6d03c6ed53e3b2dfd2c3ff9b1066ffa97b9
Author: qing zhao <qing.z...@oracle.com>
Date:   Mon Sep 30 18:29:29 2024 +0000

    c: ICE in build_counted_by_ref [PR116735]
    
    When handling the counted_by attribute, if the corresponding field
    doesn't exit, in additiion to issue error, we should also remove
    the already added non-existing "counted_by" attribute from the
    field_decl.
    
            PR c/116735
    
    gcc/c/ChangeLog:
    
            * c-decl.cc (verify_counted_by_attribute): Remove the attribute
            when error.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/flex-array-counted-by-9.c: New test.

Diff:
---
 gcc/c/c-decl.cc                                | 32 +++++++++++++++-----------
 gcc/testsuite/gcc.dg/flex-array-counted-by-9.c | 25 ++++++++++++++++++++
 2 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index aa7f69d1b7bc..224c015cd6df 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9502,14 +9502,17 @@ verify_counted_by_attribute (tree struct_type, tree 
field_decl)
 
   tree counted_by_field = lookup_field (struct_type, fieldname);
 
-  /* Error when the field is not found in the containing structure.  */
+  /* Error when the field is not found in the containing structure and
+     remove the corresponding counted_by attribute from the field_decl.  */
   if (!counted_by_field)
-    error_at (DECL_SOURCE_LOCATION (field_decl),
-             "argument %qE to the %qE attribute is not a field declaration"
-             " in the same structure as %qD", fieldname,
-             (get_attribute_name (attr_counted_by)),
-             field_decl);
-
+    {
+      error_at (DECL_SOURCE_LOCATION (field_decl),
+               "argument %qE to the %<counted_by%> attribute"
+               " is not a field declaration in the same structure"
+               " as %qD", fieldname, field_decl);
+      DECL_ATTRIBUTES (field_decl)
+       = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
+    }
   else
   /* Error when the field is not with an integer type.  */
     {
@@ -9518,14 +9521,15 @@ verify_counted_by_attribute (tree struct_type, tree 
field_decl)
       tree real_field = TREE_VALUE (counted_by_field);
 
       if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field)))
-       error_at (DECL_SOURCE_LOCATION (field_decl),
-                 "argument %qE to the %qE attribute is not a field declaration"
-                 " with an integer type", fieldname,
-                 (get_attribute_name (attr_counted_by)));
-
+       {
+         error_at (DECL_SOURCE_LOCATION (field_decl),
+                   "argument %qE to the %<counted_by%> attribute"
+                   " is not a field declaration with an integer type",
+                   fieldname);
+         DECL_ATTRIBUTES (field_decl)
+           = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl));
+       }
     }
-
-  return;
 }
 
 /* TYPE is a struct or union that we're applying may_alias to after the body is
diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-9.c 
b/gcc/testsuite/gcc.dg/flex-array-counted-by-9.c
new file mode 100644
index 000000000000..5c6fedd0d3d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-9.c
@@ -0,0 +1,25 @@
+/* PR c/116735  */
+/* { dg-options "-std=c99" } */
+/* { dg-do compile } */
+
+struct foo {
+  int len;
+  int element[] __attribute__ ((__counted_by__ (lenx))); /* { dg-error 
"attribute is not a field declaration in the same structure as" } */
+};
+
+struct bar {
+  float count;
+  int array[] __attribute ((counted_by (count))); /* { dg-error "attribute is 
not a field declaration with an integer type" } */
+};
+
+int main ()
+{
+  struct foo *p = __builtin_malloc (sizeof (struct foo) + 3 * sizeof (int));
+  struct bar *q = __builtin_malloc (sizeof (struct bar) + 3 * sizeof (int));
+  p->len = 3;
+  p->element[0] = 17;
+  p->element[1] = 13;
+  q->array[0] = 13;
+  q->array[2] = 17;
+  return 0;
+}

Reply via email to