public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-3149] c++: Improve handling of foreigner namespace attributes
@ 2022-10-07  7:05 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-10-07  7:05 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:88f04e90f63f08620cc9cd2f059a1315b70bed3b

commit r13-3149-g88f04e90f63f08620cc9cd2f059a1315b70bed3b
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Oct 7 09:01:04 2022 +0200

    c++: Improve handling of foreigner namespace attributes
    
    In some cases we want to look up or remove both standard
    attributes and attributes from gnu namespace but not others.
    This patch arranges for ATTR_NS of "" to stand for ATTR_NS
    NULL or "gnu", so that we don't need 2 separate calls, and
    introduces is_attribute_namespace_p function which allows
    testing the namespace of an attribute similar way.
    
    The patch also uses the new lookup_attribute overload and extra
    tests to avoid emitting weird warnings on foreign namespace attributes
    which we should just ignore (perhaps with a warning), but shouldn't
    imply any meaning to them just because they have a name matching some
    standard or gnu attribute name.
    
    2022-10-07  Jakub Jelinek  <jakub@redhat.com>
    
    gcc/
            * attribs.h (is_attribute_namespace_p): New inline function.
            (lookup_attribute): Document meaning of ATTR_NS equal to "".
            * attribs.cc (remove_attribute): Use is_attribute_namespace_p.
            (private_lookup_attribute): For ATTR_NS "" match either standard
            attribute or "gnu" namespace one.
    gcc/c-family/
            * c-common.cc (attribute_fallthrough_p): Lookup fallthrough attribute
            only in gnu namespace or as standard attribute, treat fallthrough
            attributes in other namespaces like any other unknown attribute.
    gcc/cp/
            * parser.cc (cp_parser_check_std_attribute): Only do checks if
            attribute is a standard attribute or in gnu namespace and only
            lookup other attributes in those namespaces.
            * cp-gimplify.cc (lookup_hotness_attribute): Adjust function comment.
            Only return true for standard attribute or gnu namespace attribute.
            (remove_hotness_attribute): Only remove hotness attributes when
            they are standard or in gnu namespace, implement it in a single
            loop rather than former 4 now 8 remove_attribute calls.
    gcc/testsuite/
            * g++.dg/cpp1z/fallthrough2.C: New test.
            * g++.dg/cpp2a/attr-likely7.C: New test.

Diff:
---
 gcc/attribs.cc                            | 27 ++++++++++++----------
 gcc/attribs.h                             | 19 +++++++++++++++-
 gcc/c-family/c-common.cc                  |  7 +++---
 gcc/cp/cp-gimplify.cc                     | 32 ++++++++++++++++++--------
 gcc/cp/parser.cc                          |  3 ++-
 gcc/testsuite/g++.dg/cpp1z/fallthrough2.C | 24 +++++++++++++++++++
 gcc/testsuite/g++.dg/cpp2a/attr-likely7.C | 38 +++++++++++++++++++++++++++++++
 7 files changed, 123 insertions(+), 27 deletions(-)

diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index 38f3e926fed..27dea748561 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -1645,7 +1645,8 @@ remove_attribute (const char *attr_name, tree list)
   return list;
 }
 
-/* Similarly but also match namespace on the removed attributes.  */
+/* Similarly but also match namespace on the removed attributes.
+   ATTR_NS "" stands for NULL or "gnu" namespace.  */
 
 tree
 remove_attribute (const char *attr_ns, const char *attr_name, tree list)
@@ -1659,15 +1660,11 @@ remove_attribute (const char *attr_ns, const char *attr_name, tree list)
       tree l = *p;
 
       tree attr = get_attribute_name (l);
-      if (is_attribute_p (attr_name, attr))
+      if (is_attribute_p (attr_name, attr)
+	  && is_attribute_namespace_p (attr_ns, l))
 	{
-	  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);
+	  continue;
 	}
       p = &TREE_CHAIN (l);
     }
@@ -2088,14 +2085,20 @@ private_lookup_attribute (const char *attr_ns, const char *attr_name,
 	  tree ns = get_attribute_namespace (list);
 	  if (ns == NULL_TREE)
 	    {
-	      if (attr_ns == NULL)
+	      if (attr_ns_len == 0)
 		break;
 	    }
 	  else if (attr_ns)
 	    {
 	      ident_len = IDENTIFIER_LENGTH (ns);
-	      if (cmp_attribs (attr_ns, attr_ns_len, IDENTIFIER_POINTER (ns),
-			       ident_len))
+	      if (attr_ns_len == 0)
+		{
+		  if (cmp_attribs ("gnu", strlen ("gnu"),
+				   IDENTIFIER_POINTER (ns), ident_len))
+		    break;
+		}
+	      else if (cmp_attribs (attr_ns, attr_ns_len,
+				    IDENTIFIER_POINTER (ns), ident_len))
 		break;
 	    }
 	}
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 121b9ebbc39..1dc16e4bc4e 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -188,6 +188,22 @@ is_attribute_p (const char *attr_name, const_tree ident)
 		      IDENTIFIER_POINTER (ident), IDENTIFIER_LENGTH (ident));
 }
 
+/* Given an attribute ATTR and a string ATTR_NS, return true
+   if the attribute namespace is valid for the string.  ATTR_NS "" stands
+   for standard attribute (NULL get_attribute_namespace) or "gnu"
+   namespace.  */
+
+static inline bool
+is_attribute_namespace_p (const char *attr_ns, const_tree attr)
+{
+  tree ident = get_attribute_namespace (attr);
+  if (attr_ns == NULL)
+    return ident == NULL_TREE;
+  if (attr_ns[0])
+    return ident && is_attribute_p (attr_ns, ident);
+  return ident == NULL_TREE || is_attribute_p ("gnu", ident);
+}
+
 /* Given an attribute name ATTR_NAME and a list of attributes LIST,
    return a pointer to the attribute's list element if the attribute
    is part of the list, or NULL_TREE if not found.  If the attribute
@@ -217,7 +233,8 @@ lookup_attribute (const char *attr_name, tree list)
     }
 }
 
-/* Similar to lookup_attribute, but also match the attribute namespace.  */
+/* Similar to lookup_attribute, but also match the attribute namespace.
+   ATTR_NS "" stands for either standard attribute or "gnu" namespace.  */
 
 static inline tree
 lookup_attribute (const char *attr_ns, const char *attr_name, tree list)
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index ffe17eaa9d9..9ec9100cc90 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -6008,12 +6008,12 @@ attribute_fallthrough_p (tree attr)
 {
   if (attr == error_mark_node)
    return false;
-  tree t = lookup_attribute ("fallthrough", attr);
+  tree t = lookup_attribute ("", "fallthrough", attr);
   if (t == NULL_TREE)
     return false;
   /* It is no longer true that "this attribute shall appear at most once in
      each attribute-list", but we still give a warning.  */
-  if (lookup_attribute ("fallthrough", TREE_CHAIN (t)))
+  if (lookup_attribute ("", "fallthrough", TREE_CHAIN (t)))
     warning (OPT_Wattributes, "attribute %<fallthrough%> specified multiple "
 	     "times");
   /* No attribute-argument-clause shall be present.  */
@@ -6024,7 +6024,8 @@ attribute_fallthrough_p (tree attr)
   for (t = attr; t != NULL_TREE; t = TREE_CHAIN (t))
     {
       tree name = get_attribute_name (t);
-      if (!is_attribute_p ("fallthrough", name))
+      if (!is_attribute_p ("fallthrough", name)
+	  || !is_attribute_namespace_p ("", t))
 	{
 	  if (!c_dialect_cxx () && get_attribute_namespace (t) == NULL_TREE)
 	    /* The specifications of standard attributes in C mean
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 5d26e59d098..cb8bbd8277f 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -3028,7 +3028,7 @@ cp_fold (tree x)
   return x;
 }
 
-/* Look up either "hot" or "cold" in attribute list LIST.  */
+/* Look up "hot", "cold", "likely" or "unlikely" in attribute list LIST.  */
 
 tree
 lookup_hotness_attribute (tree list)
@@ -3036,24 +3036,36 @@ lookup_hotness_attribute (tree list)
   for (; list; list = TREE_CHAIN (list))
     {
       tree name = get_attribute_name (list);
-      if (is_attribute_p ("hot", name)
-	  || is_attribute_p ("cold", name)
-	  || is_attribute_p ("likely", name)
-	  || is_attribute_p ("unlikely", name))
+      if ((is_attribute_p ("hot", name)
+	   || is_attribute_p ("cold", name)
+	   || is_attribute_p ("likely", name)
+	   || is_attribute_p ("unlikely", name))
+	  && is_attribute_namespace_p ("", list))
 	break;
     }
   return list;
 }
 
-/* Remove both "hot" and "cold" attributes from LIST.  */
+/* Remove "hot", "cold", "likely" and "unlikely" attributes from LIST.  */
 
 static tree
 remove_hotness_attribute (tree list)
 {
-  list = remove_attribute ("hot", list);
-  list = remove_attribute ("cold", list);
-  list = remove_attribute ("likely", list);
-  list = remove_attribute ("unlikely", list);
+  for (tree *p = &list; *p; )
+    {
+      tree l = *p;
+      tree name = get_attribute_name (l);
+      if ((is_attribute_p ("hot", name)
+	   || is_attribute_p ("cold", name)
+	   || is_attribute_p ("likely", name)
+	   || is_attribute_p ("unlikely", name))
+	  && is_attribute_namespace_p ("", l))
+	{
+	  *p = TREE_CHAIN (l);
+	  continue;
+	}
+      p = &TREE_CHAIN (l);
+    }
   return list;
 }
 
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 90e06f914fb..555476e42e7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -29265,7 +29265,8 @@ cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute)
   if (attributes)
     for (const auto &a : alist)
       if (is_attribute_p (a, get_attribute_name (attribute))
-	  && lookup_attribute (a, attributes))
+	  && is_attribute_namespace_p ("", attribute)
+	  && lookup_attribute ("", a, attributes))
 	{
 	  if (!from_macro_expansion_at (loc))
 	    warning_at (loc, OPT_Wattributes, "attribute %qs specified "
diff --git a/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C b/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C
new file mode 100644
index 00000000000..b74323fd168
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-Wextra -Wall -Wpedantic" }
+
+int
+foo (int i)
+{
+  switch (i)
+    {
+    case 2:
+      ++i;
+      [[fallthrough, whatever::fallthrough]];		// { dg-bogus "attribute 'fallthrough' specified multiple times" }
+    case 3:						// { dg-warning "'fallthrough' attribute ignored" "" { target *-*-* } .-1 }
+      ++i;
+      [[fallthrough, whatever2::fallthrough(1, 2, 3)]];	// { dg-bogus "attribute 'fallthrough' specified multiple times" }
+    case 4:						// { dg-warning "'fallthrough' attribute ignored" "" { target *-*-* } .-1 }
+      [[whatever3::fallthrough("abcd")]];		// { dg-warning "attributes at the beginning of statement are ignored" }
+    case 5:
+      [[whatever4::fallthrough]];			// { dg-bogus "attribute 'fallthrough' not preceding a case label or default label" }
+      ++i;						// { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 }
+    default:
+      break;
+    }
+  return i;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C b/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C
new file mode 100644
index 00000000000..638a6d9728e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C
@@ -0,0 +1,38 @@
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-times "hot label" 5 "gimple" } }
+// { dg-final { scan-tree-dump-times "cold label" 3 "gimple" } }
+
+bool b;
+
+template <class T> int f()
+{
+  if (b)
+    [[likely, whatever::unlikely ("abcd")]] return 0;		// { dg-bogus "ignoring attribute 'unlikely' after earlier 'likely'" }
+  else								// { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 }
+    [[unlikely, whatever2::hot]] flabel: return 1;		// { dg-warning "'whatever2::hot' scoped attribute directive ignored" }
+  switch (b)
+    {
+      [[likely, whatever3::cold (1, 2, 3)]] case true: break;	// { dg-warning "'whatever3::cold' scoped attribute directive ignored" }
+    };
+  return 1;
+}
+
+int main()
+{
+  if (b)
+    [[whatever4::unlikely (1), likely]] return 0;		// { dg-bogus "ignoring attribute 'likely' after earlier 'unlikely'" }
+  else if (b)							// { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 }
+    [[whatever5::hot, unlikely]] elabel:			// { dg-warning "'whatever5::hot' scoped attribute directive ignored" }
+      return 1;
+  else
+    [[whatever6::cold, likely]] b = false;			// { dg-bogus "ignoring attribute 'likely' after earlier 'cold'" }
+								// { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 }
+  f<int>();
+
+  switch (b)
+    {
+      [[whatever7::unlikely (1), likely]] case true: break;	// { dg-warning "'whatever7::unlikely' scoped attribute directive ignored" }
+      [[whatever8::unlikely, unlikely]] case false: break;	// { dg-bogus "attribute 'unlikely' specified multiple times" }
+    };								// { dg-warning "'whatever8::unlikely' scoped attribute directive ignored" "" { target *-*-* } .-1 }
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-07  7:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-07  7:05 [gcc r13-3149] c++: Improve handling of foreigner namespace attributes Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).