diff mbox series

v2 [C PATCH] Fix regression causing ICE for structs with VLAs [PR 112488]

Message ID 7e4a91d16011c4d5ac5ab37412de78118a77fa63.camel@tugraz.at
State New
Headers show
Series v2 [C PATCH] Fix regression causing ICE for structs with VLAs [PR 112488] | expand

Commit Message

Martin Uecker Dec. 9, 2023, 7:58 p.m. UTC
I revised version which fixes a problem with breaking other
callers of finish_rust. Please ignore the previous one.

Bootstrapped and regression tested on x86_64


Fix regression causing ICE for structs with VLAs [PR 112488]

A previous patch the fixed several ICEs related to size expressions
of VM types (PR c/70418, ...) caused a regression for structs where
a DECL_EXPR is not generated anymore although reqired.  We now call
add_decl_expr introduced by the previous patch from finish_struct.
The function is revised with a new argument to not set the TYPE_NAME
for the type to the DECL_EXPR in this specific case.

	PR c/112488

gcc/c
	* c-decl.cc (add_decl_expr): Revise.
	(finish_struct): Create DECL_EXPR.
	* c-parser.cc (c_parser_struct_or_union_specifier): Call
	finish_struct with expression for VLA sizes.
	* c-tree.h (finish_struct): Add argument.

gcc/testsuite
	* gcc.dg/pr112488-1.c: New test.
	* gcc.dg/pr112488-2.c: New test.
	* gcc.dg/pr112898.c: New test.
	* gcc.misc-tests/gcov-pr85350.c: Adapt.
---
 gcc/c/c-decl.cc                             | 33 ++++++++++++++++-----
 gcc/c/c-parser.cc                           |  2 +-
 gcc/c/c-tree.h                              |  3 +-
 gcc/testsuite/gcc.dg/pr112488-1.c           | 14 +++++++++
 gcc/testsuite/gcc.dg/pr112488-2.c           | 13 ++++++++
 gcc/testsuite/gcc.dg/pr112898.c             |  9 ++++++
 gcc/testsuite/gcc.misc-tests/gcov-pr85350.c |  2 +-
 7 files changed, 65 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr112488-1.c
 create mode 100644 gcc/testsuite/gcc.dg/pr112488-2.c
 create mode 100644 gcc/testsuite/gcc.dg/pr112898.c

Comments

Joseph Myers Dec. 11, 2023, 9:02 p.m. UTC | #1
On Sat, 9 Dec 2023, Martin Uecker wrote:

> Fix regression causing ICE for structs with VLAs [PR 112488]
> 
> A previous patch the fixed several ICEs related to size expressions
> of VM types (PR c/70418, ...) caused a regression for structs where
> a DECL_EXPR is not generated anymore although reqired.  We now call
> add_decl_expr introduced by the previous patch from finish_struct.
> The function is revised with a new argument to not set the TYPE_NAME
> for the type to the DECL_EXPR in this specific case.

OK.
diff mbox series

Patch

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 92c83e1bf10..039a66fef09 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -6618,12 +6618,10 @@  smallest_type_quals_location (const location_t *locations,
    the size evaluation prior to the side effects.  We therefore
    use BIND_EXPRs in TYPENAME contexts too.  */
 static void
-add_decl_expr (location_t loc, enum decl_context decl_context, tree type,
-	       tree *expr)
+add_decl_expr (location_t loc, tree type, tree *expr, bool set_name_p)
 {
   tree bind = NULL_TREE;
-  if (decl_context == TYPENAME || decl_context == PARM
-      || decl_context == FIELD)
+  if (expr)
     {
       bind = build3 (BIND_EXPR, void_type_node, NULL_TREE, NULL_TREE,
 		     NULL_TREE);
@@ -6636,7 +6634,8 @@  add_decl_expr (location_t loc, enum decl_context decl_context, tree type,
   pushdecl (decl);
   DECL_ARTIFICIAL (decl) = 1;
   add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
-  TYPE_NAME (type) = decl;
+  if (set_name_p)
+    TYPE_NAME (type) = decl;
 
   if (bind)
     {
@@ -7635,7 +7634,12 @@  grokdeclarator (const struct c_declarator *declarator,
 	       type has a name/declaration of it's own, but special attention
 	       is required if the type is anonymous. */
 	    if (!TYPE_NAME (type) && c_type_variably_modified_p (type))
-	      add_decl_expr (loc, decl_context, type, expr);
+	      {
+		bool bind_p = decl_context == TYPENAME
+			      || decl_context == FIELD
+			      || decl_context == PARM;
+		add_decl_expr (loc, type, bind_p ? expr : NULL, true);
+	      }
 
 	    type = c_build_pointer_type (type);
 
@@ -7900,7 +7904,12 @@  grokdeclarator (const struct c_declarator *declarator,
 
 	    /* The pointed-to type may need a decl expr (see above).  */
 	    if (!TYPE_NAME (type) && c_type_variably_modified_p (type))
-	      add_decl_expr (loc, decl_context, type, expr);
+	      {
+		bool bind_p = decl_context == TYPENAME
+			      || decl_context == FIELD
+			      || decl_context == PARM;
+		add_decl_expr (loc, type, bind_p ? expr : NULL, true);
+	      }
 
 	    type = c_build_pointer_type (type);
 	    type_quals = array_ptr_quals;
@@ -9257,7 +9266,8 @@  is_flexible_array_member_p (bool is_last_field,
 
 tree
 finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
-	       class c_struct_parse_info *enclosing_struct_parse_info)
+	       class c_struct_parse_info *enclosing_struct_parse_info,
+	       tree *expr)
 {
   tree x;
   bool toplevel = file_scope == current_scope;
@@ -9595,6 +9605,13 @@  finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 
   finish_incomplete_vars (incomplete_vars, toplevel);
 
+  /* Make sure a DECL_EXPR is created for structs with VLA members.
+     Because we do not know the context, we always pass expr
+     to force creation of a BIND_EXPR which is required in some
+     contexts.  */
+  if (c_type_variably_modified_p (t))
+    add_decl_expr (loc, t, expr, false);
+
   if (warn_cxx_compat)
     warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc);
 
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index df9a07928b5..dcb6c21da41 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -4087,7 +4087,7 @@  c_parser_struct_or_union_specifier (c_parser *parser)
       ret.spec = finish_struct (struct_loc, type, nreverse (contents),
 				chainon (std_attrs,
 					 chainon (attrs, postfix_attrs)),
-				struct_info);
+				struct_info, &expr);
       ret.kind = ctsk_tagdef;
       ret.expr = expr;
       ret.expr_const_operands = true;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index d0bdc3df2c2..b325723a734 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -656,7 +656,8 @@  extern void finish_decl (tree, location_t, tree, tree, tree);
 extern tree finish_enum (tree, tree, tree);
 extern void finish_function (location_t = input_location);
 extern tree finish_struct (location_t, tree, tree, tree,
-			   class c_struct_parse_info *);
+			   class c_struct_parse_info *,
+			   tree *expr = NULL);
 extern tree c_simulate_enum_decl (location_t, const char *,
 				  vec<string_int_pair> *);
 extern tree c_simulate_record_decl (location_t, const char *,
diff --git a/gcc/testsuite/gcc.dg/pr112488-1.c b/gcc/testsuite/gcc.dg/pr112488-1.c
new file mode 100644
index 00000000000..b53295c4366
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr112488-1.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile }
+ * { dg-options "-O1" } */
+
+extern void abort(void);
+
+int test(int *n) {
+  struct T { char a[*n], b[*n]; };
+  return sizeof(struct T) - sizeof(struct T);
+}
+
+void f1(int *p) {
+  if (!test(p)) abort();
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr112488-2.c b/gcc/testsuite/gcc.dg/pr112488-2.c
new file mode 100644
index 00000000000..b5e5fbd3f2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr112488-2.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile }
+ * { dg-options "-std=gnu23 -O1" } */
+
+extern void abort(void);
+
+int test(int *n, struct T { char a[*n], b[*n]; }*) {
+  return sizeof(struct T) - sizeof(struct T);
+}
+
+void f1(int *p) {
+  if (test(p, 0)) abort();
+}
+
diff --git a/gcc/testsuite/gcc.dg/pr112898.c b/gcc/testsuite/gcc.dg/pr112898.c
new file mode 100644
index 00000000000..395f3afaf2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr112898.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } 
+   { dg-options "-O2 -finstrument-functions-once" } */
+
+void func(int n)
+{
+        struct T { int x[n]; };
+	struct T *t = __builtin_malloc(sizeof *t);
+}
+
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
index a42bf1282b2..0383b81fdfb 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-pr85350.c
@@ -4,7 +4,7 @@ 
 int main (void)
 {
   const int t = 2; /* count(1) */
-  struct s1 {	/* count(-) */
+  struct s1 {	/* count(1) */
     int x;
     int g[t];
   };