PR c++/94098 - ICE on attribute access redeclaration
authorMartin Sebor <msebor@redhat.com>
Fri, 27 Mar 2020 19:54:22 +0000 (13:54 -0600)
committerMartin Sebor <msebor@redhat.com>
Fri, 27 Mar 2020 19:54:22 +0000 (13:54 -0600)
gcc/c-family/ChangeLog:

PR c++/94098
* c-attribs.c (handle_access_attribute): Avoid setting TYPE_ATTRIBUTES
here.

gcc/ChangeLog:

PR c++/94098
* calls.c (init_attr_rdwr_indices): Iterate over all access attributes.

gcc/testsuite/ChangeLog:

PR c++/94098
* g++.dg/ext/attr-access-2.C: New test.

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-attribs.c
gcc/calls.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/attr-access-2.C [new file with mode: 0644]

index 3a52840eff1a47917e658c44ec7bfe5ac71a3700..5f7081c9c1d29815b0458ea2a03b1569b399a889 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-27  Martin Sebor  <msebor@redhat.com>
+
+       PR c++/94098
+       * calls.c (init_attr_rdwr_indices): Iterate over all access attributes.
+
 2020-03-27  Andrew Stubbs  <ams@codesourcery.com>
 
        * config/gcn/gcn-valu.md:
index 0d805c64bdee33e754e130fbc985297f9259a116..30a18a36ac6aae163e58d7305993680f875ea7fe 100644 (file)
@@ -1,3 +1,9 @@
+2020-03-27  Martin Sebor  <msebor@redhat.com>
+
+       PR c++/94098
+       * c-attribs.c (handle_access_attribute): Avoid setting TYPE_ATTRIBUTES
+       here.
+
 2020-03-23  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/91993
index 9abf81d02481010de0eba15eaba22d63344209ab..f30158a258b586bbf05e53ea764b197702f411ff 100644 (file)
@@ -4182,7 +4182,6 @@ handle_access_attribute (tree *node, tree name, tree args,
 
   /* Replace any existing access attribute specification with
      the concatenation above.  */
-  attrs = remove_attribute (IDENTIFIER_POINTER (name), attrs);
   new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
   new_attrs = tree_cons (name, new_attrs, attrs);
 
@@ -4190,15 +4189,12 @@ handle_access_attribute (tree *node, tree name, tree args,
     {
       /* Repeat for the previously declared type.  */
       attrs = TYPE_ATTRIBUTES (TREE_TYPE (node[1]));
-      tree new_attrs
-       = append_access_attrs (node[1], attrs, attrstr, code, idxs);
-      if (!new_attrs)
+      tree attrs1 = append_access_attrs (node[1], attrs, attrstr, code, idxs);
+      if (!attrs1)
        return NULL_TREE;
 
-      attrs = remove_attribute (IDENTIFIER_POINTER (name), attrs);
-      new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
-      new_attrs = tree_cons (name, new_attrs, attrs);
-      TYPE_ATTRIBUTES (TREE_TYPE (node[1])) = new_attrs;
+      attrs1 = tree_cons (NULL_TREE, attrs1, NULL_TREE);
+      new_attrs = tree_cons (name, attrs1, attrs);
     }
 
   /* Recursively call self to "replace" the documented/external form
index 4c3a8f3c215d58918c07f3bd146692f946282d8b..5bd922779af7144a4310f963428f8d537b509938 100644 (file)
@@ -1873,7 +1873,7 @@ struct rdwr_access_hash: int_hash<int, -1> { };
 typedef hash_map<rdwr_access_hash, attr_access> rdwr_map;
 
 /* Initialize a mapping for a call to function FNDECL declared with
-   attribute access.  Each attribute poisitional operand inserts one
+   attribute access.  Each attribute positional operand inserts one
    entry into the mapping with the operand number as the key.  */
 
 static void
@@ -1882,54 +1882,50 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree fntype)
   if (!fntype)
     return;
 
-  tree access = TYPE_ATTRIBUTES (fntype);
-  /* If the function's type has no attributes there's nothing to do.  */
-  if (!access)
-    return;
-
-  access = lookup_attribute ("access", access);
-  if (!access)
-    return;
-
-  /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE
-     is the attribute argument's value.  */
-  tree mode = TREE_VALUE (access);
-  gcc_assert (TREE_CODE (mode) == TREE_LIST);
-  mode = TREE_VALUE (mode);
-  gcc_assert (TREE_CODE (mode) == STRING_CST);
-
-  const char *modestr = TREE_STRING_POINTER (mode);
-  for (const char *m = modestr; *m; )
+  for (tree access = TYPE_ATTRIBUTES (fntype);
+       (access = lookup_attribute ("access", access));
+       access = TREE_CHAIN (access))
     {
-      attr_access acc = { };
-
-      switch (*m)
+      /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE
+        is the attribute argument's value.  */
+      tree mode = TREE_VALUE (access);
+      gcc_assert (TREE_CODE (mode) == TREE_LIST);
+      mode = TREE_VALUE (mode);
+      gcc_assert (TREE_CODE (mode) == STRING_CST);
+
+      const char *modestr = TREE_STRING_POINTER (mode);
+      for (const char *m = modestr; *m; )
        {
-       case 'r': acc.mode = acc.read_only; break;
-       case 'w': acc.mode = acc.write_only; break;
-       default: acc.mode = acc.read_write; break;
-       }
+         attr_access acc = { };
 
-      char *end;
-      acc.ptrarg = strtoul (++m, &end, 10);
-      m = end;
-      if (*m == ',')
-       {
-         acc.sizarg = strtoul (++m, &end, 10);
+         switch (*m)
+           {
+           case 'r': acc.mode = acc.read_only; break;
+           case 'w': acc.mode = acc.write_only; break;
+           default: acc.mode = acc.read_write; break;
+           }
+
+         char *end;
+         acc.ptrarg = strtoul (++m, &end, 10);
          m = end;
-       }
-      else
-       acc.sizarg = UINT_MAX;
+         if (*m == ',')
+           {
+             acc.sizarg = strtoul (++m, &end, 10);
+             m = end;
+           }
+         else
+           acc.sizarg = UINT_MAX;
 
-      acc.ptr = NULL_TREE;
-      acc.size = NULL_TREE;
+         acc.ptr = NULL_TREE;
+         acc.size = NULL_TREE;
 
-      /* Unconditionally add an entry for the required pointer
-        operand of the attribute, and one for the optional size
-        operand when it's specified.  */
-      rwm->put (acc.ptrarg, acc);
-      if (acc.sizarg != UINT_MAX)
-       rwm->put (acc.sizarg, acc);
+         /* Unconditionally add an entry for the required pointer
+            operand of the attribute, and one for the optional size
+            operand when it's specified.  */
+         rwm->put (acc.ptrarg, acc);
+         if (acc.sizarg != UINT_MAX)
+           rwm->put (acc.sizarg, acc);
+       }
     }
 }
 
index 1de6c7ab2351491afd5266066af81b0d2405e287..d4c7d48466b1135696a0a37e5da51bef744135fc 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-27  Martin Sebor  <msebor@redhat.com>
+
+       PR c++/94098
+       * g++.dg/ext/attr-access-2.C: New test.
+
 2020-03-27  Martin Sebor  <msebor@redhat.com>
 
        PR c++/94078
diff --git a/gcc/testsuite/g++.dg/ext/attr-access-2.C b/gcc/testsuite/g++.dg/ext/attr-access-2.C
new file mode 100644 (file)
index 0000000..46f9075
--- /dev/null
@@ -0,0 +1,88 @@
+/* PR c++/94098 - checking ICE on attribute access redeclaration
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+#define RO(...)  __attribute__ ((access (read_only, __VA_ARGS__)))
+#define RW(...)  __attribute__ ((access (read_write, __VA_ARGS__)))
+#define WO(...)  __attribute__ ((access (write_only, __VA_ARGS__)))
+
+typedef __INT32_TYPE__ int32_t;
+
+int        rdwr1_2_3_4 (void*, void*, void*, void*);
+int RW (1) rdwr1_2_3_4 (void*, void*, void*, void*);
+int RW (2) rdwr1_2_3_4 (void*, void*, void*, void*);
+int RW (3) rdwr1_2_3_4 (void*, void*, void*, void*);
+int RW (4) rdwr1_2_3_4 (void*, void*, void*, void*);
+
+extern int32_t x[1];
+
+void call_rdwrp1_2_3_4 (void)
+{
+  rdwr1_2_3_4 (x, x, x, x);
+  rdwr1_2_3_4 (x, x, x, x + 1);     // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwr1_2_3_4 (x, x, x + 1, x);     // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwr1_2_3_4 (x, x + 1, x, x);     // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwr1_2_3_4 (x + 1, x, x, x);     // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+int        rdwr4_3_2_1 (void*, void*, void*, void*);
+int RW (4) rdwr4_3_2_1 (void*, void*, void*, void*);
+int RW (3) rdwr4_3_2_1 (void*, void*, void*, void*);
+int RW (2) rdwr4_3_2_1 (void*, void*, void*, void*);
+int RW (1) rdwr4_3_2_1 (void*, void*, void*, void*);
+
+void call_rdwr4_3_2_1 (void)
+{
+  rdwr4_3_2_1 (x, x, x, x);
+  rdwr4_3_2_1 (x, x, x, x + 1);     // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwr4_3_2_1 (x, x, x + 1, x);     // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwr4_3_2_1 (x, x + 1, x, x);     // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwr4_3_2_1 (x + 1, x, x, x);     // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+int                             rdwrall (void*, void*, void*, void*);
+int RW (1)                      rdwrall (void*, void*, void*, void*);
+int RW (1) RW (2)               rdwrall (void*, void*, void*, void*);
+int RW (1) RW (2) RW (3)        rdwrall (void*, void*, void*, void*);
+int RW (1) RW (2) RW (3) RW (4) rdwrall (void*, void*, void*, void*);
+
+void call_rdwrall (void)
+{
+  rdwrall (x, x, x, x);
+  rdwrall (x, x, x, x + 1);         // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwrall (x, x, x + 1, x);         // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwrall (x, x + 1, x, x);         // { dg-warning "\\\[-Wstringop-overflow" }
+  rdwrall (x + 1, x, x, x);         // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+// Verify the attribute is a part of the function's type.
+typedef __typeof__ (rdwrall) F;
+
+void call_fnptr_typeof (F *f)
+{
+  f (x, x, x, x);
+  f (x, x, x, x + 1);               // { dg-warning "\\\[-Wstringop-overflow" }
+  f (x, x, x + 1, x);               // { dg-warning "\\\[-Wstringop-overflow" }
+  f (x, x + 1, x, x);               // { dg-warning "\\\[-Wstringop-overflow" }
+  f (x + 1, x, x, x);               // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+
+// Verify the attribute is effective on a typedef.
+typedef        void FWRall (void*, void*, void*, void*);
+typedef RW (1) void FWRall (void*, void*, void*, void*);
+typedef RW (2) void FWRall (void*, void*, void*, void*);
+typedef RW (3) void FWRall (void*, void*, void*, void*);
+typedef RW (4) void FWRall (void*, void*, void*, void*);
+
+void call_fnptr (FWRall *f)
+{
+  f (x, x, x, x);
+  f (x, x, x, x + 1);               // { dg-warning "\\\[-Wstringop-overflow" "pr94171" { xfail *-*-* } }
+  f (x, x, x + 1, x);               // { dg-warning "\\\[-Wstringop-overflow" "pr94171" { xfail *-*-* } }
+  f (x, x + 1, x, x);               // { dg-warning "\\\[-Wstringop-overflow" "pr94171" { xfail *-*-* } }
+  f (x + 1, x, x, x);               // { dg-warning "\\\[-Wstringop-overflow" "pr94171" { xfail *-*-* } }
+}