190 lines
6.2 KiB
Diff
190 lines
6.2 KiB
Diff
|
|
From 8c6ffb4c6f86231eee318ceeb8546a53037edfe9 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Jakub Jelinek <jakub@redhat.com>
|
||
|
|
Date: Tue, 4 Oct 2022 23:13:15 +0200
|
||
|
|
Subject: [PATCH 128/157] [Backport][SME] attribs: Add overloads with namespace
|
||
|
|
name
|
||
|
|
|
||
|
|
Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0764dc8537a4f87089ecd32391cb5f8803b43c96
|
||
|
|
|
||
|
|
I've discovered a problem with the way we handle scoped attributes. For
|
||
|
|
declaration or type attributes for attributes we don't know anything about
|
||
|
|
we just don't add them to the declarations or types, so later in the FEs and
|
||
|
|
middle-end it is fine to use lookup_attribute etc. which just check the
|
||
|
|
attribute name and not namespace because non-standard non-GNU attributes
|
||
|
|
just won't show there. But in the case of attributes on statements, nothing
|
||
|
|
has filtered out the unknown attributes, so with my earlier assume
|
||
|
|
attribute patch e.g. c-c++-common/Wno-attributes-6.c test failed because
|
||
|
|
it uses:
|
||
|
|
[[vendor::assume(1 + 1 == 2)]];
|
||
|
|
with -Wno-attributes=vendor::assume and lookup_attribute ("assume", )
|
||
|
|
finds such attribute and handled it that way.
|
||
|
|
So, for those cases, this patch introduces lookup_attribute and
|
||
|
|
remove_attribute overloads which specify also the namespace.
|
||
|
|
I think the fallthrough, hot, cold, likely, unlikely attribute handling
|
||
|
|
will need to use the new APIs too, so that we don't handle
|
||
|
|
msft::fallthrough attribute as something we'd know.
|
||
|
|
|
||
|
|
2022-10-04 Jakub Jelinek <jakub@redhat.com>
|
||
|
|
|
||
|
|
* attribs.h (remove_attribute): Declare overload with additional
|
||
|
|
attr_ns argument.
|
||
|
|
(private_lookup_attribute): Declare overload with additional
|
||
|
|
attr_ns and attr_ns_len arguments.
|
||
|
|
(lookup_attribute): New overload with additional attr_ns argument.
|
||
|
|
* attribs.cc (remove_attribute): New overload with additional
|
||
|
|
attr_ns argument.
|
||
|
|
(private_lookup_attribute): New overload with additional
|
||
|
|
attr_ns and attr_ns_len arguments.
|
||
|
|
---
|
||
|
|
gcc/attribs.cc | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
gcc/attribs.h | 38 ++++++++++++++++++++++++++++++
|
||
|
|
2 files changed, 101 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
|
||
|
|
index 656ea739e..8e2696bc5 100644
|
||
|
|
--- a/gcc/attribs.cc
|
||
|
|
+++ b/gcc/attribs.cc
|
||
|
|
@@ -1598,6 +1598,36 @@ remove_attribute (const char *attr_name, tree list)
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Similarly but also match namespace on the removed attributes. */
|
||
|
|
+
|
||
|
|
+tree
|
||
|
|
+remove_attribute (const char *attr_ns, const char *attr_name, tree list)
|
||
|
|
+{
|
||
|
|
+ tree *p;
|
||
|
|
+ gcc_checking_assert (attr_name[0] != '_');
|
||
|
|
+ gcc_checking_assert (attr_ns == NULL || attr_ns[0] != '_');
|
||
|
|
+
|
||
|
|
+ for (p = &list; *p;)
|
||
|
|
+ {
|
||
|
|
+ tree l = *p;
|
||
|
|
+
|
||
|
|
+ tree attr = get_attribute_name (l);
|
||
|
|
+ if (is_attribute_p (attr_name, attr))
|
||
|
|
+ {
|
||
|
|
+ tree ns = get_attribute_namespace (l);
|
||
|
|
+ if ((ns == NULL_TREE && attr_ns == NULL)
|
||
|
|
+ || (ns && attr_ns && is_attribute_p (attr_ns, ns)))
|
||
|
|
+ {
|
||
|
|
+ *p = TREE_CHAIN (l);
|
||
|
|
+ continue;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ p = &TREE_CHAIN (l);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return list;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Return an attribute list that is the union of a1 and a2. */
|
||
|
|
|
||
|
|
tree
|
||
|
|
@@ -1995,6 +2025,39 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Similarly but with also attribute namespace. */
|
||
|
|
+
|
||
|
|
+tree
|
||
|
|
+private_lookup_attribute (const char *attr_ns, const char *attr_name,
|
||
|
|
+ size_t attr_ns_len, size_t attr_len, tree list)
|
||
|
|
+{
|
||
|
|
+ while (list)
|
||
|
|
+ {
|
||
|
|
+ tree attr = get_attribute_name (list);
|
||
|
|
+ size_t ident_len = IDENTIFIER_LENGTH (attr);
|
||
|
|
+ if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr),
|
||
|
|
+ ident_len))
|
||
|
|
+ {
|
||
|
|
+ tree ns = get_attribute_namespace (list);
|
||
|
|
+ if (ns == NULL_TREE)
|
||
|
|
+ {
|
||
|
|
+ if (attr_ns == NULL)
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+ else if (attr_ns)
|
||
|
|
+ {
|
||
|
|
+ ident_len = IDENTIFIER_LENGTH (ns);
|
||
|
|
+ if (cmp_attribs (attr_ns, attr_ns_len, IDENTIFIER_POINTER (ns),
|
||
|
|
+ ident_len))
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ list = TREE_CHAIN (list);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return list;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Return true if the function decl or type NODE has been declared
|
||
|
|
with attribute ANAME among attributes ATTRS. */
|
||
|
|
|
||
|
|
diff --git a/gcc/attribs.h b/gcc/attribs.h
|
||
|
|
index 0856f98fb..9ad530fcb 100644
|
||
|
|
--- a/gcc/attribs.h
|
||
|
|
+++ b/gcc/attribs.h
|
||
|
|
@@ -88,6 +88,10 @@ extern tree merge_type_attributes (tree, tree);
|
||
|
|
|
||
|
|
extern tree remove_attribute (const char *, tree);
|
||
|
|
|
||
|
|
+/* Similarly but also with specific attribute namespace. */
|
||
|
|
+
|
||
|
|
+extern tree remove_attribute (const char *, const char *, tree);
|
||
|
|
+
|
||
|
|
/* Given two attributes lists, return a list of their union. */
|
||
|
|
|
||
|
|
extern tree merge_attributes (tree, tree);
|
||
|
|
@@ -119,6 +123,10 @@ extern int attribute_list_contained (const_tree, const_tree);
|
||
|
|
for size. */
|
||
|
|
extern tree private_lookup_attribute (const char *attr_name, size_t attr_len,
|
||
|
|
tree list);
|
||
|
|
+extern tree private_lookup_attribute (const char *attr_ns,
|
||
|
|
+ const char *attr_name,
|
||
|
|
+ size_t attr_ns_len, size_t attr_len,
|
||
|
|
+ tree list);
|
||
|
|
|
||
|
|
extern unsigned decls_mismatched_attributes (tree, tree, tree,
|
||
|
|
const char* const[],
|
||
|
|
@@ -215,6 +223,36 @@ lookup_attribute (const char *attr_name, tree list)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Similar to lookup_attribute, but also match the attribute namespace. */
|
||
|
|
+
|
||
|
|
+static inline tree
|
||
|
|
+lookup_attribute (const char *attr_ns, const char *attr_name, tree list)
|
||
|
|
+{
|
||
|
|
+ if (CHECKING_P && attr_name[0] != '_')
|
||
|
|
+ {
|
||
|
|
+ size_t attr_len = strlen (attr_name);
|
||
|
|
+ gcc_checking_assert (!canonicalize_attr_name (attr_name, attr_len));
|
||
|
|
+ }
|
||
|
|
+ if (CHECKING_P && attr_ns && attr_ns[0] != '_')
|
||
|
|
+ {
|
||
|
|
+ size_t attr_ns_len = strlen (attr_ns);
|
||
|
|
+ gcc_checking_assert (!canonicalize_attr_name (attr_ns, attr_ns_len));
|
||
|
|
+ }
|
||
|
|
+ /* In most cases, list is NULL_TREE. */
|
||
|
|
+ if (list == NULL_TREE)
|
||
|
|
+ return NULL_TREE;
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ size_t attr_ns_len = attr_ns ? strlen (attr_ns) : 0;
|
||
|
|
+ size_t attr_len = strlen (attr_name);
|
||
|
|
+ /* Do the strlen() before calling the out-of-line implementation.
|
||
|
|
+ In most cases attr_name is a string constant, and the compiler
|
||
|
|
+ will optimize the strlen() away. */
|
||
|
|
+ return private_lookup_attribute (attr_ns, attr_name,
|
||
|
|
+ attr_ns_len, attr_len, list);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Given an attribute name ATTR_NAME and a list of attributes LIST,
|
||
|
|
return a pointer to the attribute's list first element if the attribute
|
||
|
|
starts with ATTR_NAME. ATTR_NAME must be in the form 'text' (not
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|