public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Check attributes on friend declarations [PR99032]
@ 2021-05-12  2:45 Marek Polacek
  2021-05-12 14:37 ` Jason Merrill
  0 siblings, 1 reply; 11+ messages in thread
From: Marek Polacek @ 2021-05-12  2:45 UTC (permalink / raw)
  To: Jason Merrill, GCC Patches

This patch implements [dcl.attr.grammar]/5: "If an attribute-specifier-seq
appertains to a friend declaration ([class.friend]), that declaration shall
be a definition."

This restriction only applies to C++11-style attributes.  There are
various forms of friend declarations, we have friend templates, C++11
extended friend declarations, and so on.  In some cases we already
ignore the attribute and warn that it was ignored.  But certain cases
weren't diagnosed, and with this patch we'll give a hard error.  I tried
hard not to emit both a warning and error and I think it worked out.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

gcc/cp/ChangeLog:

	PR c++/99032
	* decl.c (grokdeclarator): Diagnose when an attribute appertains to
	a friend declaration that is not a definition.
	* parser.c (cp_parser_elaborated_type_specifier): Likewise.
	(cp_parser_member_declaration): Likewise.

gcc/testsuite/ChangeLog:

	PR c++/99032
	* g++.dg/cpp0x/friend7.C: New test.
---
 gcc/cp/decl.c                        |  4 +++
 gcc/cp/parser.c                      | 15 +++++++++-
 gcc/testsuite/g++.dg/cpp0x/friend7.C | 41 ++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/friend7.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bc3928d7f85..687a59d49e3 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13741,6 +13741,10 @@ grokdeclarator (const cp_declarator *declarator,
 
 	if (friendp)
 	  {
+	    if (attrlist && !funcdef_flag
+		&& cxx11_attribute_p (*attrlist))
+	      error_at (id_loc, "attribute appertains to a friend declaration "
+			"that is not a definition");
 	    /* Friends are treated specially.  */
 	    if (ctype == current_class_type)
 	      ;  /* We already issued a permerror.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0fe29c658d2..612ca4598b9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19764,11 +19764,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	       && ! processing_explicit_instantiation)
 	warning (OPT_Wattributes,
 		 "attributes ignored on template instantiation");
+      else if (is_friend && cxx11_attribute_p (attributes))
+	error ("attribute appertains to a friend declaration that is not "
+	       "a definition");
       else if (is_declaration && cp_parser_declares_only_class_p (parser))
 	cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
       else
 	warning (OPT_Wattributes,
-		 "attributes ignored on elaborated-type-specifier that is not a forward declaration");
+		 "attributes ignored on elaborated-type-specifier that is "
+		 "not a forward declaration");
     }
 
   if (tag_type == enum_type)
@@ -26054,6 +26058,15 @@ cp_parser_member_declaration (cp_parser* parser)
 		 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
+			&& (cxx11_attribute_p (decl_specifiers.std_attributes)
+			    || cxx11_attribute_p (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
new file mode 100644
index 00000000000..4aa7b14cf7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/friend7.C
@@ -0,0 +1,41 @@
+// PR c++/99032
+// { dg-do compile { target c++11 } }
+
+class X { };
+template<typename T1, typename T2>
+void foo (T1, T2);
+
+struct S {
+  [[deprecated]] friend void f(); // { dg-error "attribute appertains" }
+  [[deprecated]] friend void f2() { }
+  __attribute__((deprecated)) friend void f3();
+  friend void f3 [[deprecated]] (); // { dg-error "attribute appertains" }
+  friend void f4 [[deprecated]] () { }
+  [[deprecated]] friend void; // { dg-error "attribute appertains" }
+  friend [[deprecated]] void; // { dg-error "attribute appertains" }
+  __attribute__((deprecated)) friend int;
+  friend __attribute__((deprecated)) int;
+  friend int __attribute__((deprecated));
+  [[deprecated]] friend X; // { dg-error "attribute appertains" }
+  [[deprecated]] friend class N; // { dg-warning "attribute ignored" }
+  friend class [[deprecated]] N2; // { dg-error "attribute appertains" }
+  friend class __attribute__((deprecated)) N3;
+  [[deprecated]] friend void foo<>(int, int); // { dg-error "attribute appertains" }
+  // FIXME: Add dg error when PR100339 is resolved.
+  //[[deprecated]] friend void ::foo(int, int);
+};
+
+template<typename T>
+class node { };
+
+template<typename T>
+struct A {
+  [[deprecated]] friend T; // { dg-error "attribute appertains" }
+  [[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" }
+};

base-commit: 71d38ec80008afdbb9a059253407d80598b765c0
-- 
2.31.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-05-18 17:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-12  2:45 [PATCH] c++: Check attributes on friend declarations [PR99032] Marek Polacek
2021-05-12 14:37 ` Jason Merrill
2021-05-12 15:03   ` Marek Polacek
2021-05-12 16:21     ` Jason Merrill
2021-05-13  0:03       ` [PATCH v2] " Marek Polacek
2021-05-13  0:27         ` Jason Merrill
2021-05-13 22:08           ` Marek Polacek
2021-05-14  0:36             ` Jason Merrill
2021-05-18 17:35             ` Franz Sirl
2021-05-18 17:46               ` Marek Polacek
2021-05-13  0:34         ` Jason Merrill

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