From: Martin Sebor Date: Mon, 2 Mar 2020 00:58:45 +0000 (-0700) Subject: PR middle-end/92721 - checking ICE on attribute access redeclaration X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=649e174102a8ae2d570616d09aa336b712e1baae;p=gcc.git PR middle-end/92721 - checking ICE on attribute access redeclaration gcc/c-family/ChangeLog: PR c++/92721 * c-attribs.c (append_access_attrs): Correctly handle attribute. (handle_access_attribute): Same. gcc/ChangeLog: PR c++/92721 * calls.c (init_attr_rdwr_indices): Correctly handle attribute. gcc/testsuite/ChangeLog: PR c++/92721 g++.dg/ext/attr-access.C: New test. --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f186408e104..74a8b691ac9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2020-03-01 Martin Sebor + + PR c++/92721 + * calls.c (init_attr_rdwr_indices): Correctly handle attribute. + 2020-03-01 Martin Sebor PR middle-end/93829 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e47af7fb249..434bac6408d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2020-03-01 Martin Sebor + + PR c++/92721 + * c-attribs.c (append_access_attrs): Correctly handle attribute. + (handle_access_attribute): Same. + 2020-02-25 Jakub Jelinek PR c/93858 diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 2ea5fd5ff46..9abf81d0248 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -3845,6 +3845,10 @@ append_access_attrs (tree t, tree attrs, const char *attrstr, if (tree acs = lookup_attribute ("access", attrs)) { + /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE + is the attribute argument's value. */ + acs = TREE_VALUE (acs); + gcc_assert (TREE_CODE (acs) == TREE_LIST); acs = TREE_VALUE (acs); gcc_assert (TREE_CODE (acs) == STRING_CST); @@ -3971,11 +3975,20 @@ handle_access_attribute (tree *node, tree name, tree args, return NULL_TREE; } + tree access_mode = TREE_VALUE (args); + if (TREE_CODE (access_mode) == STRING_CST) + { + /* This must be a recursive call to handle the condensed internal + form of the attribute (see below). Since all validation has + been done simply return here, accepting the attribute as is. */ + *no_add_attrs = false; + return NULL_TREE; + } + /* Set to true when the access mode has the form of a function call as in 'attribute (read_only (1, 2))'. That's an easy mistake to make and so worth a special diagnostic. */ bool funcall = false; - tree access_mode = TREE_VALUE (args); if (TREE_CODE (access_mode) == CALL_EXPR) { access_mode = CALL_EXPR_FN (access_mode); @@ -4170,6 +4183,7 @@ 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); if (node[1]) @@ -4182,11 +4196,14 @@ handle_access_attribute (tree *node, tree name, tree args, 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; } - TYPE_ATTRIBUTES (*node) = new_attrs; + /* Recursively call self to "replace" the documented/external form + of the attribute with the condensend internal form. */ + decl_attributes (node, new_attrs, flags); return NULL_TREE; } diff --git a/gcc/calls.c b/gcc/calls.c index d1c53171176..4c3a8f3c215 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1891,8 +1891,13 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree fntype) 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; ) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 401c648819d..5c430242445 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-03-01 Martin Sebor + + PR c++/92721 + g++.dg/ext/attr-access.C: New test. + 2020-03-01 Martin Sebor PR middle-end/93926 diff --git a/gcc/testsuite/g++.dg/ext/attr-access.C b/gcc/testsuite/g++.dg/ext/attr-access.C new file mode 100644 index 00000000000..fcb54cd8861 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-access.C @@ -0,0 +1,109 @@ +/* PR middle-end/92721 - checking ICE on attribute access redeclaration + Test to verify the handling of attribute access combining multiple + declarations of the same function. + { dg-do compile } + { dg-options "-O0 -Wall -ftrack-macro-expansion=0" } */ + +#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; + +void RO (1) RO (1) rop1_ror2 (const int32_t*, const int32_t&); +void RO (1) RO (2) rop1_ror2 (const int32_t*, const int32_t&); +void RO (2) RO (1) rop1_ror2 (const int32_t*, const int32_t&); +void RO (2) RO (2) rop1_ror2 (const int32_t*, const int32_t&); + +void RW (1) RW (1) rdwrp1_rdwrr2 (int32_t*, int32_t&); +void RW (1) RW (2) rdwrp1_rdwrr2 (int32_t*, int32_t&); +void RW (2) RW (1) rdwrp1_rdwrr2 (int32_t*, int32_t&); +void RW (2) RW (2) rdwrp1_rdwrr2 (int32_t*, int32_t&); + +void WO (1) WO (1) wop1_wor2 (int32_t*, int32_t&); +void WO (1) WO (2) wop1_wor2 (int32_t*, int32_t&); +void WO (2) WO (1) wop1_wor2 (int32_t*, int32_t&); +void WO (2) WO (2) wop1_wor2 (int32_t*, int32_t&); + + +// Verify that everything works even with no optimization. + +void call_rop1_ror2_O0 (void) +{ + const int32_t x[1] = { }; + + rop1_ror2 (x, x[0]); + rop1_ror2 (x, x[1]); // { dg-warning "reading 4 bytes from a region of size 0" } + rop1_ror2 (x + 1, x[0]); // { dg-warning "reading 4 bytes from a region of size 0" } +} + +void call_rdwrp1_rdwrr2_O0 (void) +{ + int32_t x[1]; + + rdwrp1_rdwrr2 (x, x[0]); + rdwrp1_rdwrr2 (x, x[1]); // { dg-warning "writing 4 bytes into a region of size 0" } + rdwrp1_rdwrr2 (x + 1, x[0]); // { dg-warning "writing 4 bytes into a region of size 0" } +} + +void call_wop1_wor2_O0 (void) +{ + int32_t x[1]; + + wop1_wor2 (x, x[0]); + wop1_wor2 (x, x[1]); // { dg-warning "writing 4 bytes into a region of size 0" } + wop1_wor2 (x + 1, x[0]); // { dg-warning "writing 4 bytes into a region of size 0" } +} + + +// Verify that everything still works with -O1. + +#pragma GCC optimize "1" + +void call_rop1_ror2_O1 (void) +{ + const int32_t x[1] = { 1 }; + const int32_t *p0 = x, &r0 = x[0]; + const int32_t *p1 = (const int32_t*)((const char*)p0 + 1); + const int32_t &r2 = *(const int32_t*)((const char*)p1 + 1); + + rop1_ror2 (x, x[0]); + rop1_ror2 (x, x[1]); // { dg-warning "reading 4 bytes from a region of size 0" } + rop1_ror2 (x + 1, x[0]); // { dg-warning "reading 4 bytes from a region of size 0" } + + rop1_ror2 (p0, r0); + rop1_ror2 (p0, r2); // { dg-warning "reading 4 bytes from a region of size 2" } + rop1_ror2 (p1, r0); // { dg-warning "reading 4 bytes from a region of size 3" } +} + +void call_rdwrp1_rdwrr2_O1 (void) +{ + int32_t x[1]; + int32_t *p0 = x, &r0 = x[0]; + int32_t *p1 = (int32_t*)((char*)p0 + 1); + int32_t &r2 = *(int32_t*)((char*)p1 + 1); + + rdwrp1_rdwrr2 (x, x[0]); + rdwrp1_rdwrr2 (x, x[1]); // { dg-warning "writing 4 bytes into a region of size 0" } + rdwrp1_rdwrr2 (x + 1, x[0]); // { dg-warning "writing 4 bytes into a region of size 0" } + + rdwrp1_rdwrr2 (p0, r0); + rdwrp1_rdwrr2 (p0, r2); // { dg-warning "writing 4 bytes into a region of size 2" } + rdwrp1_rdwrr2 (p1, r0); // { dg-warning "writing 4 bytes into a region of size 3" } +} + +void call_wop1_wor2_O1 (void) +{ + int32_t x[1]; + int32_t *p0 = x, &r0 = x[0]; + int32_t *p1 = (int32_t*)((char*)p0 + 1); + int32_t &r2 = *(int32_t*)((char*)p1 + 1); + + wop1_wor2 (x, x[0]); + wop1_wor2 (x, x[1]); // { dg-warning "writing 4 bytes into a region of size 0" } + wop1_wor2 (x + 1, x[0]); // { dg-warning "writing 4 bytes into a region of size 0" } + + wop1_wor2 (p0, r0); + wop1_wor2 (p0, r2); // { dg-warning "writing 4 bytes into a region of size 2" } + wop1_wor2 (p1, r0); // { dg-warning "writing 4 bytes into a region of size 3" } +}