mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
c-family: add btf_type_tag and btf_decl_tag attributes
Add two new c-family attributes, "btf_type_tag" and "btf_decl_tag" along with attribute handlers for them. These attributes may be used to annotate types or declarations respectively with arbitrary strings, which will be recorded in DWARF and/or BTF information. Both attributes accept exactly one string argument. Wide strings are not supported. gcc/c-family/ * c-attribs.cc (c_common_attribute_table): Add btf_decl_tag and btf_type_tag attributes. (handle_btf_decl_tag_attribute): New handler for btf_decl_tag. (hanlde_btf_type_tag_attribute): New handler for btf_type_tag. (btf_tag_args_ok): Helper for new attribute handlers. gcc/testsuite/ * gcc.dg/attr-btf-decl-tag-1.c: New test. * gcc.dg/attr-btf-decl-tag-2.c: New test. * gcc.dg/attr-btf-type-tag-1.c: New test. * gcc.dg/attr-btf-type-tag-2.c: New test. * gcc.dg/attr-btf-type-tag-3.c: New test.
This commit is contained in:
@@ -189,6 +189,9 @@ static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *);
|
||||
|
||||
static tree handle_btf_decl_tag_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_btf_type_tag_attribute (tree *, tree, tree, int, bool *);
|
||||
|
||||
/* Helper to define attribute exclusions. */
|
||||
#define ATTR_EXCL(name, function, type, variable) \
|
||||
{ name, function, type, variable }
|
||||
@@ -657,7 +660,11 @@ const struct attribute_spec c_common_gnu_attributes[] =
|
||||
{ "flag_enum", 0, 0, false, true, false, false,
|
||||
handle_flag_enum_attribute, NULL },
|
||||
{ "null_terminated_string_arg", 1, 1, false, true, true, false,
|
||||
handle_null_terminated_string_arg_attribute, NULL}
|
||||
handle_null_terminated_string_arg_attribute, NULL},
|
||||
{ "btf_type_tag", 1, 1, false, true, false, false,
|
||||
handle_btf_type_tag_attribute, NULL},
|
||||
{ "btf_decl_tag", 1, 1, true, false, false, false,
|
||||
handle_btf_decl_tag_attribute, NULL}
|
||||
};
|
||||
|
||||
const struct scoped_attribute_specs c_common_gnu_attribute_table =
|
||||
@@ -5172,6 +5179,107 @@ handle_null_terminated_string_arg_attribute (tree *node, tree name, tree args,
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Common argument checking for btf_type_tag and btf_decl_tag.
|
||||
Return true if the ARGS are valid, otherwise emit an error and
|
||||
return false. */
|
||||
|
||||
static bool
|
||||
btf_tag_args_ok (tree name, tree args)
|
||||
{
|
||||
if (!args) /* Correct number of args (1) is checked for us. */
|
||||
return false;
|
||||
else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
|
||||
{
|
||||
error ("%qE attribute requires a string argument", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only narrow character strings are accepted. */
|
||||
tree argtype = TREE_TYPE (TREE_TYPE (TREE_VALUE (args)));
|
||||
if (!(argtype == char_type_node
|
||||
|| argtype == char8_type_node
|
||||
|| argtype == signed_char_type_node
|
||||
|| argtype == unsigned_char_type_node))
|
||||
{
|
||||
error ("unsupported wide string type argument in %qE attribute", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle the "btf_decl_tag" attribute. */
|
||||
|
||||
static tree
|
||||
handle_btf_decl_tag_attribute (tree * ARG_UNUSED (node), tree name, tree args,
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
{
|
||||
if (!btf_tag_args_ok (name, args))
|
||||
*no_add_attrs = true;
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle the "btf_type_tag" attribute. */
|
||||
|
||||
static tree
|
||||
handle_btf_type_tag_attribute (tree *node, tree name, tree args,
|
||||
int flags, bool *no_add_attrs)
|
||||
{
|
||||
if (!btf_tag_args_ok (name, args))
|
||||
{
|
||||
*no_add_attrs = true;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE)
|
||||
{
|
||||
warning (OPT_Wattributes,
|
||||
"%qE attribute does not apply to functions", name);
|
||||
*no_add_attrs = true;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Ensure a variant type is always created to hold the type_tag,
|
||||
unless ATTR_FLAG_IN_PLACE is set. Same logic as in
|
||||
common_handle_aligned_attribute. */
|
||||
tree decl = NULL_TREE;
|
||||
tree *type = NULL;
|
||||
bool is_type = false;
|
||||
|
||||
if (DECL_P (*node))
|
||||
{
|
||||
decl = *node;
|
||||
type = &TREE_TYPE (decl);
|
||||
is_type = TREE_CODE (*node) == TYPE_DECL;
|
||||
}
|
||||
else if (TYPE_P (*node))
|
||||
type = node, is_type = true;
|
||||
|
||||
if (is_type)
|
||||
{
|
||||
if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
|
||||
/* OK, modify the type in place. */;
|
||||
|
||||
/* If we have a TYPE_DECL, then copy the type, so that we
|
||||
don't accidentally modify a builtin type. See pushdecl. */
|
||||
else if (decl && TREE_TYPE (decl) != error_mark_node
|
||||
&& DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
|
||||
{
|
||||
tree tt = TREE_TYPE (decl);
|
||||
*type = build_variant_type_copy (*type);
|
||||
DECL_ORIGINAL_TYPE (decl) = tt;
|
||||
TYPE_NAME (*type) = decl;
|
||||
TREE_USED (*type) = TREE_USED (decl);
|
||||
TREE_TYPE (decl) = *type;
|
||||
}
|
||||
else
|
||||
*type = build_variant_type_copy (*type);
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle the "nonstring" variable attribute. */
|
||||
|
||||
static tree
|
||||
|
||||
14
gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c
Normal file
14
gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c
Normal file
@@ -0,0 +1,14 @@
|
||||
/* Test btf_decl_tag attribute argument checking. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
void *vptr __attribute__((btf_decl_tag("vptr"), btf_decl_tag ("perthread")));
|
||||
|
||||
struct Foo
|
||||
{
|
||||
int x __attribute__((btf_decl_tag (0x55))); /* { dg-error "requires a string" } */
|
||||
char *c __attribute__((btf_decl_tag (L"Lstr"))); /* { dg-error "unsupported wide string" } */
|
||||
};
|
||||
|
||||
extern int foo (int x, int y __attribute__((btf_decl_tag))); /* { dg-error "wrong number of arguments" } */
|
||||
|
||||
char *str __attribute__((btf_decl_tag("A", "B"))); /* { dg-error "wrong number of arguments" } */
|
||||
15
gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c
Normal file
15
gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Test btf_decl_tag attribute argument checking for wide string types. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "--std=c11" } */
|
||||
|
||||
int **my_ptr __attribute__((btf_decl_tag("my_ptr")));
|
||||
|
||||
void *x __attribute__((btf_decl_tag (U"Ustr"))); /* { dg-error "unsupported wide string" } */
|
||||
|
||||
const int y __attribute__((btf_decl_tag (u"ustr"))); /* { dg-error "unsupported wide string" } */
|
||||
|
||||
union U
|
||||
{
|
||||
int x;
|
||||
char c __attribute__((btf_decl_tag (u8"u8str"))); /* OK. */
|
||||
};
|
||||
12
gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c
Normal file
12
gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* Test btf_type_tag attribute argument checking. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
void * __attribute__((btf_type_tag ("A"), btf_type_tag ("vptr"))) a;
|
||||
|
||||
int __attribute__((btf_type_tag (5))) b; /* { dg-error "requires a string" } */
|
||||
|
||||
char * __attribute__((btf_type_tag (L"Lstr"))) c; /* { dg-error "unsupported wide string" } */
|
||||
|
||||
int * __attribute__((btf_type_tag)) d; /* { dg-error "wrong number of arguments" } */
|
||||
|
||||
char * __attribute__((btf_type_tag ("A", "B"))) e; /* { dg-error "wrong number of arguments" } */
|
||||
9
gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c
Normal file
9
gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c
Normal file
@@ -0,0 +1,9 @@
|
||||
/* Test btf_type_tag attribute argument checking for wide string types. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "--std=c11" } */
|
||||
|
||||
int __attribute__((btf_type_tag (U"Ustr"))) x; /* { dg-error "unsupported wide string" } */
|
||||
|
||||
int __attribute__((btf_type_tag (u"ustr"))) y; /* { dg-error "unsupported wide string" } */
|
||||
|
||||
int __attribute__((btf_type_tag (u8"u8str"))) z; /* OK. */
|
||||
8
gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c
Normal file
8
gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Test btf_type_tag attribute warnings. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
int __attribute__((btf_type_tag ("A"))) a (int x); /* { dg-warning "does not apply to functions" } */
|
||||
|
||||
__attribute__((btf_type_tag ("B"))) int *b (int y); /* { dg-warning "does not apply to functions" } */
|
||||
|
||||
int *c (int z) __attribute__((btf_type_tag ("C"))); /* { dg-warning "does not apply to functions" } */
|
||||
Reference in New Issue
Block a user