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.
---
gcc/c-family/c-attribs.cc | 110 ++++++++++++++++++++-
gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c | 14 +++
gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c | 15 +++
gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c | 12 +++
gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c | 9 ++
gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c | 8 ++
6 files changed, 167 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c
create mode 100644 gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c
create mode 100644 gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c
create mode 100644 gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c
create mode 100644 gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 1e3a94ed949..a7d9656c2bd 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 =
@@ -5155,6 +5162,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
diff --git a/gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c
b/gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c
new file mode 100644
index 00000000000..d26d992c44d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-btf-decl-tag-1.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c
b/gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c
new file mode 100644
index 00000000000..956e20eb2ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-btf-decl-tag-2.c
@@ -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. */
+};
diff --git a/gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c
b/gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c
new file mode 100644
index 00000000000..2ed54ae5be3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-btf-type-tag-1.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c
b/gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c
new file mode 100644
index 00000000000..edc22b11ef8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-btf-type-tag-2.c
@@ -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. */
diff --git a/gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c
b/gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c
new file mode 100644
index 00000000000..afb14b12a22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-btf-type-tag-3.c
@@ -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" } */
--
2.47.3