aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-03-27 13:54:22 -0600
committerMartin Sebor <msebor@redhat.com>2020-03-27 13:54:22 -0600
commitccacf77be5508dd5b4df59f402965196d11edb05 (patch)
tree3075596dc7eefeb4b555b569ab76387f07eb17a5
parent038769535a8cbdd3dd3e100bde3140df52f868c5 (diff)
downloadgcc-ccacf77be5508dd5b4df59f402965196d11edb05.zip
gcc-ccacf77be5508dd5b4df59f402965196d11edb05.tar.gz
gcc-ccacf77be5508dd5b4df59f402965196d11edb05.tar.bz2
PR c++/94098 - ICE on attribute access redeclaration
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.
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-attribs.c12
-rw-r--r--gcc/calls.c82
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-access-2.C88
6 files changed, 147 insertions, 51 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3a52840..5f7081c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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:
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 0d805c6..30a18a3 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 9abf81d..f30158a 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -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
diff --git a/gcc/calls.c b/gcc/calls.c
index 4c3a8f3..5bd9227 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -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);
+ }
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1de6c7a..d4c7d48 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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
PR c++/93824
PR c++/93810
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
index 0000000..46f9075
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-access-2.C
@@ -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 *-*-* } }
+}