Commit ccacf77b by Martin Sebor

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.
parent 03876953
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> 2020-03-27 Andrew Stubbs <ams@codesourcery.com>
* config/gcn/gcn-valu.md: * config/gcn/gcn-valu.md:
......
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> 2020-03-23 Jakub Jelinek <jakub@redhat.com>
PR c++/91993 PR c++/91993
......
...@@ -4182,7 +4182,6 @@ handle_access_attribute (tree *node, tree name, tree args, ...@@ -4182,7 +4182,6 @@ handle_access_attribute (tree *node, tree name, tree args,
/* Replace any existing access attribute specification with /* Replace any existing access attribute specification with
the concatenation above. */ the concatenation above. */
attrs = remove_attribute (IDENTIFIER_POINTER (name), attrs);
new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE); new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
new_attrs = tree_cons (name, new_attrs, attrs); new_attrs = tree_cons (name, new_attrs, attrs);
...@@ -4190,15 +4189,12 @@ handle_access_attribute (tree *node, tree name, tree args, ...@@ -4190,15 +4189,12 @@ handle_access_attribute (tree *node, tree name, tree args,
{ {
/* Repeat for the previously declared type. */ /* Repeat for the previously declared type. */
attrs = TYPE_ATTRIBUTES (TREE_TYPE (node[1])); attrs = TYPE_ATTRIBUTES (TREE_TYPE (node[1]));
tree new_attrs tree attrs1 = append_access_attrs (node[1], attrs, attrstr, code, idxs);
= append_access_attrs (node[1], attrs, attrstr, code, idxs); if (!attrs1)
if (!new_attrs)
return NULL_TREE; return NULL_TREE;
attrs = remove_attribute (IDENTIFIER_POINTER (name), attrs); attrs1 = tree_cons (NULL_TREE, attrs1, NULL_TREE);
new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE); new_attrs = tree_cons (name, attrs1, attrs);
new_attrs = tree_cons (name, new_attrs, attrs);
TYPE_ATTRIBUTES (TREE_TYPE (node[1])) = new_attrs;
} }
/* Recursively call self to "replace" the documented/external form /* Recursively call self to "replace" the documented/external form
......
...@@ -1873,7 +1873,7 @@ struct rdwr_access_hash: int_hash<int, -1> { }; ...@@ -1873,7 +1873,7 @@ struct rdwr_access_hash: int_hash<int, -1> { };
typedef hash_map<rdwr_access_hash, attr_access> rdwr_map; typedef hash_map<rdwr_access_hash, attr_access> rdwr_map;
/* Initialize a mapping for a call to function FNDECL declared with /* 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. */ entry into the mapping with the operand number as the key. */
static void static void
...@@ -1882,54 +1882,50 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree fntype) ...@@ -1882,54 +1882,50 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree fntype)
if (!fntype) if (!fntype)
return; return;
tree access = TYPE_ATTRIBUTES (fntype); for (tree access = TYPE_ATTRIBUTES (fntype);
/* If the function's type has no attributes there's nothing to do. */ (access = lookup_attribute ("access", access));
if (!access) access = TREE_CHAIN (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; )
{ {
attr_access acc = { }; /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE
is the attribute argument's value. */
switch (*m) 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; attr_access acc = { };
case 'w': acc.mode = acc.write_only; break;
default: acc.mode = acc.read_write; break;
}
char *end; switch (*m)
acc.ptrarg = strtoul (++m, &end, 10); {
m = end; case 'r': acc.mode = acc.read_only; break;
if (*m == ',') case 'w': acc.mode = acc.write_only; break;
{ default: acc.mode = acc.read_write; break;
acc.sizarg = strtoul (++m, &end, 10); }
char *end;
acc.ptrarg = strtoul (++m, &end, 10);
m = end; m = end;
} if (*m == ',')
else {
acc.sizarg = UINT_MAX; acc.sizarg = strtoul (++m, &end, 10);
m = end;
}
else
acc.sizarg = UINT_MAX;
acc.ptr = NULL_TREE; acc.ptr = NULL_TREE;
acc.size = NULL_TREE; acc.size = NULL_TREE;
/* Unconditionally add an entry for the required pointer /* Unconditionally add an entry for the required pointer
operand of the attribute, and one for the optional size operand of the attribute, and one for the optional size
operand when it's specified. */ operand when it's specified. */
rwm->put (acc.ptrarg, acc); rwm->put (acc.ptrarg, acc);
if (acc.sizarg != UINT_MAX) if (acc.sizarg != UINT_MAX)
rwm->put (acc.sizarg, acc); rwm->put (acc.sizarg, acc);
}
} }
} }
......
2020-03-27 Martin Sebor <msebor@redhat.com> 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++/94078
PR c++/93824 PR c++/93824
PR c++/93810 PR c++/93810
......
/* 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 *-*-* } }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment