diff options
author | Martin Sebor <msebor@redhat.com> | 2020-03-01 17:58:45 -0700 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-03-01 17:58:45 -0700 |
commit | 649e174102a8ae2d570616d09aa336b712e1baae (patch) | |
tree | 0a9d51cdfc11c504a79a9f42d59f35f97847f62e | |
parent | 726e292d410fc29812a95eb6d88a2ceb82d9080d (diff) | |
download | gcc-649e174102a8ae2d570616d09aa336b712e1baae.zip gcc-649e174102a8ae2d570616d09aa336b712e1baae.tar.gz gcc-649e174102a8ae2d570616d09aa336b712e1baae.tar.bz2 |
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.
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-family/c-attribs.c | 21 | ||||
-rw-r--r-- | gcc/calls.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-access.C | 109 |
6 files changed, 149 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f186408..74a8b69 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2020-03-01 Martin Sebor <msebor@redhat.com> + PR c++/92721 + * calls.c (init_attr_rdwr_indices): Correctly handle attribute. + +2020-03-01 Martin Sebor <msebor@redhat.com> + PR middle-end/93829 * tree-ssa-strlen.c (count_nonzero_bytes): Set the size to that of a pointer in the outermost ADDR_EXPRs. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e47af7f..434bac6 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2020-03-01 Martin Sebor <msebor@redhat.com> + + PR c++/92721 + * c-attribs.c (append_access_attrs): Correctly handle attribute. + (handle_access_attribute): Same. + 2020-02-25 Jakub Jelinek <jakub@redhat.com> PR c/93858 diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 2ea5fd5..9abf81d 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 d1c5317..4c3a8f3 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 401c648..5c43024 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2020-03-01 Martin Sebor <msebor@redhat.com> + PR c++/92721 + g++.dg/ext/attr-access.C: New test. + +2020-03-01 Martin Sebor <msebor@redhat.com> + PR middle-end/93926 * gcc.dg/Wbuiltin-declaration-mismatch-13.c: New test. 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 0000000..fcb54cd --- /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" } +} |