[gcc r15-208] Allow flexible array members in unions and alone in structures [PR53548]

2024-05-06 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:adb1c8a0f167c3a1f7593d75f5a10eb07a5d741a

commit r15-208-gadb1c8a0f167c3a1f7593d75f5a10eb07a5d741a
Author: Qing Zhao 
Date:   Mon May 6 16:25:04 2024 +

Allow flexible array members in unions and alone in structures [PR53548]

The request for GCC to accept that the C99 flexible array member can be
in a union or alone in a structure has been made a long time ago around 2012
for supporting several practical cases including glibc.

A GCC PR has been opened for such request at that time:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53548

However, this PR was closed as WONTFIX around 2015 due to the following 
reason:

"there is an existing extension that makes the requested functionality 
possible"
i.e GCC fully supported that the zero-length array can be in a union or 
alone
in a structure for a long time. (though I didn't see any official 
documentation
on such extension)

It's reasonable to close PR53548 at that time since zero-length array 
extension
can be used for such purpose.

However, since GCC13, in order to improve the C/C++ security, we introduced
-fstrict-flex-arrays=n to gradually eliminate the "fake flexible array"
usages from C/C++ source code. As a result, zero-length arrays eventually
will be replaced by C99 flexiable array member completely.

Therefore, GCC needs to explicitly allow such extensions directly for C99
flexible arrays, since flexable array member in unions or alone in structs
are common code patterns in active use by the Linux kernel (and other 
projects).

For example, these do not error by default with GCC:

union one {
  int a;
  int b[0];
};

union two {
  int a;
  struct {
struct { } __empty;
int b[];
  };
};

But these do:

union three {
  int a;
  int b[];
};

struct four {
  int b[];
}

Clang has supported such extensions since March, 2024
https://github.com/llvm/llvm-project/pull/84428

GCC should also support such extensions. This will allow for
a seamless transition for code bases away from zero-length arrays without
losing existing code patterns.

gcc/ChangeLog:

PR c/53548
* doc/extend.texi: Add documentation for Flexible Array Members in
Unions and Flexible Array Members alone in Structures.

Diff:
---
 gcc/doc/extend.texi | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e290265d68d..267fccd1512 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -42,6 +42,8 @@ extensions, accepted by GCC in C90 mode and in C++.
 * Named Address Spaces::Named address spaces.
 * Zero Length:: Zero-length arrays.
 * Empty Structures::Structures with no members.
+* Flexible Array Members in Unions::  Unions with Flexible Array Members.
+* Flexible Array Members alone in Structures::  Structures with only Flexible 
Array Members.
 * Variable Length:: Arrays whose length is computed at run time.
 * Variadic Macros:: Macros with a variable number of arguments.
 * Escaped Newlines::Slightly looser rules for escaped newlines.
@@ -1873,6 +1875,38 @@ The structure has size zero.  In C++, empty structures 
are part
 of the language.  G++ treats empty structures as if they had a single
 member of type @code{char}.
 
+@node Flexible Array Members in Unions
+@section Unions with Flexible Array Members
+@cindex unions with flexible array members
+@cindex unions with FAMs
+
+GCC permits a C99 flexible array member (FAM) to be in a union:
+
+@smallexample
+union with_fam @{
+  int a;
+  int b[];
+@};
+@end smallexample
+
+If every member of a union is a flexible array member, the size of
+such a union is zero.
+
+@node Flexible Array Members alone in Structures
+@section Structures with only Flexible Array Members
+@cindex structures with only flexible array members
+@cindex structures with only FAMs
+
+GCC permits a C99 flexible array member (FAM) to be alone in a structure:
+
+@smallexample
+struct only_fam @{
+  int b[];
+@};
+@end smallexample
+
+The size of such a structure is zero.
+
 @node Variable Length
 @section Arrays of Variable Length
 @cindex variable-length arrays


[gcc r15-209] C and C++ FE changes to support flexible array members in unions and alone in structures. Adjust tes

2024-05-06 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:f27fc59d9f7c735d200fda647a487850144b10eb

commit r15-209-gf27fc59d9f7c735d200fda647a487850144b10eb
Author: Qing Zhao 
Date:   Mon May 6 16:26:19 2024 +

C and C++ FE changes to support flexible array members in unions and alone 
in structures. Adjust testcases for flexible array member in union and alone in 
structure extension.

PR c/53548

gcc/c/ChangeLog:

PR c/53548
* c-decl.cc (finish_struct): Change errors to pedwarns for the cases
flexible array members in union or alone in structures.

gcc/cp/ChangeLog:

PR c/53548
* class.cc (diagnose_flexarrays): Change error to pdewarn for the 
case
flexible array members alone in structures.
* decl.cc (grokdeclarator): Change error to pdewarn for the case
flexible array members in unions.

gcc/ChangeLog:

PR c/53548
* stor-layout.cc (place_union_field): Use zero sizes for flexible 
array
member fields.

gcc/testsuite/ChangeLog:

PR c/53548
* c-c++-common/builtin-clear-padding-3.c: Adjust testcase.
* g++.dg/ext/flexary12.C: Likewise.
* g++.dg/ext/flexary19.C: Likewise.
* g++.dg/ext/flexary2.C: Likewise.
* g++.dg/ext/flexary3.C: Likewise.
* g++.dg/ext/flexary36.C: Likewise.
* g++.dg/ext/flexary4.C: Likewise.
* g++.dg/ext/flexary5.C: Likewise.
* g++.dg/ext/flexary8.C: Likewise.
* g++.dg/torture/pr64280.C: Likewise.
* gcc.dg/20050620-1.c: Likewise.
* gcc.dg/940510-1.c: Likewise.

Diff:
---
 gcc/c/c-decl.cc| 16 ++-
 gcc/cp/class.cc| 11 +++--
 gcc/cp/decl.cc |  7 ++-
 gcc/stor-layout.cc |  9 +++-
 .../c-c++-common/builtin-clear-padding-3.c | 10 ++--
 gcc/testsuite/g++.dg/ext/flexary12.C   |  6 +--
 gcc/testsuite/g++.dg/ext/flexary19.C   | 42 -
 gcc/testsuite/g++.dg/ext/flexary2.C|  2 +-
 gcc/testsuite/g++.dg/ext/flexary3.C|  2 +-
 gcc/testsuite/g++.dg/ext/flexary36.C   |  2 +-
 gcc/testsuite/g++.dg/ext/flexary4.C| 54 +++---
 gcc/testsuite/g++.dg/ext/flexary5.C|  4 +-
 gcc/testsuite/g++.dg/ext/flexary8.C|  8 ++--
 gcc/testsuite/g++.dg/torture/pr64280.C |  2 +-
 gcc/testsuite/gcc.dg/20050620-1.c  |  2 +-
 gcc/testsuite/gcc.dg/940510-1.c|  4 +-
 16 files changed, 91 insertions(+), 90 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 52af8f32998..9ef2ab25773 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9516,11 +9516,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   if (flexible_array_member_type_p (TREE_TYPE (x)))
{
  if (TREE_CODE (t) == UNION_TYPE)
-   {
- error_at (DECL_SOURCE_LOCATION (x),
-   "flexible array member in union");
- TREE_TYPE (x) = error_mark_node;
-   }
+   pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+"flexible array member in union is a GCC extension");
  else if (!is_last_field)
{
  error_at (DECL_SOURCE_LOCATION (x),
@@ -9528,12 +9525,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
  TREE_TYPE (x) = error_mark_node;
}
  else if (!saw_named_field)
-   {
- error_at (DECL_SOURCE_LOCATION (x),
-   "flexible array member in a struct with no named "
-   "members");
- TREE_TYPE (x) = error_mark_node;
-   }
+   pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+"flexible array member in a struct with no named "
+"members is a GCC extension");
}
 
   if (pedantic && TREE_CODE (t) == RECORD_TYPE
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 5ef7c71af61..0ce361eb88e 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -7624,6 +7624,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
   bool diagd = false;
 
   const char *msg = 0;
+  const char *msg_fam = 0;
 
   if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
 {
@@ -7649,15 +7650,19 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
   if (fmem->after[0])
msg = G_("flexible array member %qD not at end of %q#T");
   else if (!fmem->first)
-   msg = G_("flexible array member %qD in an otherwise empty %q#T");
+   msg_fam = G_("flexible array member %qD in an otherwise"
+" empty %q#T is a GCC extension");
 
-  if (msg)
+  if (msg || msg_f

[gcc r15-210] Add testing cases for flexible array members in unions and alone in structures.

2024-05-06 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:93f6a47583f3fa8a1b66856ecb19ec28f26b2ba4

commit r15-210-g93f6a47583f3fa8a1b66856ecb19ec28f26b2ba4
Author: Qing Zhao 
Date:   Mon May 6 16:27:09 2024 +

Add testing cases for flexible array members in unions and alone in 
structures.

PR c/53548

gcc/testsuite/ChangeLog:

PR c/53548
* c-c++-common/fam-in-union-alone-in-struct-1.c: New testcase.
* c-c++-common/fam-in-union-alone-in-struct-2.c: New testcase.
* c-c++-common/fam-in-union-alone-in-struct-3.c: New testcase.

Diff:
---
 .../c-c++-common/fam-in-union-alone-in-struct-1.c  | 52 ++
 .../c-c++-common/fam-in-union-alone-in-struct-2.c  | 51 +
 .../c-c++-common/fam-in-union-alone-in-struct-3.c  | 36 +++
 3 files changed, 139 insertions(+)

diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
new file mode 100644
index 000..7d4721aa95a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
@@ -0,0 +1,52 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures.  */
+/* { dg-do run} */
+/* { dg-options "-Wpedantic" } */
+
+union with_fam_1 {
+  int a;
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+union with_fam_2 {
+  char a;
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+union with_fam_3 {
+  char a[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-1 } */
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+struct only_fam {
+  int b[];
+  /* { dg-warning "in a struct with no named members" "" { target c } .-1 } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-2 } */
+  /* { dg-warning "forbids flexible array member" "" { target c++ } .-3 } */
+};
+
+struct only_fam_2 {
+  unsigned int : 2;
+  unsigned int : 3;
+  int b[];
+  /* { dg-warning "in a struct with no named members" "" { target c } .-1 } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-2 } */
+  /* { dg-warning "forbids flexible array member" "" { target c++ } .-3 } */
+};
+
+int main ()
+{
+  if (sizeof (union with_fam_1) != sizeof (int))
+__builtin_abort ();
+  if (sizeof (union with_fam_2) != __alignof__ (int))
+__builtin_abort ();
+  if (sizeof (union with_fam_3) != 0)
+__builtin_abort ();
+  if (sizeof (struct only_fam) != 0)
+__builtin_abort ();
+  if (sizeof (struct only_fam_2) != sizeof (int))
+__builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
new file mode 100644
index 000..3743f9e7dac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
@@ -0,0 +1,51 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures: initialization  */
+/* { dg-do run} */
+/* { dg-options "-O2" } */
+
+union with_fam_1 {
+  int a;
+  int b[]; 
+} with_fam_1_v = {.b = {1, 2, 3, 4}};
+
+union with_fam_2 {
+  int a;
+  char b[];  
+} with_fam_2_v = {.a = 0x1f2f3f4f};
+
+union with_fam_3 {
+  char a[];  
+  int b[];  
+} with_fam_3_v = {.b = {0x1f2f3f4f, 0x5f6f7f7f}};
+
+struct only_fam {
+  int b[]; 
+} only_fam_v = {{7, 11}};
+
+struct only_fam_2 {
+  unsigned int : 2;
+  unsigned int : 3;
+  int b[]; 
+} only_fam_2_v = {{7, 11}};
+
+int main ()
+{
+  if (with_fam_1_v.b[3] != 4
+  || with_fam_1_v.b[0] != 1)
+__builtin_abort ();
+  if (with_fam_2_v.b[3] != 0x1f
+  || with_fam_2_v.b[0] != 0x4f)
+__builtin_abort ();
+  if (with_fam_3_v.a[0] != 0x4f
+  || with_fam_3_v.a[7] != 0x5f)
+__builtin_abort ();
+  if (only_fam_v.b[0] != 7
+  || only_fam_v.b[1] != 11)
+__builtin_abort ();
+  if (only_fam_2_v.b[0] != 7
+  || only_fam_2_v.b[1] != 11)
+__builtin_abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c
new file mode 100644
index 000..dd36fa01306
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c
@@ -0,0 +1,36 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures.  */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+union with_fam_1 {
+  int a;
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};
+
+union with_fam_2 {
+  char a;
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};
+
+union with_fam_3 {
+  char a[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+  /* { dg-error "in an otherwise empty" 

[gcc r15-211] Update the C FE routine "add_flexible_array_elts_to_size" C++ FE routine "layout_var_decl" to handle

2024-05-06 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:6634a409124a884ff66b3756568a7daae7d3c295

commit r15-211-g6634a409124a884ff66b3756568a7daae7d3c295
Author: Qing Zhao 
Date:   Mon May 6 16:28:01 2024 +

Update the C FE routine "add_flexible_array_elts_to_size" C++ FE routine 
"layout_var_decl" to handle the cases when the DECL is union.

PR c/53548

Add testing cases to test the _bos for flexible array members in unions
or alone in structures.

gcc/c/ChangeLog:

PR c/53548
* c-decl.cc (add_flexible_array_elts_to_size): Handle the cases
when the DECL is union.

gcc/cp/ChangeLog:

PR c/53548
* decl.cc (layout_var_decl): Handle the cases when the DECL is
union with a flexible array member initializer.

gcc/testsuite/ChangeLog:

PR c/53548
* c-c++-common/fam-in-union-alone-in-struct-bos-1.c: New test.
* c-c++-common/fam-in-union-alone-in-struct-bos.c: New test.

Diff:
---
 gcc/c/c-decl.cc| 29 --
 gcc/cp/decl.cc | 32 ---
 .../fam-in-union-alone-in-struct-bos-1.c   | 66 ++
 .../fam-in-union-alone-in-struct-bos.c | 45 +++
 4 files changed, 159 insertions(+), 13 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 9ef2ab25773..b691b91b3db 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5339,8 +5339,9 @@ zero_length_array_type_p (const_tree type)
 }
 
 /* INIT is a constructor that forms DECL's initializer.  If the final
-   element initializes a flexible array field, add the size of that
-   initializer to DECL's size.  */
+   element initializes a flexible array field, adjust the size of the
+   DECL with the initializer based on whether the DECL is a union or
+   a structure.  */
 
 static void
 add_flexible_array_elts_to_size (tree decl, tree init)
@@ -5355,10 +5356,26 @@ add_flexible_array_elts_to_size (tree decl, tree init)
   if (flexible_array_member_type_p (type))
 {
   complete_array_type (&type, elt, false);
-  DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
-  DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+  /* For a structure, add the size of the initializer to the DECL's
+size.  */
+  if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
+  /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+  else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
 }
 }
 
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index e8622e22a4c..04a151c341c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6563,8 +6563,9 @@ layout_var_decl (tree decl)
}
 }
 
-  /* If the final element initializes a flexible array field, add the size of
- that initializer to DECL's size.  */
+  /* If the final element initializes a flexible array field, adjust
+ the size of the DECL with the initializer based on whether the
+ DECL is a union or a structure.  */
   if (type != error_mark_node
   && DECL_INITIAL (decl)
   && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
@@ -6585,11 +6586,28 @@ layout_var_decl (tree decl)
  && TREE_CODE (vtype) == ARRAY_TYPE
  && COMPLETE_TYPE_P (vtype))
{
- DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
- DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
- TYPE_SIZE_UNIT (vtype));
+ /* For a structure, add the size of the initializer to the DECL's
+size.  */
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+   }
+ /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+ else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (

[gcc r15-3434] Explicitly document that the "counted_by" attribute is only supported in C.

2024-09-03 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:f9642ffe7814396f31203f4366f78a43a01a215c

commit r15-3434-gf9642ffe7814396f31203f4366f78a43a01a215c
Author: Qing Zhao 
Date:   Tue Sep 3 19:28:23 2024 +

Explicitly document that the "counted_by" attribute is only supported in C.

The "counted_by" attribute currently is only supported in C, mention this
explicitly in documentation and also issue warnings when see "counted_by"
attribute in C++ with -Wattributes.

gcc/c-family/ChangeLog:

* c-attribs.cc (handle_counted_by_attribute): Is ignored and issues
warning with -Wattributes in C++ for now.

gcc/ChangeLog:

* doc/extend.texi: Explicitly mentions counted_by is available
only in C for now.

gcc/testsuite/ChangeLog:

* g++.dg/ext/flex-array-counted-by.C: New test.
* g++.dg/ext/flex-array-counted-by-2.C: New test.

Diff:
---
 gcc/c-family/c-attribs.cc  | 10 +-
 gcc/doc/extend.texi|  4 
 gcc/testsuite/g++.dg/ext/flex-array-counted-by-2.C | 13 +
 gcc/testsuite/g++.dg/ext/flex-array-counted-by.C   | 11 +++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index cf27cd6d5212..79303518dcb7 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -2867,8 +2867,16 @@ handle_counted_by_attribute (tree *node, tree name,
   tree argval = TREE_VALUE (args);
   tree old_counted_by = lookup_attribute ("counted_by", DECL_ATTRIBUTES 
(decl));
 
+  /* This attribute is not supported in C++.  */
+  if (c_dialect_cxx ())
+{
+  warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "%qE attribute is not supported for C++ for now, ignored",
+ name);
+  *no_add_attrs = true;
+}
   /* This attribute only applies to field decls of a structure.  */
-  if (TREE_CODE (decl) != FIELD_DECL)
+  else if (TREE_CODE (decl) != FIELD_DECL)
 {
   error_at (DECL_SOURCE_LOCATION (decl),
"%qE attribute is not allowed for a non-field"
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 5845bcedf6e5..ebfa6779becb 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7926,6 +7926,10 @@ The @code{counted_by} attribute may be attached to the 
C99 flexible array
 member of a structure.  It indicates that the number of the elements of the
 array is given by the field "@var{count}" in the same structure as the
 flexible array member.
+
+This attribute is available only in C for now.
+In C++ this attribute is ignored.
+
 GCC may use this information to improve detection of object size information
 for such structures and provide better results in compile-time diagnostics
 and runtime features like the array bound sanitizer and
diff --git a/gcc/testsuite/g++.dg/ext/flex-array-counted-by-2.C 
b/gcc/testsuite/g++.dg/ext/flex-array-counted-by-2.C
new file mode 100644
index ..6ac2b509b687
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flex-array-counted-by-2.C
@@ -0,0 +1,13 @@
+/* Testing the fact that the attribute counted_by is not supported in C++.  */
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-Wattributes" } */
+
+struct trailing {
+  int count;
+  int field [[gnu::counted_by (count)]] []; /* { dg-warning "attribute is not 
supported for C\\+\\+ for now, ignored" } */
+};
+
+struct trailing1 {
+  int count1;
+  [[gnu::counted_by (count)]] int field []; /* { dg-warning "attribute is not 
supported for C\\+\\+ for now, ignored" } */
+};
diff --git a/gcc/testsuite/g++.dg/ext/flex-array-counted-by.C 
b/gcc/testsuite/g++.dg/ext/flex-array-counted-by.C
new file mode 100644
index ..8bc79d459dfc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flex-array-counted-by.C
@@ -0,0 +1,11 @@
+/* Testing the fact that the attribute counted_by is not supported in C++.  */
+/* { dg-do compile } */
+/* { dg-options "-Wattributes" } */
+
+int size;
+int x __attribute ((counted_by (size))); /* { dg-warning "attribute is not 
supported for C\\+\\+ for now, ignored" } */
+
+struct trailing {
+  int count;
+  int field[] __attribute ((counted_by (count))); /* { dg-warning "attribute 
is not supported for C\\+\\+ for now, ignored" } */
+};


[gcc r13-8556] Fix SSA corruption due to widening_mul opt on conflict across an abnormal edge [PR111407]

2024-04-02 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:2d9a9488e26233eb9497722fa9ccb88258f7402c

commit r13-8556-g2d9a9488e26233eb9497722fa9ccb88258f7402c
Author: Qing Zhao 
Date:   Thu Feb 29 15:07:49 2024 +

Fix SSA corruption due to widening_mul opt on conflict across an abnormal 
edge [PR111407]

This is a bug in tree-ssa-math-opts.cc, when applying the widening mul
optimization, the compiler needs to check whether the operand is in a
ABNORMAL PHI, if YES, we should avoid the transformation.

PR tree-optimization/111407

gcc/ChangeLog:

* tree-ssa-math-opts.cc (convert_mult_to_widen): Avoid the transform
when one of the operands is subject to abnormal coalescing.

gcc/testsuite/ChangeLog:

* gcc.dg/pr111407.c: New test.

(cherry picked from commit 4aca1cfd6235090e48a53dab734437740671bbf3)

Diff:
---
 gcc/testsuite/gcc.dg/pr111407.c | 21 +
 gcc/tree-ssa-math-opts.cc   |  8 
 2 files changed, 29 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr111407.c b/gcc/testsuite/gcc.dg/pr111407.c
new file mode 100644
index 000..a171074753f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111407.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/111407*/
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+enum { SEND_TOFILE } __sigsetjmp();
+void fclose();
+void foldergets();
+void sendpart_stats(int *p1, int a1, int b1) {
+ int *a = p1;
+ fclose();
+ p1 = 0;
+ long t = b1;
+ if (__sigsetjmp()) {
+   {
+ long t1 = a1;
+ a1+=1;
+ fclose(a1*(long)t1);
+   }
+ }
+ if (p1)
+   fclose();
+}
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index 15eed3e960c..ff949e4fec9 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -2754,6 +2754,14 @@ convert_mult_to_widen (gimple *stmt, 
gimple_stmt_iterator *gsi)
   if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
 return false;
 
+  /* if any one of rhs1 and rhs2 is subject to abnormal coalescing,
+ avoid the tranform. */
+  if ((TREE_CODE (rhs1) == SSA_NAME
+   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
+  || (TREE_CODE (rhs2) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs2)))
+return false;
+
   to_mode = SCALAR_INT_TYPE_MODE (type);
   from_mode = SCALAR_INT_TYPE_MODE (type1);
   if (to_mode == from_mode)


[gcc r12-10306] Fix SSA corruption due to widening_mul opt on conflict across an abnormal edge [PR111407]

2024-04-02 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:5f23f9f141c4b52e8f4a9aadc88b8155cf1959a3

commit r12-10306-g5f23f9f141c4b52e8f4a9aadc88b8155cf1959a3
Author: Qing Zhao 
Date:   Thu Feb 29 15:07:49 2024 +

Fix SSA corruption due to widening_mul opt on conflict across an abnormal 
edge [PR111407]

This is a bug in tree-ssa-math-opts.cc, when applying the widening mul
optimization, the compiler needs to check whether the operand is in a
ABNORMAL PHI, if YES, we should avoid the transformation.

PR tree-optimization/111407

gcc/ChangeLog:

* tree-ssa-math-opts.cc (convert_mult_to_widen): Avoid the transform
when one of the operands is subject to abnormal coalescing.

gcc/testsuite/ChangeLog:

* gcc.dg/pr111407.c: New test.

(cherry picked from commit 4aca1cfd6235090e48a53dab734437740671bbf3)

Diff:
---
 gcc/testsuite/gcc.dg/pr111407.c | 21 +
 gcc/tree-ssa-math-opts.cc   |  8 
 2 files changed, 29 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr111407.c b/gcc/testsuite/gcc.dg/pr111407.c
new file mode 100644
index 000..a171074753f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111407.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/111407*/
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+enum { SEND_TOFILE } __sigsetjmp();
+void fclose();
+void foldergets();
+void sendpart_stats(int *p1, int a1, int b1) {
+ int *a = p1;
+ fclose();
+ p1 = 0;
+ long t = b1;
+ if (__sigsetjmp()) {
+   {
+ long t1 = a1;
+ a1+=1;
+ fclose(a1*(long)t1);
+   }
+ }
+ if (p1)
+   fclose();
+}
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index 232e903b0d2..bab0cc5aef4 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -2681,6 +2681,14 @@ convert_mult_to_widen (gimple *stmt, 
gimple_stmt_iterator *gsi)
   if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
 return false;
 
+  /* if any one of rhs1 and rhs2 is subject to abnormal coalescing,
+ avoid the tranform. */
+  if ((TREE_CODE (rhs1) == SSA_NAME
+   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
+  || (TREE_CODE (rhs2) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs2)))
+return false;
+
   to_mode = SCALAR_INT_TYPE_MODE (type);
   from_mode = SCALAR_INT_TYPE_MODE (type1);
   if (to_mode == from_mode)


[gcc r11-11306] Fix SSA corruption due to widening_mul opt on conflict across an abnormal edge [PR111407]

2024-04-02 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:4de35949e462d89926a171cd1ef7b6f40a308dab

commit r11-11306-g4de35949e462d89926a171cd1ef7b6f40a308dab
Author: Qing Zhao 
Date:   Mon Mar 25 14:17:56 2024 +

Fix SSA corruption due to widening_mul opt on conflict across an abnormal 
edge [PR111407]

This is a bug in tree-ssa-math-opts.c, when applying the widening mul
optimization, the compiler needs to check whether the operand is in a
ABNORMAL PHI, if YES, we should avoid the transformation.

PR tree-optimization/111407

gcc/ChangeLog:

* tree-ssa-math-opts.c (convert_mult_to_widen): Avoid the transform
when one of the operands is subject to abnormal coalescing.

gcc/testsuite/ChangeLog:

* gcc.dg/pr111407.c: New test.

(cherry picked from commit 4aca1cfd6235090e48a53dab734437740671bbf3)

Diff:
---
 gcc/testsuite/gcc.dg/pr111407.c | 21 +
 gcc/tree-ssa-math-opts.c|  8 
 2 files changed, 29 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/pr111407.c b/gcc/testsuite/gcc.dg/pr111407.c
new file mode 100644
index 000..a171074753f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111407.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/111407*/
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+enum { SEND_TOFILE } __sigsetjmp();
+void fclose();
+void foldergets();
+void sendpart_stats(int *p1, int a1, int b1) {
+ int *a = p1;
+ fclose();
+ p1 = 0;
+ long t = b1;
+ if (__sigsetjmp()) {
+   {
+ long t1 = a1;
+ a1+=1;
+ fclose(a1*(long)t1);
+   }
+ }
+ if (p1)
+   fclose();
+}
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index adeb70fd635..dcaf272d73f 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -2678,6 +2678,14 @@ convert_mult_to_widen (gimple *stmt, 
gimple_stmt_iterator *gsi)
   if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
 return false;
 
+  /* if any one of rhs1 and rhs2 is subject to abnormal coalescing,
+ avoid the tranform. */
+  if ((TREE_CODE (rhs1) == SSA_NAME
+   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
+  || (TREE_CODE (rhs2) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs2)))
+return false;
+
   to_mode = SCALAR_INT_TYPE_MODE (type);
   from_mode = SCALAR_INT_TYPE_MODE (type1);
   if (to_mode == from_mode)


[gcc r15-944] Provide counted_by attribute to flexible array member field

2024-05-31 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:f824acd0e807546a733c122ab6340f18cef88766

commit r15-944-gf824acd0e807546a733c122ab6340f18cef88766
Author: Qing Zhao 
Date:   Tue May 28 18:30:05 2024 +

Provide counted_by attribute to flexible array member field

'counted_by (COUNT)'
 The 'counted_by' attribute may be attached to the C99 flexible
 array member of a structure.  It indicates that the number of the
 elements of the array is given by the field "COUNT" in the
 same structure as the flexible array member.
 GCC may use this information to improve detection of object size 
information
 for such structures and provide better results in compile-time 
diagnostics
 and runtime features like 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.  Otherwise, the compiler reports an error and
 ignores the attribute.

 When the field that represents the number of the elements is assigned a
 negative integer value, the compiler treats the value as zero.

 An explicit 'counted_by' annotation defines a relationship between
 two objects, 'p->array' and 'p->count', and there are the following
 requirementthat on the relationship between this pair:

* 'p->count' must be initialized before the first reference to
  'p->array';

* 'p->array' has _at least_ 'p->count' number of elements
  available all the time.  This relationship must hold even
  after any of these related objects are updated during the
  program.

 It's the user's responsibility to make sure the above requirements
 to be kept all the time.  Otherwise the compiler reports
 warnings, at the same time, the results of the array bound
 sanitizer and the '__builtin_dynamic_object_size' is undefined.

 One important feature of the attribute is, a reference to the
 flexible array member field uses the latest value assigned to
 the field that represents the number of the elements before that
 reference.  For example,

p->count = val1;
p->array[20] = 0;  // ref1 to p->array
p->count = val2;
p->array[30] = 0;  // ref2 to p->array

 in the above, 'ref1' uses 'val1' as the number of the elements
 in 'p->array', and 'ref2' uses 'val2' as the number of elements
 in 'p->array'.

gcc/c-family/ChangeLog:

* 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:

* 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.
* c-tree.h (lookup_field): New prototype.
* c-typeck.cc (lookup_field): Expose as extern function.
(tagged_types_tu_compatible_p): Check counted_by attribute for
structure type.

gcc/ChangeLog:

* doc/extend.texi: Document attribute counted_by.

gcc/testsuite/ChangeLog:

* gcc.dg/flex-array-counted-by.c: New test.
* gcc.dg/flex-array-counted-by-7.c: New test.
* gcc.dg/flex-array-counted-by-8.c: New test.

Diff:
---
 gcc/c-family/c-attribs.cc  |  68 -
 gcc/c-family/c-common.cc   |  13 +++
 gcc/c-family/c-common.h|   1 +
 gcc/c/c-decl.cc|  80 
 gcc/c/c-tree.h |   1 +
 gcc/c/c-typeck.cc  |  37 ++-
 gcc/doc/extend.texi|  68 +
 gcc/testsuite/gcc.dg/flex-array-counted-by-7.c |   8 ++
 gcc/testsuite/gcc.dg/flex-array-counted-by-8.c | 127 +
 gcc/testsuite/gcc.dg/flex-array-counted-by.c   |  62 
 10 files changed, 444 insertions(+), 21 deletions(-)

diff --git a/g

[gcc r15-945] Convert references with "counted_by" attributes to/from .ACCESS_WITH_SIZE.

2024-05-31 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:bb49b6e4f55891d0d8b596845118f40df6ae72a5

commit r15-945-gbb49b6e4f55891d0d8b596845118f40df6ae72a5
Author: Qing Zhao 
Date:   Tue May 28 18:34:09 2024 +

Convert references with "counted_by" attributes to/from .ACCESS_WITH_SIZE.

Including the following changes:
* The definition of the new internal function .ACCESS_WITH_SIZE
  in internal-fn.def.
* C FE converts every reference to a FAM with a "counted_by" attribute
  to a call to the internal function .ACCESS_WITH_SIZE.
  (build_component_ref in c_typeck.cc)

  This includes the case when the object is statically allocated and
  initialized.
  In order to make this working, the routine digest_init in c-typeck.cc
  is updated to fold calls to .ACCESS_WITH_SIZE to its first argument
  when require_constant is TRUE.

  However, for the reference inside "offsetof", the "counted_by" attribute 
is
  ignored since it's not useful at all.
  (c_parser_postfix_expression in c/c-parser.cc)

  In addtion to "offsetof", for the reference inside operator "typeof" and
  "alignof", we ignore counted_by attribute too.

  When building ADDR_EXPR for the .ACCESS_WITH_SIZE in C FE,
  replace the call with its first argument.

* Convert every call to .ACCESS_WITH_SIZE to its first argument.
  (expand_ACCESS_WITH_SIZE in internal-fn.cc)
* Provide the utility routines to check the call is .ACCESS_WITH_SIZE and
  get the reference from the call to .ACCESS_WITH_SIZE.
  (is_access_with_size_p and get_ref_from_access_with_size in tree.cc)

gcc/c/ChangeLog:

* c-parser.cc (c_parser_postfix_expression): Ignore the counted-by
attribute when build_component_ref inside offsetof operator.
* c-tree.h (build_component_ref): Add one more parameter.
* c-typeck.cc (build_counted_by_ref): New function.
(build_access_with_size_for_counted_by): New function.
(build_component_ref): Check the counted-by attribute and build
call to .ACCESS_WITH_SIZE.
(build_unary_op): When building ADDR_EXPR for
.ACCESS_WITH_SIZE, use its first argument.
(lvalue_p): Accept call to .ACCESS_WITH_SIZE.
(digest_init): Fold call to .ACCESS_WITH_SIZE to its first
argument when require_constant is TRUE.

gcc/ChangeLog:

* internal-fn.cc (expand_ACCESS_WITH_SIZE): New function.
* internal-fn.def (ACCESS_WITH_SIZE): New internal function.
* tree.cc (is_access_with_size_p): New function.
(get_ref_from_access_with_size): New function.
* tree.h (is_access_with_size_p): New prototype.
(get_ref_from_access_with_size): New prototype.

gcc/testsuite/ChangeLog:

* gcc.dg/flex-array-counted-by-2.c: New test.

Diff:
---
 gcc/c/c-parser.cc  |  10 +-
 gcc/c/c-tree.h |   2 +-
 gcc/c/c-typeck.cc  | 142 -
 gcc/internal-fn.cc |  34 ++
 gcc/internal-fn.def|   5 +
 gcc/testsuite/gcc.dg/flex-array-counted-by-2.c | 112 +++
 gcc/tree.cc|  22 
 gcc/tree.h |   8 ++
 8 files changed, 328 insertions(+), 7 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 00f8bf4376e..2d9e9c0969f 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -10848,9 +10848,12 @@ c_parser_postfix_expression (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_NAME))
  {
c_token *comp_tok = c_parser_peek_token (parser);
+   /* Ignore the counted_by attribute for reference inside
+  offsetof since the information is not useful at all.  */
offsetof_ref
  = build_component_ref (loc, offsetof_ref, comp_tok->value,
-comp_tok->location, UNKNOWN_LOCATION);
+comp_tok->location, UNKNOWN_LOCATION,
+false);
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_DOT)
   || c_parser_next_token_is (parser,
@@ -10877,11 +10880,14 @@ c_parser_postfix_expression (c_parser *parser)
break;
  }
c_token *comp_tok = c_parser_peek_token (parser);
+   /* Ignore the counted_by attribute for reference inside
+  offsetof since the information is not useful.  */
offsetof_ref
  = build_component_ref (loc, offsetof_ref,
  

[gcc r15-946] Use the .ACCESS_WITH_SIZE in builtin object size.

2024-05-31 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:6f17933548fc34ee269e90546a590df8269cee60

commit r15-946-g6f17933548fc34ee269e90546a590df8269cee60
Author: Qing Zhao 
Date:   Tue May 28 18:36:00 2024 +

Use the .ACCESS_WITH_SIZE in builtin object size.

gcc/ChangeLog:

* tree-object-size.cc (access_with_size_object_size): New function.
(call_object_size): Call the new function.

gcc/testsuite/ChangeLog:

* gcc.dg/builtin-object-size-common.h: Add a new macro EXPECT.
* gcc.dg/flex-array-counted-by-3.c: New test.
* gcc.dg/flex-array-counted-by-4.c: New test.
* gcc.dg/flex-array-counted-by-5.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/builtin-object-size-common.h |  11 ++
 gcc/testsuite/gcc.dg/flex-array-counted-by-3.c|  63 
 gcc/testsuite/gcc.dg/flex-array-counted-by-4.c| 178 ++
 gcc/testsuite/gcc.dg/flex-array-counted-by-5.c|  48 ++
 gcc/tree-object-size.cc   |  60 
 5 files changed, 360 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-common.h 
b/gcc/testsuite/gcc.dg/builtin-object-size-common.h
index 66ff7cdd953..b677067c6e6 100644
--- a/gcc/testsuite/gcc.dg/builtin-object-size-common.h
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-common.h
@@ -30,3 +30,14 @@ unsigned nfails = 0;
   __builtin_abort ();\
 return 0;\
   } while (0)
+
+#define EXPECT(p, _v) do {   \
+  size_t v = _v; \
+  if (p == v)\
+__builtin_printf ("ok:  %s == %zd\n", #p, p);\
+  else   \
+{\
+  __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v);\
+  FAIL ();   \
+}\
+} while (0);
diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-3.c 
b/gcc/testsuite/gcc.dg/flex-array-counted-by-3.c
new file mode 100644
index 000..78f50230e89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-3.c
@@ -0,0 +1,63 @@
+/* Test the attribute counted_by and its usage in
+ * __builtin_dynamic_object_size.  */ 
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "builtin-object-size-common.h"
+
+struct flex {
+  int b;
+  int c[];
+} *array_flex;
+
+struct annotated {
+  int b;
+  int c[] __attribute__ ((counted_by (b)));
+} *array_annotated;
+
+struct nested_annotated {
+  struct {
+union {
+  int b;
+  float f; 
+};
+int n;
+  };
+  int c[] __attribute__ ((counted_by (b)));
+} *array_nested_annotated;
+
+void __attribute__((__noinline__)) setup (int normal_count, int attr_count)
+{
+  array_flex
+= (struct flex *)malloc (sizeof (struct flex)
++ normal_count *  sizeof (int));
+  array_flex->b = normal_count;
+
+  array_annotated
+= (struct annotated *)malloc (sizeof (struct annotated)
+ + attr_count *  sizeof (int));
+  array_annotated->b = attr_count;
+
+  array_nested_annotated
+= (struct nested_annotated *)malloc (sizeof (struct nested_annotated)
++ attr_count *  sizeof (int));
+  array_nested_annotated->b = attr_count;
+
+  return;
+}
+
+void __attribute__((__noinline__)) test ()
+{
+EXPECT(__builtin_dynamic_object_size(array_flex->c, 1), -1);
+EXPECT(__builtin_dynamic_object_size(array_annotated->c, 1),
+  array_annotated->b * sizeof (int));
+EXPECT(__builtin_dynamic_object_size(array_nested_annotated->c, 1),
+  array_nested_annotated->b * sizeof (int));
+}
+
+int main(int argc, char *argv[])
+{
+  setup (10,10);   
+  test ();
+  DONE ();
+}
diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-4.c 
b/gcc/testsuite/gcc.dg/flex-array-counted-by-4.c
new file mode 100644
index 000..20103d58ef5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-4.c
@@ -0,0 +1,178 @@
+/* Test the attribute counted_by and its usage in
+__builtin_dynamic_object_size: what's the correct behavior when the
+allocation size mismatched with the value of counted_by attribute?
+We should always use the latest value that is hold by the counted_by
+field.  */
+/* { dg-do run } */
+/* { dg-options "-O -fstrict-flex-arrays=3" } */
+
+#include "builtin-object-size-common.h"
+
+struct annotated {
+  size_t foo;
+  char others;
+  char array[] __attribute__((counted_by (foo)));
+};
+
+#define noinline __attribute__((__noinline__))
+#define SIZE_BUMP 10 
+#define MAX(a, b) ((a) > (b) 

[gcc r15-947] Use the .ACCESS_WITH_SIZE in bound sanitizer.

2024-05-31 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:3d94fee616d6132075f3292a6eafdcb7b1d3f5a5

commit r15-947-g3d94fee616d6132075f3292a6eafdcb7b1d3f5a5
Author: Qing Zhao 
Date:   Tue May 28 18:37:14 2024 +

Use the .ACCESS_WITH_SIZE in bound sanitizer.

gcc/c-family/ChangeLog:

* c-ubsan.cc (get_bound_from_access_with_size): New function.
(ubsan_instrument_bounds): Handle call to .ACCESS_WITH_SIZE.

gcc/testsuite/ChangeLog:

* gcc.dg/ubsan/flex-array-counted-by-bounds-2.c: New test.
* gcc.dg/ubsan/flex-array-counted-by-bounds-3.c: New test.
* gcc.dg/ubsan/flex-array-counted-by-bounds-4.c: New test.
* gcc.dg/ubsan/flex-array-counted-by-bounds.c: New test.

Diff:
---
 gcc/c-family/c-ubsan.cc| 42 
 .../gcc.dg/ubsan/flex-array-counted-by-bounds-2.c  | 45 +
 .../gcc.dg/ubsan/flex-array-counted-by-bounds-3.c  | 34 
 .../gcc.dg/ubsan/flex-array-counted-by-bounds-4.c  | 34 
 .../gcc.dg/ubsan/flex-array-counted-by-bounds.c| 46 ++
 5 files changed, 201 insertions(+)

diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc
index 940982819dd..7cd3c6aa5b8 100644
--- a/gcc/c-family/c-ubsan.cc
+++ b/gcc/c-family/c-ubsan.cc
@@ -376,6 +376,40 @@ ubsan_instrument_return (location_t loc)
   return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
 }
 
+/* Get the tree that represented the number of counted_by, i.e, the maximum
+   number of the elements of the object that the call to .ACCESS_WITH_SIZE
+   points to, this number will be the bound of the corresponding array.  */
+static tree
+get_bound_from_access_with_size (tree call)
+{
+  if (!is_access_with_size_p (call))
+return NULL_TREE;
+
+  tree ref_to_size = CALL_EXPR_ARG (call, 1);
+  unsigned int class_of_size = TREE_INT_CST_LOW (CALL_EXPR_ARG (call, 2));
+  tree type = TREE_TYPE (CALL_EXPR_ARG (call, 3));
+  tree size = fold_build2 (MEM_REF, type, unshare_expr (ref_to_size),
+  build_int_cst (ptr_type_node, 0));
+  /* If size is negative value, treat it as zero.  */
+  if (!TYPE_UNSIGNED (type))
+  {
+tree cond = fold_build2 (LT_EXPR, boolean_type_node,
+unshare_expr (size), build_zero_cst (type));
+size = fold_build3 (COND_EXPR, type, cond,
+   build_zero_cst (type), size);
+  }
+
+  /* Only when class_of_size is 1, i.e, the number of the elements of
+ the object type, return the size.  */
+  if (class_of_size != 1)
+return NULL_TREE;
+  else
+size = fold_convert (sizetype, size);
+
+  return size;
+}
+
+
 /* Instrument array bounds for ARRAY_REFs.  We create special builtin,
that gets expanded in the sanopt pass, and make an array dimension
of it.  ARRAY is the array, *INDEX is an index to the array.
@@ -401,6 +435,14 @@ ubsan_instrument_bounds (location_t loc, tree array, tree 
*index,
  && COMPLETE_TYPE_P (type)
  && integer_zerop (TYPE_SIZE (type)))
bound = build_int_cst (TREE_TYPE (TYPE_MIN_VALUE (domain)), -1);
+  else if (INDIRECT_REF_P (array)
+  && is_access_with_size_p ((TREE_OPERAND (array, 0
+   {
+ bound = get_bound_from_access_with_size ((TREE_OPERAND (array, 0)));
+ bound = fold_build2 (MINUS_EXPR, TREE_TYPE (bound),
+  bound,
+  build_int_cst (TREE_TYPE (bound), 1));
+   }
   else
return NULL_TREE;
 }
diff --git a/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c 
b/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c
new file mode 100644
index 000..b503320628d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/flex-array-counted-by-bounds-2.c
@@ -0,0 +1,45 @@
+/* Test the attribute counted_by and its usage in
+   bounds sanitizer combined with VLA.  */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-output "index 11 out of bounds for type 'int 
\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index 20 out of bounds for type 'int 
\\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'int 
\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int 
\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */
+
+
+#include 
+
+void __attribute__((__noinline__)) setup_and_test_vla (int n, int m)
+{
+   struct foo {
+   int n;
+   int p[][n] __attribute__((counted_by(n)));
+   } *f;
+
+   f = (struct foo *) malloc (sizeof(struct foo) + m*sizeof(int[n]));
+   f->n = m;
+   f->p[m][n-1]=1;
+   return;
+}
+
+void __attribute__((__noinline__)) setup_and_test_vla_1 (int n1, int n2, int m)
+{
+  struct foo {
+int n;
+int p[][n2][n1] __attribute__((counted_by(n)));
+  } *f;
+
+  f = (struct foo *) malloc

[gcc r15-948] Add the 6th argument to .ACCESS_WITH_SIZE

2024-05-31 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:4c5bea7def13613fba166edb23289bab446b0b48

commit r15-948-g4c5bea7def13613fba166edb23289bab446b0b48
Author: Qing Zhao 
Date:   Tue May 28 18:39:31 2024 +

Add the 6th argument to .ACCESS_WITH_SIZE

to carry the TYPE of the flexible array.

Such information is needed during tree-object-size.cc.

We cannot use the result type or the type of the 1st argument
of the routine .ACCESS_WITH_SIZE to decide the element type
of the original array due to possible type casting in the
source code.

gcc/c/ChangeLog:

* c-typeck.cc (build_access_with_size_for_counted_by): Add the 6th
argument to .ACCESS_WITH_SIZE.

gcc/ChangeLog:

* tree-object-size.cc (access_with_size_object_size): Use the type
of the 6th argument for the type of the element.
* internal-fn.cc (expand_ACCESS_WITH_SIZE): Update the comment with
the 6th argument.

gcc/testsuite/ChangeLog:

* gcc.dg/flex-array-counted-by-6.c: New test.

Diff:
---
 gcc/c/c-typeck.cc  | 11 --
 gcc/internal-fn.cc |  2 ++
 gcc/testsuite/gcc.dg/flex-array-counted-by-6.c | 46 ++
 gcc/tree-object-size.cc| 16 +
 4 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 268c3ddbe14..a0e7dbe1b48 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -2714,7 +2714,8 @@ build_counted_by_ref (tree datum, tree subdatum, tree 
*counted_by_type)
 
to:
 
-   (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1))
+   (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1,
+   (TYPE_OF_ARRAY *)0))
 
NOTE: The return type of this function is the POINTER type pointing
to the original flexible array type.
@@ -2726,6 +2727,9 @@ build_counted_by_ref (tree datum, tree subdatum, tree 
*counted_by_type)
The 4th argument of the call is a constant 0 with the TYPE of the
object pointed by COUNTED_BY_REF.
 
+   The 6th argument of the call is a constant 0 with the pointer TYPE
+   to the original flexible array type.
+
   */
 static tree
 build_access_with_size_for_counted_by (location_t loc, tree ref,
@@ -2738,12 +2742,13 @@ build_access_with_size_for_counted_by (location_t loc, 
tree ref,
 
   tree call
 = build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE,
-   result_type, 5,
+   result_type, 6,
array_to_pointer_conversion (loc, ref),
counted_by_ref,
build_int_cst (integer_type_node, 1),
build_int_cst (counted_by_type, 0),
-   build_int_cst (integer_type_node, -1));
+   build_int_cst (integer_type_node, -1),
+   build_int_cst (result_type, 0));
   /* Wrap the call with an INDIRECT_REF with the flexible array type.  */
   call = build1 (INDIRECT_REF, TREE_TYPE (ref), call);
   SET_EXPR_LOCATION (call, loc);
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index eb2c4cd5904..0d27f17b283 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -3456,6 +3456,8 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
  1: read_only
  2: write_only
  3: read_write
+   6th argument: A constant 0 with the pointer TYPE to the original flexible
+ array type.
 
Both the return type and the type of the first argument of this
function have been converted from the incomplete array type to
diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-6.c 
b/gcc/testsuite/gcc.dg/flex-array-counted-by-6.c
new file mode 100644
index 000..65fa01443d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-6.c
@@ -0,0 +1,46 @@
+/* Test the attribute counted_by and its usage in
+ * __builtin_dynamic_object_size: when the type of the flexible array member
+ * is casting to another type.  */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "builtin-object-size-common.h"
+
+typedef unsigned short u16;
+
+struct info {
+   u16 data_len;
+   char data[] __attribute__((counted_by(data_len)));
+};
+
+struct foo {
+   int a;
+   int b;
+};
+
+static __attribute__((__noinline__))
+struct info *setup ()
+{
+ struct info *p;
+ size_t bytes = 3 * sizeof(struct foo);
+
+ p = (struct info *)malloc (sizeof (struct info) + bytes);
+ p->data_len = bytes;
+
+ return p;
+}
+
+static void
+__attribute__((__noinline__)) report (struct info *p)
+{
+ struct foo *bar = (struct foo *)p->data;
+ EXPECT(__builtin_dynamic_object_size((char *)(bar + 1), 1), 16);
+ EXPECT(__builtin_dynamic_object_size((char *)(bar + 2), 1), 8);
+}
+
+int main(int argc, char *argv[])
+{
+ stru

[gcc r15-4122] c: ICE in build_counted_by_ref [PR116735]

2024-10-07 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:9a17e6d03c6ed53e3b2dfd2c3ff9b1066ffa97b9

commit r15-4122-g9a17e6d03c6ed53e3b2dfd2c3ff9b1066ffa97b9
Author: qing zhao 
Date:   Mon Sep 30 18:29:29 2024 +

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 % 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 % 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 ..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;
+}


[gcc r13-9072] tree-optimization/116585 - SSA corruption with split_constant_offset

2024-10-02 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:a344ba9e42224220a7279a4051a08662435b1c60

commit r13-9072-ga344ba9e42224220a7279a4051a08662435b1c60
Author: Richard Biener 
Date:   Wed Sep 18 09:52:55 2024 +0200

tree-optimization/116585 - SSA corruption with split_constant_offset

split_constant_offset when looking through SSA defs can end up
picking SSA leafs that are subject to abnormal coalescing.  This
can lead to downstream consumers to insert code based on the
result (like from dataref analysis) in places that violate constraints
for abnormal coalescing.  It's best to not expand defs whose operands
are subject to abnormal coalescing - and not either do something when
a subexpression has operands like that already.

PR tree-optimization/116585
* tree-data-ref.cc (split_constant_offset_1): When either
operand is subject to abnormal coalescing do no further
processing.

* gcc.dg/torture/pr116585.c: New testcase.

(cherry picked from commit 1d0cb3b5fca69b81e69cfdb4aea0eebc1ac04750)

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr116585.c | 32 
 gcc/tree-data-ref.cc| 11 ---
 2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr116585.c 
b/gcc/testsuite/gcc.dg/torture/pr116585.c
new file mode 100644
index ..108c481e1043
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116585.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+
+char *s1, *s2;
+extern int* my_alloc (int);
+extern int _setjmp ();
+extern void bar();
+void foo(int s1len, int s2len)
+{
+  int e;
+  e = _setjmp ();
+{
+  int l, i;
+  int *md = my_alloc(((sizeof(int)) * (s1len + 1) * (s2len)));
+  s1len++;
+  for (; s1len; l)
+   for (; s2len; l)
+ for (; s1len; i)
+   {
+ int j = 1;
+ for (; j < s2len; j++)
+   {
+ int cost;
+ if (s1[1] == s2[1])
+   cost = 0;
+ else
+   cost = 1;
+ md[j * s1len ] = ((cost));
+   }
+   }
+  bar();
+}
+}
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 96934addff14..7657eeaf9e65 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -763,6 +763,14 @@ split_constant_offset_1 (tree type, tree op0, enum 
tree_code code, tree op1,
   if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type))
 return false;
 
+  if (TREE_CODE (op0) == SSA_NAME
+  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
+return false;
+  if (op1
+  && TREE_CODE (op1) == SSA_NAME
+  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))
+return false;
+
   switch (code)
 {
 case INTEGER_CST:
@@ -855,9 +863,6 @@ split_constant_offset_1 (tree type, tree op0, enum 
tree_code code, tree op1,
 
 case SSA_NAME:
   {
-   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
- return false;
-
gimple *def_stmt = SSA_NAME_DEF_STMT (op0);
enum tree_code subcode;


[gcc r14-10730] tree-optimization/116585 - SSA corruption with split_constant_offset

2024-10-02 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:e69c03971aa50fda96b3382bfded54da3d087c32

commit r14-10730-ge69c03971aa50fda96b3382bfded54da3d087c32
Author: Richard Biener 
Date:   Wed Sep 18 09:52:55 2024 +0200

tree-optimization/116585 - SSA corruption with split_constant_offset

split_constant_offset when looking through SSA defs can end up
picking SSA leafs that are subject to abnormal coalescing.  This
can lead to downstream consumers to insert code based on the
result (like from dataref analysis) in places that violate constraints
for abnormal coalescing.  It's best to not expand defs whose operands
are subject to abnormal coalescing - and not either do something when
a subexpression has operands like that already.

PR tree-optimization/116585
* tree-data-ref.cc (split_constant_offset_1): When either
operand is subject to abnormal coalescing do no further
processing.

* gcc.dg/torture/pr116585.c: New testcase.

(cherry picked from commit 1d0cb3b5fca69b81e69cfdb4aea0eebc1ac04750)

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr116585.c | 32 
 gcc/tree-data-ref.cc| 11 ---
 2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr116585.c 
b/gcc/testsuite/gcc.dg/torture/pr116585.c
new file mode 100644
index ..108c481e1043
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116585.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+
+char *s1, *s2;
+extern int* my_alloc (int);
+extern int _setjmp ();
+extern void bar();
+void foo(int s1len, int s2len)
+{
+  int e;
+  e = _setjmp ();
+{
+  int l, i;
+  int *md = my_alloc(((sizeof(int)) * (s1len + 1) * (s2len)));
+  s1len++;
+  for (; s1len; l)
+   for (; s2len; l)
+ for (; s1len; i)
+   {
+ int j = 1;
+ for (; j < s2len; j++)
+   {
+ int cost;
+ if (s1[1] == s2[1])
+   cost = 0;
+ else
+   cost = 1;
+ md[j * s1len ] = ((cost));
+   }
+   }
+  bar();
+}
+}
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 654a82202147..69b421f3c941 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -765,6 +765,14 @@ split_constant_offset_1 (tree type, tree op0, enum 
tree_code code, tree op1,
   if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type))
 return false;
 
+  if (TREE_CODE (op0) == SSA_NAME
+  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
+return false;
+  if (op1
+  && TREE_CODE (op1) == SSA_NAME
+  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))
+return false;
+
   switch (code)
 {
 case INTEGER_CST:
@@ -860,9 +868,6 @@ split_constant_offset_1 (tree type, tree op0, enum 
tree_code code, tree op1,
 
 case SSA_NAME:
   {
-   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
- return false;
-
gimple *def_stmt = SSA_NAME_DEF_STMT (op0);
enum tree_code subcode;


[gcc r12-10739] tree-optimization/116585 - SSA corruption with split_constant_offset

2024-10-02 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:8e5bd9b4b38f5b4fbd2a95d8f61168d9eeea97d3

commit r12-10739-g8e5bd9b4b38f5b4fbd2a95d8f61168d9eeea97d3
Author: Richard Biener 
Date:   Wed Sep 18 09:52:55 2024 +0200

tree-optimization/116585 - SSA corruption with split_constant_offset

split_constant_offset when looking through SSA defs can end up
picking SSA leafs that are subject to abnormal coalescing.  This
can lead to downstream consumers to insert code based on the
result (like from dataref analysis) in places that violate constraints
for abnormal coalescing.  It's best to not expand defs whose operands
are subject to abnormal coalescing - and not either do something when
a subexpression has operands like that already.

PR tree-optimization/116585
* tree-data-ref.cc (split_constant_offset_1): When either
operand is subject to abnormal coalescing do no further
processing.

* gcc.dg/torture/pr116585.c: New testcase.

(cherry picked from commit 1d0cb3b5fca69b81e69cfdb4aea0eebc1ac04750)

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr116585.c | 32 
 gcc/tree-data-ref.cc| 11 ---
 2 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr116585.c 
b/gcc/testsuite/gcc.dg/torture/pr116585.c
new file mode 100644
index ..108c481e1043
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr116585.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+
+char *s1, *s2;
+extern int* my_alloc (int);
+extern int _setjmp ();
+extern void bar();
+void foo(int s1len, int s2len)
+{
+  int e;
+  e = _setjmp ();
+{
+  int l, i;
+  int *md = my_alloc(((sizeof(int)) * (s1len + 1) * (s2len)));
+  s1len++;
+  for (; s1len; l)
+   for (; s2len; l)
+ for (; s1len; i)
+   {
+ int j = 1;
+ for (; j < s2len; j++)
+   {
+ int cost;
+ if (s1[1] == s2[1])
+   cost = 0;
+ else
+   cost = 1;
+ md[j * s1len ] = ((cost));
+   }
+   }
+  bar();
+}
+}
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 706a49f226ed..b7bca6a9d064 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -761,6 +761,14 @@ split_constant_offset_1 (tree type, tree op0, enum 
tree_code code, tree op1,
   if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type))
 return false;
 
+  if (TREE_CODE (op0) == SSA_NAME
+  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
+return false;
+  if (op1
+  && TREE_CODE (op1) == SSA_NAME
+  && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))
+return false;
+
   switch (code)
 {
 case INTEGER_CST:
@@ -853,9 +861,6 @@ split_constant_offset_1 (tree type, tree op0, enum 
tree_code code, tree op1,
 
 case SSA_NAME:
   {
-   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0))
- return false;
-
gimple *def_stmt = SSA_NAME_DEF_STMT (op0);
enum tree_code subcode;


[gcc r15-4370] Provide new GCC builtin __builtin_counted_by_ref [PR116016]

2024-10-15 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:e7380688fa5917011c3fb85b5e06fb00f776a95d

commit r15-4370-ge7380688fa5917011c3fb85b5e06fb00f776a95d
Author: Qing Zhao 
Date:   Tue Oct 15 17:55:22 2024 +

Provide new GCC builtin __builtin_counted_by_ref [PR116016]

With the addition of the 'counted_by' attribute and its wide roll-out
within the Linux kernel, a use case has been found that would be very
nice to have for object allocators: being able to set the counted_by
counter variable without knowing its name.

For example, given:

  struct foo {
...
int counter;
...
struct bar array[] __attribute__((counted_by (counter)));
  } *p;

The existing Linux object allocators are roughly:

  #define MAX(A, B) (A > B) ? (A) : (B)
  #define alloc(P, FAM, COUNT) ({ \
__auto_type __p = &(P); \
size_t __size = MAX (sizeof(*P),
 __builtin_offsetof (__typeof(*P), FAM)
 + sizeof (*(P->FAM)) * COUNT); \
*__p = kmalloc(__size); \
  })

Right now, any addition of a counted_by annotation must also
include an open-coded assignment of the counter variable after
the allocation:

  p = alloc(p, array, how_many);
  p->counter = how_many;

In order to avoid the tedious and error-prone work of manually adding
the open-coded counted-by intializations everywhere in the Linux
kernel, a new GCC builtin __builtin_counted_by_ref will be very useful
to be added to help the adoption of the counted-by attribute.

 -- Built-in Function: TYPE __builtin_counted_by_ref (PTR)
 The built-in function '__builtin_counted_by_ref' checks whether the
 array object pointed by the pointer PTR has another object
 associated with it that represents the number of elements in the
 array object through the 'counted_by' attribute (i.e.  the
 counted-by object).  If so, returns a pointer to the corresponding
 counted-by object.  If such counted-by object does not exist,
 returns a null pointer.

 This built-in function is only available in C for now.

 The argument PTR must be a pointer to an array.  The TYPE of the
 returned value is a pointer type pointing to the corresponding
 type of the counted-by object or a void pointer type in case of a
 null pointer being returned.

With this new builtin, the central allocator could be updated to:

  #define MAX(A, B) (A > B) ? (A) : (B)
  #define alloc(P, FAM, COUNT) ({ \
__auto_type __p = &(P); \
__auto_type __c = (COUNT); \
size_t __size = MAX (sizeof (*(*__p)),\
 __builtin_offsetof (__typeof(*(*__p)),FAM) \
 + sizeof (*((*__p)->FAM)) * __c); \
if ((*__p = kmalloc(__size))) { \
  __auto_type ret = __builtin_counted_by_ref((*__p)->FAM); \
  *_Generic(ret, void *: &(size_t){0}, default: ret) = __c; \
} \
  })

And then structs can gain the counted_by attribute without needing
additional open-coded counter assignments for each struct, and
unannotated structs could still use the same allocator.

PR c/116016

gcc/c-family/ChangeLog:

* c-common.cc: Add new __builtin_counted_by_ref.
* c-common.h (enum rid): Add RID_BUILTIN_COUNTED_BY_REF.

gcc/c/ChangeLog:

* c-decl.cc (names_builtin_p): Add RID_BUILTIN_COUNTED_BY_REF.
* c-parser.cc (has_counted_by_object): New routine.
(get_counted_by_ref): New routine.
(c_parser_postfix_expression): Handle New 
RID_BUILTIN_COUNTED_BY_REF.
* c-tree.h: New routine handle_counted_by_for_component_ref.
* c-typeck.cc (handle_counted_by_for_component_ref): New routine.
(build_component_ref): Call the new routine.

gcc/ChangeLog:

* doc/extend.texi: Add documentation for __builtin_counted_by_ref.

gcc/testsuite/ChangeLog:

* gcc.dg/builtin-counted-by-ref-1.c: New test.
* gcc.dg/builtin-counted-by-ref.c: New test.

Diff:
---
 gcc/c-family/c-common.cc|   1 +
 gcc/c-family/c-common.h |   1 +
 gcc/c/c-decl.cc |   1 +
 gcc/c/c-parser.cc   |  79 ++
 gcc/c/c-tree.h  |   1 +
 gcc/c/c-typeck.cc   |  33 --
 gcc/doc/extend.texi |  55 ++
 gcc/testsuite/gcc.dg/builtin-counted-by-ref-1.c | 135 
 gcc/testsuite/gcc.dg/builtin-counted-by-ref.c   |  61 +++
 9 files changed, 358 insertions(+), 9 deletions(-)

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index ec6a5da892dd..8ad9b99

[gcc r15-9505] c: Fully fold each parameter for call to .ACCESS_WITH_SIZE [PR119717]

2025-04-15 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:727f330f9ac661339af1121fc5c9b67dd0d35872

commit r15-9505-g727f330f9ac661339af1121fc5c9b67dd0d35872
Author: Qing Zhao 
Date:   Mon Apr 14 19:41:12 2025 +

c: Fully fold each parameter for call to .ACCESS_WITH_SIZE [PR119717]

C_MAYBE_CONST_EXPR is a C FE operator that will be removed by c_fully_fold.
In c_fully_fold, it assumes that operands of function calls have already
been folded. However, when we build call to .ACCESS_WITH_SIZE, all its
operands are not fully folded. therefore the C FE specific operator is
passed to middle-end.

In order to fix this issue, fully fold the parameters before building the
call to .ACCESS_WITH_SIZE.

PR c/119717

gcc/c/ChangeLog:

* c-typeck.cc (build_access_with_size_for_counted_by): Fully fold 
the
parameters for call to .ACCESS_WITH_SIZE.

gcc/testsuite/ChangeLog:

* gcc.dg/pr119717.c: New test.

Diff:
---
 gcc/c/c-typeck.cc   |  8 ++--
 gcc/testsuite/gcc.dg/pr119717.c | 24 
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 3870e8a15587..55d896e02df5 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -3013,12 +3013,16 @@ build_access_with_size_for_counted_by (location_t loc, 
tree ref,
   gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)));
   /* The result type of the call is a pointer to the flexible array type.  */
   tree result_type = c_build_pointer_type (TREE_TYPE (ref));
+  tree first_param
+= c_fully_fold (array_to_pointer_conversion (loc, ref), false, NULL);
+  tree second_param
+= c_fully_fold (counted_by_ref, false, NULL);
 
   tree call
 = build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE,
result_type, 6,
-   array_to_pointer_conversion (loc, ref),
-   counted_by_ref,
+   first_param,
+   second_param,
build_int_cst (integer_type_node, 1),
build_int_cst (counted_by_type, 0),
build_int_cst (integer_type_node, -1),
diff --git a/gcc/testsuite/gcc.dg/pr119717.c b/gcc/testsuite/gcc.dg/pr119717.c
new file mode 100644
index ..e5eedc567b3d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119717.c
@@ -0,0 +1,24 @@
+/* PR c/119717  */
+/* { dg-additional-options "-std=c23" } */
+/* { dg-do compile } */
+
+struct annotated {
+  unsigned count;
+  [[gnu::counted_by(count)]] char array[];
+};
+
+[[gnu::noinline,gnu::noipa]]
+static unsigned
+size_of (bool x, struct annotated *a)
+{
+  char *p = (x ? a : 0)->array;
+  return __builtin_dynamic_object_size (p, 1);
+}
+
+int main()
+{
+  struct annotated *p = __builtin_malloc(sizeof *p);
+  p->count = 0;
+  __builtin_printf ("the bdos whole is %ld\n", size_of (0, p));
+  return 0;
+}


[gcc r16-1017] C: Flex array in the middle via type alias is not reported [PR120353]

2025-05-30 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:f37c5f1d88c9da17f16cdb33e7c9d43e4bb5f64d

commit r16-1017-gf37c5f1d88c9da17f16cdb33e7c9d43e4bb5f64d
Author: Qing Zhao 
Date:   Wed May 28 21:13:38 2025 +

C: Flex array in the middle via type alias is not reported [PR120353]

The root cause of the bug is: the TYPE_INCLUDES_FLEXARRAY marking of the
structure type is not copied to its aliased type.
The fix is to copy this marking to all the variant types of the current
structure type.

PR c/120353

gcc/c/ChangeLog:

* c-decl.cc (finish_struct): Copy TYPE_INCLUDES_FLEXARRAY marking
to all the variant types of the current structure type.

gcc/testsuite/ChangeLog:

* gcc.dg/pr120353.c: New test.

Diff:
---
 gcc/c/c-decl.cc |  1 +
 gcc/testsuite/gcc.dg/pr120353.c | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index e10f9c1ea7b6..38de96e12876 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9893,6 +9893,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
   C_TYPE_VARIABLY_MODIFIED (x) = C_TYPE_VARIABLY_MODIFIED (t);
   C_TYPE_INCOMPLETE_VARS (x) = NULL_TREE;
+  TYPE_INCLUDES_FLEXARRAY (x) = TYPE_INCLUDES_FLEXARRAY (t);
 }
 
   /* Update type location to the one of the definition, instead of e.g.
diff --git a/gcc/testsuite/gcc.dg/pr120353.c b/gcc/testsuite/gcc.dg/pr120353.c
new file mode 100644
index ..6f8e4acf7f26
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120353.c
@@ -0,0 +1,11 @@
+/* PR120353: Test for -Wflex-array-member-not-at-end on structure with 
+   typedef.  */ 
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+typedef struct flex flex_t;
+struct flex { int n; int data[]; };
+struct out_flex_mid {flex_t flex_data;  int m; }; /* { dg-warning "structure 
containing a flexible array member is not at the end of another structure" } */
+
+typedef struct flex flex_t1;
+struct out_flex_mid1 {flex_t1 flex_data1; int n; }; /* { dg-warning "structure 
containing a flexible array member is not at the end of another structure" } */


[gcc r16-1018] C: Flex array in union followed by a structure field is not reported [PR120354]

2025-05-30 Thread Qing Zhao via Gcc-cvs
https://gcc.gnu.org/g:70418e6c0120cfce33ab69628602dfdadbed683a

commit r16-1018-g70418e6c0120cfce33ab69628602dfdadbed683a
Author: Qing Zhao 
Date:   Thu May 29 15:59:41 2025 +

C: Flex array in union followed by a structure field is not reported 
[PR120354]

There is only one last_field for a structure type, but there might
be multiple last_fields for a union type, therefore we should ORed
the result of TYPE_INCLUDES_FLEXARRAY for multiple last_fields of
a union type.

PR c/120354

gcc/c/ChangeLog:

* c-decl.cc (finish_struct): Or the results for 
TYPE_INCLUDES_FLEXARRAY.

gcc/testsuite/ChangeLog:

* gcc.dg/pr120354.c: New test.

Diff:
---
 gcc/c/c-decl.cc |  9 ++---
 gcc/testsuite/gcc.dg/pr120354.c | 33 +
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 38de96e12876..1008bcaebdc9 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9649,15 +9649,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
 
   /* Set TYPE_INCLUDES_FLEXARRAY for the context of x, t.
-when x is an array and is the last field.  */
+when x is an array and is the last field.
+There is only one last_field for a structure type, but there might
+be multiple last_fields for a union type, therefore we should ORed
+the result for multiple last_fields.  */
   if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && c_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)))
TYPE_INCLUDES_FLEXARRAY (t)
- = is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
+ |= is_last_field && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (x));
 
   if (warn_flex_array_member_not_at_end
  && !is_last_field
diff --git a/gcc/testsuite/gcc.dg/pr120354.c b/gcc/testsuite/gcc.dg/pr120354.c
new file mode 100644
index ..6749737a1737
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120354.c
@@ -0,0 +1,33 @@
+/* PR120354: Test for -Wflex-array-member-not-at-end on union with 
+   flexible array members.  */ 
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+struct P {};
+union L {};
+
+union X {
+int x[];
+struct P y;
+};
+
+struct T {
+union X x; /* { dg-warning "structure containing a flexible array member 
is not at the end of another structure" } */
+int plug;
+};
+
+struct Q {
+int len;
+int data[];
+};
+
+union Y {
+struct Q q;
+union L y;
+};
+
+struct S {
+union Y y;  /* { dg-warning "structure containing a flexible array member 
is not at the end of another structure" } */
+int plug;
+};
+