public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Relax attribute on friend declaration checking [PR100596]
@ 2021-05-18 21:00 Marek Polacek
  2021-05-19 17:02 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Marek Polacek @ 2021-05-18 21:00 UTC (permalink / raw)
  To: Jason Merrill, GCC Patches

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.

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

	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.
---
 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(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/friend8.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 580db914d40..122dadf976f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6763,7 +6763,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 17511f09e79..92fb4a2daea 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13741,11 +13741,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 c0b57955954..ac1cefc5c41 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;
+}

base-commit: 8c114759b8c9c9e2ec90b82d92a24b5a71647017
-- 
2.31.1


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

* Re: [PATCH] c++: Relax attribute on friend declaration checking [PR100596]
  2021-05-18 21:00 [PATCH] c++: Relax attribute on friend declaration checking [PR100596] Marek Polacek
@ 2021-05-19 17:02 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2021-05-19 17:02 UTC (permalink / raw)
  To: Marek Polacek, GCC Patches

On 5/18/21 5:00 PM, Marek Polacek wrote:
> 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.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

> 	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.
> ---
>   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(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/friend8.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 580db914d40..122dadf976f 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -6763,7 +6763,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 17511f09e79..92fb4a2daea 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -13741,11 +13741,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 c0b57955954..ac1cefc5c41 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;
> +}
> 
> base-commit: 8c114759b8c9c9e2ec90b82d92a24b5a71647017
> 


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

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

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-18 21:00 [PATCH] c++: Relax attribute on friend declaration checking [PR100596] Marek Polacek
2021-05-19 17:02 ` 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).