PR middle-end/97879 - ICE on invalid mode in attribute access
gcc/c-family/ChangeLog: PR middle-end/97879 * c-attribs.c (handle_access_attribute): Handle ATTR_FLAG_INTERNAL. Error out on invalid modes. gcc/c/ChangeLog: PR middle-end/97879 * c-decl.c (start_function): Set ATTR_FLAG_INTERNAL in flags. gcc/ChangeLog: PR middle-end/97879 * tree-core.h (enum attribute_flags): Add ATTR_FLAG_INTERNAL. gcc/testsuite/ChangeLog: PR middle-end/97879 * gcc.dg/attr-access-3.c: New test.
This commit is contained in:
parent
a01dda3c23
commit
df90f07037
|
@ -2810,9 +2810,11 @@ handle_copy_attribute (tree *node, tree name, tree args,
|
|||
tree attrs = TYPE_ATTRIBUTES (reftype);
|
||||
|
||||
/* Copy type attributes from REF to DECL. Pass in REF if it's a DECL
|
||||
or a type but not if it's an expression. */
|
||||
or a type but not if it's an expression. Set ATTR_FLAG_INTERNAL
|
||||
since the attributes' arguments may be in their internal form. */
|
||||
for (tree at = attrs; at; at = TREE_CHAIN (at))
|
||||
decl_attributes (node, at, flags, EXPR_P (ref) ? NULL_TREE : ref);
|
||||
decl_attributes (node, at, flags | ATTR_FLAG_INTERNAL,
|
||||
EXPR_P (ref) ? NULL_TREE : ref);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
@ -4289,8 +4291,8 @@ append_access_attr (tree node[3], tree attrs, const char *attrstr,
|
|||
the attribute and its arguments into a string. */
|
||||
|
||||
static tree
|
||||
handle_access_attribute (tree node[3], tree name, tree args,
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
handle_access_attribute (tree node[3], tree name, tree args, int flags,
|
||||
bool *no_add_attrs)
|
||||
{
|
||||
tree attrs = TYPE_ATTRIBUTES (*node);
|
||||
tree type = *node;
|
||||
|
@ -4336,15 +4338,19 @@ handle_access_attribute (tree node[3], tree name, tree args,
|
|||
|
||||
/* Recursively call self to "replace" the documented/external
|
||||
form of the attribute with the condensend internal form. */
|
||||
decl_attributes (node, axsat, flags);
|
||||
decl_attributes (node, axsat, flags | ATTR_FLAG_INTERNAL);
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* This is 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;
|
||||
if (flags & ATTR_FLAG_INTERNAL)
|
||||
{
|
||||
/* This is 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
|
||||
|
@ -4363,6 +4369,13 @@ handle_access_attribute (tree node[3], tree name, tree args,
|
|||
access_mode = DECL_NAME (access_mode);
|
||||
funcall = true;
|
||||
}
|
||||
else if (TREE_CODE (access_mode) != IDENTIFIER_NODE)
|
||||
{
|
||||
error ("attribute %qE mode %qE is not an identifier; expected one of "
|
||||
"%qs, %qs, %qs, or %qs", name, access_mode,
|
||||
"read_only", "read_write", "write_only", "none");
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
const char* const access_str = IDENTIFIER_POINTER (access_mode);
|
||||
const char *ps = access_str;
|
||||
|
@ -4573,7 +4586,7 @@ handle_access_attribute (tree node[3], tree name, tree args,
|
|||
|
||||
/* Recursively call self to "replace" the documented/external form
|
||||
of the attribute with the condensed internal form. */
|
||||
decl_attributes (node, new_attrs, flags);
|
||||
decl_attributes (node, new_attrs, flags | ATTR_FLAG_INTERNAL);
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
|
|
@ -9598,7 +9598,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
|
|||
current_function_decl = pushdecl (decl1);
|
||||
|
||||
if (tree access = build_attr_access_from_parms (parms, false))
|
||||
decl_attributes (¤t_function_decl, access, 0, old_decl);
|
||||
decl_attributes (¤t_function_decl, access, ATTR_FLAG_INTERNAL,
|
||||
old_decl);
|
||||
|
||||
push_scope ();
|
||||
declare_parm_level ();
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* PR middle-end/97879 - ICE on invalid mode in attribute access
|
||||
{ dg-do compile }
|
||||
{ dg-options "-Wall" } */
|
||||
|
||||
#define A(...) __attribute__ ((access (__VA_ARGS__)))
|
||||
|
||||
A (" ", 1) void f1 (int *); // { dg-error "attribute 'access' mode '\" \"' is not an identifier; expected one of 'read_only', 'read_write', 'write_only', or 'none'" }
|
||||
void f1 (int *);
|
||||
|
||||
|
||||
A ("none", 1) void f2 (char *); // { dg-error "not an identifier" }
|
||||
void f2 (char *);
|
||||
|
||||
A (1) void f3 (); // { dg-error "not an identifier" }
|
||||
|
||||
A (1, 2) void f4 (); // { dg-error "not an identifier" }
|
||||
A (2., 3.) void f5 (); // { dg-error "not an identifier" }
|
||||
|
||||
// Verify that copying a valid access attribute doesn't cause errors.
|
||||
A (read_only, 1, 2) void f6 (void*, int);
|
||||
__attribute__ ((copy (f6))) void f7 (void*, int);
|
|
@ -859,7 +859,10 @@ enum attribute_flags {
|
|||
are not in fact compatible with the function type. */
|
||||
ATTR_FLAG_BUILT_IN = 16,
|
||||
/* A given attribute has been parsed as a C++-11 attribute. */
|
||||
ATTR_FLAG_CXX11 = 32
|
||||
ATTR_FLAG_CXX11 = 32,
|
||||
/* The attribute handler is being invoked with an internal argument
|
||||
that may not otherwise be valid when specified in source code. */
|
||||
ATTR_FLAG_INTERNAL = 64
|
||||
};
|
||||
|
||||
/* Types used to represent sizes. */
|
||||
|
|
Loading…
Reference in New Issue