/* 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);
{
/* 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
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
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);
+ }
}
}
--- /dev/null
+/* 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 *-*-* } }
+}