Reset front end trees before they make it into the middle end (PR middle-end/97172).
authorMartin Sebor <msebor@redhat.com>
Mon, 1 Feb 2021 16:08:21 +0000 (09:08 -0700)
committerMartin Sebor <msebor@redhat.com>
Mon, 1 Feb 2021 16:09:52 +0000 (09:09 -0700)
gcc/ChangeLog:

PR middle-end/97172
* attribs.c (attr_access::free_lang_data): Define new function.
* attribs.h (attr_access::free_lang_data): Declare new function.

gcc/c/ChangeLog:

PR middle-end/97172
* c-decl.c (free_attr_access_data): New function.
(c_parse_final_cleanups): Call free_attr_access_data.

gcc/testsuite/ChangeLog:

PR middle-end/97172
* gcc.dg/pr97172.c: New test.

gcc/attribs.c
gcc/attribs.h
gcc/c/c-decl.c
gcc/testsuite/gcc.dg/pr97172.c [new file with mode: 0644]

index 94991fbbeabfab11ca937662b473305f8562293c..81322d40f1dd63072ce3a9822ac96efd5275144c 100644 (file)
@@ -2238,6 +2238,38 @@ attr_access::vla_bounds (unsigned *nunspec) const
   return list_length (size);
 }
 
+/* Reset front end-specific attribute access data from ATTRS.
+   Called from the free_lang_data pass.  */
+
+/* static */ void
+attr_access::free_lang_data (tree attrs)
+{
+  for (tree acs = attrs; (acs = lookup_attribute ("access", acs));
+       acs = TREE_CHAIN (acs))
+    {
+      tree vblist = TREE_VALUE (acs);
+      vblist = TREE_CHAIN (vblist);
+      if (!vblist)
+       continue;
+
+      vblist = TREE_VALUE (vblist);
+      if (!vblist)
+       continue;
+
+      for (vblist = TREE_VALUE (vblist); vblist; vblist = TREE_CHAIN (vblist))
+       {
+         tree *pvbnd = &TREE_VALUE (vblist);
+         if (!*pvbnd || DECL_P (*pvbnd))
+           continue;
+
+         /* VLA bounds that are expressions as opposed to DECLs are
+            only used in the front end.  Reset them to keep front end
+            trees leaking into the middle end (see pr97172) and to
+            free up memory.  */
+         *pvbnd = NULL_TREE;
+       }
+    }
+}
 
 /* Defined in attr_access.  */
 constexpr char attr_access::mode_chars[];
index 21d28a47f39f2c7517b250ce8ba02ed74a763a65..898e73db3e4d3900538b9aa5355de3e4937a3ab8 100644 (file)
@@ -274,6 +274,9 @@ struct attr_access
   /* Return the access mode corresponding to the character code.  */
   static access_mode from_mode_char (char);
 
+  /* Reset front end-specific attribute access data from attributes.  */
+  static void free_lang_data (tree);
+
   /* The character codes corresponding to all the access modes.  */
   static constexpr char mode_chars[5] = { '-', 'r', 'w', 'x', '^' };
 
index 4ba9477f5d189b50dc0c2fec41862e72ee7aa9f7..be95643fcf929b0e0c952b8c472e598f164b7627 100644 (file)
@@ -12146,6 +12146,27 @@ collect_source_refs (void)
       collect_source_ref (DECL_SOURCE_FILE (decl));
 }
 
+/* Free attribute access data that are not needed by the middle end. */
+
+static void
+free_attr_access_data ()
+{
+  struct cgraph_node *n;
+
+  /* Iterate over all functions declared in the translation unit.  */
+  FOR_EACH_FUNCTION (n)
+    {
+      tree fntype = TREE_TYPE (n->decl);
+      if (!fntype)
+       continue;
+      tree attrs = TYPE_ATTRIBUTES (fntype);
+      if (!attrs)
+       continue;
+
+      attr_access::free_lang_data (attrs);
+    }
+}
+
 /* Perform any final parser cleanups and generate initial debugging
    information.  */
 
@@ -12190,6 +12211,9 @@ c_parse_final_cleanups (void)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
+  if (!in_lto_p)
+    free_attr_access_data ();
+
   timevar_stop (TV_PHASE_DEFERRED);
   timevar_start (TV_PHASE_PARSING);
 
diff --git a/gcc/testsuite/gcc.dg/pr97172.c b/gcc/testsuite/gcc.dg/pr97172.c
new file mode 100644 (file)
index 0000000..ab5b2e9
--- /dev/null
@@ -0,0 +1,50 @@
+/* PR middle-end/97172 - ICE: tree code ‘ssa_name’ is not supported in LTO
+   streams
+   { dg-do compile }
+   { dg-options "-Wall -flto" }
+   { dg-require-effective-target lto } */
+
+int n;
+
+void fn (int a[n]);
+void fnp1 (int a[n + 1]);
+
+void fx_n (int a[][n]);
+void fx_np1 (int a[][n + 1]);
+
+void f2_n (int a[2][n]);
+void f2_np1 (int a[2][n + 1]);
+
+void fn_3 (int a[n][3]);
+void fnp1_3 (int a[n + 1][3]);
+
+void fn_n (int a[n][n]);
+void fn_np1 (int a[n][n + 1]);
+void fnp1_np1 (int a[n + 1][n + 1]);
+
+void fn_n_n (int a[n][n][n]);
+void fn_n_np1 (int a[n][n][n + 1]);
+void fn_np1_np1 (int a[n][n + 1][n + 1]);
+void fnp1_np1_np1 (int a[n + 1][n + 1][n + 1]);
+
+
+void gn (int a[n]) { fn (a); }
+void gnp1 (int a[n + 1]) { fnp1 (a); }
+
+void gx_n (int a[][n]) { fx_n (a); }
+void gx_np1 (int a[][n + 1]) { fx_np1 (a); }
+
+void g2_n (int a[2][n]) { f2_n (a); }
+void g2_np1 (int a[2][n + 1]) { f2_np1 (a); }
+
+void gn_3 (int a[n][3]) { fn_3 (a); }
+void gnp1_3 (int a[n + 1][3]) { fnp1_3 (a); }
+
+void gn_n (int a[n][n]) { fn_n (a); }
+void gn_np1 (int a[n][n + 1]) { fn_np1 (a); }
+void gnp1_np1 (int a[n + 1][n + 1]) { fnp1_np1 (a); }
+
+void gn_n_n (int a[n][n][n]) { fn_n_n (a); }
+void gn_n_np1 (int a[n][n][n + 1]) { fn_n_np1 (a); }
+void gn_np1_np1 (int a[n][n + 1][n + 1]) { fn_np1_np1 (a); }
+void gnp1_np1_np1 (int a[n + 1][n + 1][n + 1]) { fnp1_np1_np1 (a); }