Add two new c-family attributes, "btf_type_tag" and "btf_decl_tag" along with attribute handlers for them.
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. --- gcc/c-family/c-attribs.cc | 80 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 5a0e3d328ba..7183ba4b279 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -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 } @@ -640,7 +643,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 = @@ -5101,6 +5108,77 @@ handle_null_terminated_string_arg_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* 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 (!args) + *no_add_attrs = true; + else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute requires a string", name); + *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 (!args) + *no_add_attrs = true; + else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute requires a string", name); + *no_add_attrs = true; + } + + /* 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 -- 2.47.2