public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-925] c++: Relax attribute on friend declaration checking [PR100596]
@ 2021-05-19 17:10 Marek Polacek
  0 siblings, 0 replies; only message in thread
From: Marek Polacek @ 2021-05-19 17:10 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:adcb497bdba499d161d2e5e8de782bdd6f75d62c

commit r12-925-gadcb497bdba499d161d2e5e8de782bdd6f75d62c
Author: Marek Polacek <polacek@redhat.com>
Date:   Tue May 18 16:11:16 2021 -0400

    c++: Relax attribute on friend declaration checking [PR100596]
    
    It turned out that there are codebases that profusely use GNU attributes
    on friend declarations, so we have to dial back our checking and allow
    them.  And for C++11 attributes let's just warn instead of giving
    errors.
    
            PR c++/100596
    
    gcc/cp/ChangeLog:
    
            * cp-tree.h (any_non_type_attribute_p): Remove.
            * decl.c (grokdeclarator): Turn an error into a warning and only
            warn for standard attributes.
            * decl2.c (any_non_type_attribute_p): Remove.
            * parser.c (cp_parser_elaborated_type_specifier): Turn an error
            into a warning and only warn for standard attributes.
            (cp_parser_member_declaration): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/friend7.C: Turn a few dg-warnings into dg-errors.
            Remove dg-errors for GNU attributes.
            * g++.dg/ext/attrib63.C: Remove dg-error.
            * g++.dg/cpp0x/friend8.C: New test.

Diff:
---
 gcc/cp/cp-tree.h                     |  1 -
 gcc/cp/decl.c                        | 14 +++++++++-----
 gcc/cp/decl2.c                       | 14 --------------
 gcc/cp/parser.c                      | 29 +++++++++++++++++++----------
 gcc/testsuite/g++.dg/cpp0x/friend7.C | 28 ++++++++++++++--------------
 gcc/testsuite/g++.dg/cpp0x/friend8.C | 15 +++++++++++++++
 gcc/testsuite/g++.dg/ext/attrib63.C  | 23 ++++++++++++++++++++---
 7 files changed, 77 insertions(+), 47 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3c900dc08f7..860ed795299 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6761,7 +6761,6 @@ extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
 			  tree, tree, tree);
 extern tree splice_template_attributes		(tree *, tree);
 extern bool any_dependent_type_attributes_p	(tree);
-extern bool any_non_type_attribute_p		(tree);
 extern tree cp_reconstruct_complex_type		(tree, tree);
 extern bool attributes_naming_typedef_ok	(tree);
 extern void cplus_decl_attributes		(tree *, tree, int);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4f2fc2e496e..28052df9f45 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13731,11 +13731,15 @@ grokdeclarator (const cp_declarator *declarator,
 
 	if (friendp)
 	  {
-	    if (attrlist && !funcdef_flag
-		/* Hack to allow attributes like vector_size on a friend.  */
-		&& any_non_type_attribute_p (*attrlist))
-	      error_at (id_loc, "attribute appertains to a friend "
-			"declaration that is not a definition");
+	    /* Packages tend to use GNU attributes on friends, so we only
+	       warn for standard attributes.  */
+	    if (attrlist && !funcdef_flag && cxx11_attribute_p (*attrlist))
+	      {
+		*attrlist = NULL_TREE;
+		if (warning_at (id_loc, OPT_Wattributes, "attribute ignored"))
+		  inform (id_loc, "an attribute that appertains to a friend "
+			  "declaration that is not a definition is ignored");
+	      }
 	    /* Friends are treated specially.  */
 	    if (ctype == current_class_type)
 	      ;  /* We already issued a permerror.  */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8e4dd6b544a..89f874a32cc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1331,20 +1331,6 @@ any_dependent_type_attributes_p (tree attrs)
   return false;
 }
 
-/* True if ATTRS contains any attribute that does not require a type.  */
-
-bool
-any_non_type_attribute_p (tree attrs)
-{
-  for (tree a = attrs; a; a = TREE_CHAIN (a))
-    {
-      const attribute_spec *as = lookup_attribute_spec (get_attribute_name (a));
-      if (as && !as->type_required)
-	return true;
-    }
-  return false;
-}
-
 /* Return true iff ATTRS are acceptable attributes to be applied in-place
    to a typedef which gives a previously unnamed class or enum a name for
    linkage purposes.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f3503b13a5a..bc0505df502 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19774,9 +19774,12 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	       && ! processing_explicit_instantiation)
 	warning (OPT_Wattributes,
 		 "attributes ignored on template instantiation");
-      else if (is_friend && attributes)
-	error ("attribute appertains to a friend declaration that is not "
-	       "a definition");
+      else if (is_friend && cxx11_attribute_p (attributes))
+	{
+	  if (warning (OPT_Wattributes, "attribute ignored"))
+	    inform (input_location, "an attribute that appertains to a friend "
+		    "declaration that is not a definition is ignored");
+	}
       else if (is_declaration && cp_parser_declares_only_class_p (parser))
 	cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
       else
@@ -26064,17 +26067,23 @@ cp_parser_member_declaration (cp_parser* parser)
 		   if (type && TREE_CODE (type) == TYPE_DECL)
 		     type = TREE_TYPE (type);
 		 }
+	       /* Warn if an attribute cannot appear here, as per
+		  [dcl.attr.grammar]/5.  But not when declares_class_or_enum:
+		  we ignore attributes in elaborated-type-specifiers.  */
+	       if (!declares_class_or_enum
+		   && cxx11_attribute_p (decl_specifiers.attributes))
+		 {
+		   decl_specifiers.attributes = NULL_TREE;
+		   if (warning_at (decl_spec_token_start->location,
+				   OPT_Wattributes, "attribute ignored"))
+		     inform (decl_spec_token_start->location, "an attribute "
+			     "that appertains to a friend declaration that "
+			     "is not a definition is ignored");
+		 }
 	       if (!type || !TYPE_P (type))
 		 error_at (decl_spec_token_start->location,
 			   "friend declaration does not name a class or "
 			   "function");
-	       /* Give an error if an attribute cannot appear here, as per
-		  [dcl.attr.grammar]/5.  But not when declares_class_or_enum:
-		  we ignore attributes in elaborated-type-specifiers.  */
-	       else if (!declares_class_or_enum && decl_specifiers.attributes)
-		 error_at (decl_spec_token_start->location,
-			   "attribute appertains to a friend declaration "
-			   "that is not a definition");
 	       else
 		 make_friend_class (current_class_type, type,
 				    /*complain=*/true);
diff --git a/gcc/testsuite/g++.dg/cpp0x/friend7.C b/gcc/testsuite/g++.dg/cpp0x/friend7.C
index 734b367cd2b..e1d5f449f5c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/friend7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/friend7.C
@@ -6,21 +6,21 @@ template<typename T1, typename T2>
 void foo (T1, T2);
 
 struct S {
-  [[deprecated]] friend void f(); // { dg-error "attribute appertains" }
+  [[deprecated]] friend void f(); // { dg-warning "attribute ignored" }
   [[deprecated]] friend void f2() { }
-  __attribute__((deprecated)) friend void f3(); // { dg-error "attribute appertains" }
-  friend void f3 [[deprecated]] (); // { dg-error "attribute appertains" }
+  __attribute__((deprecated)) friend void f3();
+  friend void f3 [[deprecated]] (); // { dg-warning "attribute ignored" }
   friend void f4 [[deprecated]] () { }
-  [[deprecated]] friend void; // { dg-error "attribute appertains" }
-  __attribute__((deprecated)) friend int; // { dg-error "attribute appertains" }
-  friend __attribute__((deprecated)) int; // { dg-error "attribute appertains" }
-  friend int __attribute__((deprecated)); // { dg-error "attribute appertains" }
-  [[deprecated]] friend X; // { dg-error "attribute appertains" }
+  [[deprecated]] friend void; // { dg-warning "attribute ignored" }
+  __attribute__((deprecated)) friend int;
+  friend __attribute__((deprecated)) int;
+  friend int __attribute__((deprecated));
+  [[deprecated]] friend X; // { dg-warning "attribute ignored" }
   [[deprecated]] friend class N; // { dg-warning "attribute ignored" }
-  friend class [[deprecated]] N2; // { dg-error "attribute appertains" }
-  friend class __attribute__((deprecated)) N3; // { dg-error "attribute appertains" }
-  [[deprecated]] friend void foo<>(int, int); // { dg-error "attribute appertains" }
-  [[deprecated]] friend void ::foo(int, int); // { dg-error "attribute appertains" }
+  friend class [[deprecated]] N2; // { dg-warning "attribute ignored" }
+  friend class __attribute__((deprecated)) N3;
+  [[deprecated]] friend void foo<>(int, int); // { dg-warning "attribute ignored" }
+  [[deprecated]] friend void ::foo(int, int); // { dg-warning "attribute ignored" }
   // { dg-bogus "should have" "PR100339" { xfail *-*-* } .-1 }
 };
 
@@ -29,12 +29,12 @@ class node { };
 
 template<typename T>
 struct A {
-  [[deprecated]] friend T; // { dg-error "attribute appertains" }
+  [[deprecated]] friend T; // { dg-warning "attribute ignored" }
   [[deprecated]] friend class node<T>; // { dg-warning "attribute ignored" }
   template<typename>
   [[deprecated]] friend class A; // { dg-warning "attribute ignored" }
   template<typename>
   [[deprecated]] friend void bar () { }
   template<typename>
-  [[deprecated]] friend void baz (); // { dg-error "attribute appertains" }
+  [[deprecated]] friend void baz (); // { dg-warning "attribute ignored" }
 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/friend8.C b/gcc/testsuite/g++.dg/cpp0x/friend8.C
new file mode 100644
index 00000000000..8d2a2d35d54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/friend8.C
@@ -0,0 +1,15 @@
+// PR c++/100596
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  __attribute((deprecated)) friend void f(A); // part of A API, definition in .C
+  [[deprecated]] friend void f2(A); // { dg-warning "ignored" }
+};
+
+int main()
+{
+  A a;
+  f(a); // { dg-warning "is deprecated" }
+  f2(a);
+}
diff --git a/gcc/testsuite/g++.dg/ext/attrib63.C b/gcc/testsuite/g++.dg/ext/attrib63.C
index 93bde1e7d72..583779a9159 100644
--- a/gcc/testsuite/g++.dg/ext/attrib63.C
+++ b/gcc/testsuite/g++.dg/ext/attrib63.C
@@ -4,9 +4,9 @@
 #define vector __attribute__((vector_size(16)))
 class A {
   friend vector float f();
-  __attribute__((deprecated)) friend void f2(); // { dg-error "attribute appertains" }
-  friend __attribute__((deprecated, vector_size(16))) float f3(); // { dg-error "attribute appertains" }
-  friend __attribute__((vector_size(16), deprecated)) float f4(); // { dg-error "attribute appertains" }
+  __attribute__((deprecated)) friend void f2();
+  friend __attribute__((deprecated, vector_size(16))) float f3();
+  friend __attribute__((vector_size(16), deprecated)) float f4();
 };
 
 vector float vf;
@@ -15,3 +15,20 @@ f ()
 {
   return vf;
 }
+
+void
+f2 ()
+{
+}
+
+vector float
+f3 ()
+{
+  return vf;
+}
+
+vector float
+f4 ()
+{
+  return vf;
+}


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

only message in thread, other threads:[~2021-05-19 17:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-19 17:10 [gcc r12-925] c++: Relax attribute on friend declaration checking [PR100596] Marek Polacek

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).