From ccacf77be5508dd5b4df59f402965196d11edb05 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 27 Mar 2020 13:54:22 -0600 Subject: [PATCH] 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. --- gcc/ChangeLog | 5 ++ gcc/c-family/ChangeLog | 6 ++ gcc/c-family/c-attribs.c | 12 ++-- gcc/calls.c | 82 +++++++++++----------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/ext/attr-access-2.C | 88 ++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 51 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/attr-access-2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a52840eff1..5f7081c9c1d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2020-03-27 Martin Sebor + + PR c++/94098 + * calls.c (init_attr_rdwr_indices): Iterate over all access attributes. + 2020-03-27 Andrew Stubbs * config/gcn/gcn-valu.md: diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 0d805c64bde..30a18a36ac6 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2020-03-27 Martin Sebor + + PR c++/94098 + * c-attribs.c (handle_access_attribute): Avoid setting TYPE_ATTRIBUTES + here. + 2020-03-23 Jakub Jelinek PR c++/91993 diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 9abf81d0248..f30158a258b 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 4c3a8f3c215..5bd922779af 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1873,7 +1873,7 @@ struct rdwr_access_hash: int_hash { }; typedef hash_map 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 1de6c7ab235..d4c7d48466b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-03-27 Martin Sebor + + PR c++/94098 + * g++.dg/ext/attr-access-2.C: New test. + 2020-03-27 Martin Sebor 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 index 00000000000..46f9075a6c6 --- /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 *-*-* } } +} -- 2.30.2