PR c/97206 - ICE in composite_type on declarations of a similar array types
authorMartin Sebor <msebor@redhat.com>
Wed, 30 Sep 2020 15:31:29 +0000 (09:31 -0600)
committerMartin Sebor <msebor@redhat.com>
Wed, 30 Sep 2020 18:59:53 +0000 (12:59 -0600)
gcc/ChangeLog:

PR c/97206
* attribs.c (attr_access::array_as_string): Avoid modifying a shared
type in place and use build_type_attribute_qual_variant instead.

gcc/testsuite/ChangeLog:

PR c/97206
* gcc.dg/Warray-parameter-7.c: New test.
* gcc.dg/Warray-parameter-8.c: New test.
* gcc.dg/Wvla-parameter-5.c: New test.

gcc/attribs.c
gcc/testsuite/gcc.dg/Warray-parameter-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Warray-parameter-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wvla-parameter-5.c [new file with mode: 0644]

index abc75368e6c29a5be3f6051316e951f992d2cb66..3f6ec3d3aa39bfdc5ccfb840b07fef487d36fdc0 100644 (file)
@@ -2256,15 +2256,14 @@ attr_access::array_as_string (tree type) const
 
   if (this->str)
     {
-      /* For array parameters (but not pointers) create an array type
-        that corresponds to the form of the parameter including its
+      /* For array parameters (but not pointers) create a temporary array
+        type that corresponds to the form of the parameter including its
         qualifiers even though they apply to the pointer, not the array
         type.  */
       const bool vla_p = minsize == HOST_WIDE_INT_M1U;
       tree eltype = TREE_TYPE (type);
-      tree artype;
-
       tree index_type = NULL_TREE;
+
       if (minsize == HOST_WIDE_INT_M1U)
        {
          /* Determine if this is a VLA (an array whose most significant
@@ -2278,28 +2277,24 @@ attr_access::array_as_string (tree type) const
       else  if (minsize)
        index_type = build_index_type (size_int (minsize - 1));
 
-      artype = build_array_type (eltype, index_type);
-
+      tree arat = NULL_TREE;
       if (static_p || vla_p)
        {
          tree flag = static_p ? integer_one_node : NULL_TREE;
          /* Hack: there's no language-independent way to encode
             the "static" specifier or the "*" notation in an array type.
-            Temporarily add an attribute to have the pretty printer add
-            "static" or "*", and remove it later.  The static notation
-            is only valid in the most significant bound but [*] can be
-            used for any bound.  Because [*] is represented the same as
-            [0] this hack only works for the most significant bound like
-            static and the others are rendered as [0].  */
-         tree at = tree_cons (get_identifier ("array"), flag, NULL_TREE);
-         TYPE_ATTRIBUTES (artype) = at;
+            Add a "fake" attribute to have the pretty-printer add "static"
+            or "*".  The "[static N]" notation is only valid in the most
+            significant bound but [*] can be used for any bound.  Because
+            [*] is represented the same as [0] this hack only works for
+            the most significant bound like static and the others are
+            rendered as [0].  */
+         arat = build_tree_list (get_identifier ("array"), flag);
        }
 
-      TYPE_ATOMIC (artype) = TYPE_ATOMIC (type);
-      TYPE_READONLY (artype) = TYPE_READONLY (type);
-      TYPE_RESTRICT (artype) = TYPE_RESTRICT (type);
-      TYPE_VOLATILE (artype) = TYPE_VOLATILE (type);
-      type = artype;
+      const int quals = TYPE_QUALS (type);
+      type = build_array_type (eltype, index_type);
+      type = build_type_attribute_qual_variant (type, arat, quals);
     }
 
   /* Format the type using the current pretty printer.  The generic tree
@@ -2309,10 +2304,6 @@ attr_access::array_as_string (tree type) const
   typstr = pp_formatted_text (pp);
   delete pp;
 
-  if (this->str)
-    /* Remove the attribute that wasn't installed by decl_attributes.  */
-    TYPE_ATTRIBUTES (type) = NULL_TREE;
-
   return typstr;
 }
 
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-7.c b/gcc/testsuite/gcc.dg/Warray-parameter-7.c
new file mode 100644 (file)
index 0000000..4863045
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR c/97206 - ICE in composite_type on declarations of a similar array types
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+__attribute__((__access__(__write_only__, 1))) void
+f1 (char* restrict);
+
+void f1 (char*);
+
+char a1[];
+char a1[] = { };
+
+
+void f2 (char[restrict]);
+void f2 (char*);
+
+char a2[];
+char a2[] = { };
+
+
+void f3 (char*);
+void f3 (char[const]);
+
+extern const char a3[];
+extern const char a3[1];
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-8.c b/gcc/testsuite/gcc.dg/Warray-parameter-8.c
new file mode 100644 (file)
index 0000000..b152702
--- /dev/null
@@ -0,0 +1,36 @@
+/* Verify that combinations of array type qualifiers render correctly.
+   { dg-do compile }
+   { dg-options "-Warray-parameter" } */
+
+void fatm (int[_Atomic 1]);       // { dg-message "previously declared as 'int\\\[_Atomic 1]" }
+void fatm (int[_Atomic 2]);       // { dg-warning "argument 1 of type 'int\\\[_Atomic 2]' with mismatched bound" }
+
+
+void fcst (int[const 2]);         // { dg-message "previously declared as 'int\\\[const 2]" }
+void fcst (int[const 3]);         // { dg-warning "argument 1 of type 'int\\\[const 3]' with mismatched bound" }
+
+
+void frst (int[restrict 3]);      // { dg-message "previously declared as 'int\\\[restrict 3]" }
+void frst (int[restrict 4]);      // { dg-warning "argument 1 of type 'int\\\[restrict 4]' with mismatched bound" }
+
+void fvol (int[volatile 4]);      // { dg-message "previously declared as 'int\\\[volatile 4]" }
+void fvol (int[volatile 5]);      // { dg-warning "argument 1 of type 'int\\\[volatile 5]' with mismatched bound" }
+
+
+void fcr (int[const restrict 1]);   // { dg-message "previously declared as 'int\\\[\(const restrict|restrict const\) 1]" }
+void fcr (int[restrict volatile 2]); // { dg-warning "argument 1 of type 'int\\\[\(restrict volatile|volatile restrict\) 2]' with mismatched bound" }
+void fcr (int[const restrict volatile 3]);  // { dg-warning "argument 1 of type 'int\\\[const volatile restrict 3]' with mismatched bound" }
+
+
+extern int n;
+
+void fcx_n (int [const 1][n]);      // { dg-message "previously declared as 'int\\\[const 1]\\\[n]'" "note" }
+void fcx_n (int [restrict 2][n]);   // { dg-warning "argument 1 of type 'int\\\[restrict 2]\\\[n]' with mismatched bound" }
+
+
+extern int n1, n2;
+
+/* The mismatch in the array bound should be diagnosed but the mismatch
+   in the VLA should not be without -Wvla-parameter.  */
+void fc3_n1 (int [const 3][n1]);   // { dg-message "previously declared as 'int\\\[const 3]\\\[n1]'" "note" }
+void fc3_n1 (int [const 5][n2]);   // { dg-warning "argument 1 of type 'int\\\[const 5]\\\[n2]' with mismatched bound" }
diff --git a/gcc/testsuite/gcc.dg/Wvla-parameter-5.c b/gcc/testsuite/gcc.dg/Wvla-parameter-5.c
new file mode 100644 (file)
index 0000000..16b40d9
--- /dev/null
@@ -0,0 +1,22 @@
+/* Verify that combinations of array type qualifiers render correctly.
+   { dg-do compile }
+   { dg-options "-Wvla-parameter" } */
+
+extern int n1, n2;
+
+void fcx_n1 (int [const][n1]);     // { dg-message "previously declared as 'int\\\[const]\\\[n1]' with bound 'n1'" "note" }
+void fcx_n1 (int [const][n2]);     // { dg-warning "argument 1 of type 'int\\\[const]\\\[n2]' declared with mismatched bound 'n2'" }
+
+/* The mismatch in the array bound should not be diagnosed without
+   -Warray-parameter but the mismatch in the VLA should still be
+   diagnosed.  */
+void fc3_n1 (int [const 3][n1]);   // { dg-message "previously declared as 'int\\\[const 3]\\\[n1]' with bound 'n1'" "note" }
+void fc3_n1 (int [const 5][n2]);   // { dg-warning "argument 1 of type 'int\\\[const 5]\\\[n2]' declared with mismatched bound 'n2'" }
+
+
+void frx_n1 (int [restrict][n1]);  // { dg-message "previously declared as 'int\\\[restrict]\\\[n1]' with bound 'n1'" "note" }
+void frx_n1 (int [restrict][n2]);  // { dg-warning "argument 1 of type 'int\\\[restrict]\\\[n2]' declared with mismatched bound 'n2'" }
+
+
+void fvx_n2 (int [volatile][n2]);  // { dg-message "previously declared as 'int\\\[volatile]\\\[n2]' with bound 'n2'" "note" }
+void fvx_n2 (int [volatile][n1]);  // { dg-warning "argument 1 of type 'int\\\[volatile]\\\[n1]' declared with mismatched bound 'n1'" }