c++: Allow attributes on concepts - DR 2428

Message ID Y3IbNWSVE+Ydjk4u@tucnak
State New
Headers
Series c++: Allow attributes on concepts - DR 2428 |

Commit Message

Jakub Jelinek Nov. 14, 2022, 10:40 a.m. UTC
  Hi!

Working virtually out of Baker Island.

The following patch adds parsing of attributes to concept definition,
allows deprecated attribute to be specified (some ugliness needed
because CONCEPT_DECL is a cp/*.def attribute and so can't be mentioned
in c-family/ directly; used what is used for objc method decls,
an alternative would be a langhook) and checks TREE_DEPRECATED in
build_standard_check (not sure if that is the right spot, or whether
it shouldn't be checked also for variable and function concepts and
how to write testcase coverage for that).

Lightly tested so far.

2022-11-13  Jakub Jelinek  <jakub@redhat.com>

gcc/c-family/
	* c-common.h (c_concept_decl): Declare.
	* c-attribs.cc (handle_deprecated_attribute): Allow deprecated
	attribute on CONCEPT_DECL if flag_concepts.
gcc/c/
	* c-decl.cc (c_concept_decl): New function.
gcc/cp/
	* cp-tree.h (finish_concept_definition): Add ATTRS parameter.
	* parser.cc (cp_parser_concept_definition): Parse attributes in
	between identifier and =.  Adjust finish_concept_definition
	caller.
	* pt.cc (finish_concept_definition): Add ATTRS parameter.  Call
	cplus_decl_attributes.
	* constraint.cc (build_standard_check): If CONCEPT_DECL is
	TREE_DEPRECATED, emit -Wdeprecated-declaration warnings.
	* tree.cc (c_concept_decl): New function.
gcc/testsuite/
	* g++.dg/cpp2a/concepts-dr2428.C: New test.


	Jakub
  

Comments

Jason Merrill Nov. 15, 2022, midnight UTC | #1
On 11/14/22 00:40, Jakub Jelinek wrote:
> Hi!
> 
> Working virtually out of Baker Island.
> 
> The following patch adds parsing of attributes to concept definition,
> allows deprecated attribute to be specified (some ugliness needed
> because CONCEPT_DECL is a cp/*.def attribute and so can't be mentioned
> in c-family/ directly; used what is used for objc method decls,
> an alternative would be a langhook)

Several of the codes in c-common.def are C++-only, you might just move 
it over?

> and checks TREE_DEPRECATED in
> build_standard_check (not sure if that is the right spot, or whether
> it shouldn't be checked also for variable and function concepts and
> how to write testcase coverage for that).

I wouldn't bother with var/fn concepts, they're obsolete.

> Lightly tested so far.
> 
> 2022-11-13  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/c-family/
> 	* c-common.h (c_concept_decl): Declare.
> 	* c-attribs.cc (handle_deprecated_attribute): Allow deprecated
> 	attribute on CONCEPT_DECL if flag_concepts.
> gcc/c/
> 	* c-decl.cc (c_concept_decl): New function.
> gcc/cp/
> 	* cp-tree.h (finish_concept_definition): Add ATTRS parameter.
> 	* parser.cc (cp_parser_concept_definition): Parse attributes in
> 	between identifier and =.  Adjust finish_concept_definition
> 	caller.
> 	* pt.cc (finish_concept_definition): Add ATTRS parameter.  Call
> 	cplus_decl_attributes.
> 	* constraint.cc (build_standard_check): If CONCEPT_DECL is
> 	TREE_DEPRECATED, emit -Wdeprecated-declaration warnings.
> 	* tree.cc (c_concept_decl): New function.
> gcc/testsuite/
> 	* g++.dg/cpp2a/concepts-dr2428.C: New test.
> 
> --- gcc/c-family/c-common.h.jj	2022-10-27 21:00:53.698247586 -1200
> +++ gcc/c-family/c-common.h	2022-11-13 21:49:37.934598359 -1200
> @@ -831,6 +831,7 @@ extern tree (*make_fname_decl) (location
>   
>   /* In c-decl.cc and cp/tree.cc.  FIXME.  */
>   extern void c_register_addr_space (const char *str, addr_space_t as);
> +extern bool c_concept_decl (enum tree_code);
>   
>   /* In c-common.cc.  */
>   extern bool in_late_binary_op;
> --- gcc/c-family/c-attribs.cc.jj	2022-10-09 19:31:57.177988375 -1200
> +++ gcc/c-family/c-attribs.cc	2022-11-13 21:52:37.920152731 -1200
> @@ -4211,7 +4211,8 @@ handle_deprecated_attribute (tree *node,
>   	  || VAR_OR_FUNCTION_DECL_P (decl)
>   	  || TREE_CODE (decl) == FIELD_DECL
>   	  || TREE_CODE (decl) == CONST_DECL
> -	  || objc_method_decl (TREE_CODE (decl)))
> +	  || objc_method_decl (TREE_CODE (decl))
> +	  || (flag_concepts && c_concept_decl (TREE_CODE (decl))))
>   	TREE_DEPRECATED (decl) = 1;
>         else if (TREE_CODE (decl) == LABEL_DECL)
>   	{
> --- gcc/c/c-decl.cc.jj	2022-11-12 23:29:08.181504470 -1200
> +++ gcc/c/c-decl.cc	2022-11-13 21:50:38.178779716 -1200
> @@ -12987,6 +12987,14 @@ c_register_addr_space (const char *word,
>     ridpointers [rid] = id;
>   }
>   
> +/* C doesn't have CONCEPT_DECL.  */
> +
> +bool
> +c_concept_decl (enum tree_code)
> +{
> +  return false;
> +}
> +
>   /* Return identifier to look up for omp declare reduction.  */
>   
>   tree
> --- gcc/cp/cp-tree.h.jj	2022-11-11 20:30:10.138056914 -1200
> +++ gcc/cp/cp-tree.h	2022-11-13 20:58:39.443218815 -1200
> @@ -8324,7 +8324,7 @@ struct diagnosing_failed_constraint
>   extern cp_expr finish_constraint_or_expr	(location_t, cp_expr, cp_expr);
>   extern cp_expr finish_constraint_and_expr	(location_t, cp_expr, cp_expr);
>   extern cp_expr finish_constraint_primary_expr	(cp_expr);
> -extern tree finish_concept_definition		(cp_expr, tree);
> +extern tree finish_concept_definition		(cp_expr, tree, tree);
>   extern tree combine_constraint_expressions      (tree, tree);
>   extern tree append_constraint			(tree, tree);
>   extern tree get_constraints                     (const_tree);
> --- gcc/cp/parser.cc.jj	2022-11-08 22:39:13.325041007 -1200
> +++ gcc/cp/parser.cc	2022-11-13 20:58:15.692542640 -1200
> @@ -29672,6 +29672,8 @@ cp_parser_concept_definition (cp_parser
>         return NULL_TREE;
>       }
>   
> +  tree attrs = cp_parser_attributes_opt (parser);
> +
>     if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
>       {
>         cp_parser_skip_to_end_of_statement (parser);
> @@ -29688,7 +29690,7 @@ cp_parser_concept_definition (cp_parser
>        but continue as if it were.  */
>     cp_parser_consume_semicolon_at_end_of_statement (parser);
>   
> -  return finish_concept_definition (id, init);
> +  return finish_concept_definition (id, init, attrs);
>   }
>   
>   // -------------------------------------------------------------------------- //
> --- gcc/cp/pt.cc.jj	2022-11-07 20:54:37.341399829 -1200
> +++ gcc/cp/pt.cc	2022-11-13 21:01:18.333053377 -1200
> @@ -29027,7 +29027,7 @@ placeholder_type_constraint_dependent_p
>      the TEMPLATE_DECL. */
>   
>   tree
> -finish_concept_definition (cp_expr id, tree init)
> +finish_concept_definition (cp_expr id, tree init, tree attrs)
>   {
>     gcc_assert (identifier_p (id));
>     gcc_assert (processing_template_decl);
> @@ -29061,6 +29061,9 @@ finish_concept_definition (cp_expr id, t
>     DECL_CONTEXT (decl) = current_scope ();
>     DECL_INITIAL (decl) = init;
>   
> +  if (attrs)
> +    cplus_decl_attributes (&decl, attrs, 0);
> +
>     set_originating_module (decl, false);
>   
>     /* Push the enclosing template.  */
> --- gcc/cp/constraint.cc.jj	2022-11-04 05:11:41.491946435 -1200
> +++ gcc/cp/constraint.cc	2022-11-13 22:24:55.314809969 -1200
> @@ -1396,6 +1396,8 @@ build_standard_check (tree tmpl, tree ar
>   {
>     gcc_assert (standard_concept_p (tmpl));
>     gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
> +  if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
> +    warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
>     tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
>     args = coerce_template_parms (parms, args, tmpl, complain);
>     if (args == error_mark_node)
> --- gcc/cp/tree.cc.jj	2022-11-08 22:39:13.318041103 -1200
> +++ gcc/cp/tree.cc	2022-11-13 21:51:21.851186254 -1200
> @@ -6103,6 +6103,14 @@ c_register_addr_space (const char * /*wo
>   {
>   }
>   
> +/* Return true if CODE is CONCEPT_DECL.  */
> +
> +bool
> +c_concept_decl (enum tree_code code)
> +{
> +  return code == CONCEPT_DECL;
> +}
> +
>   /* Return the number of operands in T that we care about for things like
>      mangling.  */
>   
> --- gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C.jj	2022-11-13 22:27:56.977337907 -1200
> +++ gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C	2022-11-13 22:28:07.767191065 -1200
> @@ -0,0 +1,22 @@
> +// DR 2428
> +// { dg-do compile { target c++20 } }
> +
> +template<typename T>
> +concept C1 [[deprecated]] = true;
> +
> +template<typename T>
> +concept C2 __attribute__((deprecated)) = false;
> +
> +template<typename T>
> +concept C3 [[deprecated]] = true;
> +
> +template<typename T>
> +concept C4 __attribute__((deprecated)) = false;
> +
> +static_assert(C3<int>);	// { dg-warning "'C3' is deprecated" }
> +static_assert(C4<int>); // { dg-error "static assertion failed" }
> +			// { dg-warning "'C4' is deprecated" "" { target *-*-* } .-1 }
> +
> +template<typename T>
> +  requires C3<T>	// { dg-warning "'C3' is deprecated" }
> +int fn1(T t) { return 0; }
> 
> 	Jakub
>
  
Jakub Jelinek Nov. 15, 2022, 8:54 a.m. UTC | #2
On Mon, Nov 14, 2022 at 07:00:54PM -0500, Jason Merrill wrote:
> > The following patch adds parsing of attributes to concept definition,
> > allows deprecated attribute to be specified (some ugliness needed
> > because CONCEPT_DECL is a cp/*.def attribute and so can't be mentioned
> > in c-family/ directly; used what is used for objc method decls,
> > an alternative would be a langhook)
> 
> Several of the codes in c-common.def are C++-only, you might just move it
> over?
> 
> > and checks TREE_DEPRECATED in
> > build_standard_check (not sure if that is the right spot, or whether
> > it shouldn't be checked also for variable and function concepts and
> > how to write testcase coverage for that).
> 
> I wouldn't bother with var/fn concepts, they're obsolete.

Ok, so like this?
The previous version passed bootstrap/regtest on x86_64-linux and i686-linux,
I'll of course test this one as well.

	Jakub
  
Jakub Jelinek Nov. 15, 2022, 8:54 a.m. UTC | #3
On Tue, Nov 15, 2022 at 09:54:00AM +0100, Jakub Jelinek via Gcc-patches wrote:
> On Mon, Nov 14, 2022 at 07:00:54PM -0500, Jason Merrill wrote:
> > > The following patch adds parsing of attributes to concept definition,
> > > allows deprecated attribute to be specified (some ugliness needed
> > > because CONCEPT_DECL is a cp/*.def attribute and so can't be mentioned
> > > in c-family/ directly; used what is used for objc method decls,
> > > an alternative would be a langhook)
> > 
> > Several of the codes in c-common.def are C++-only, you might just move it
> > over?
> > 
> > > and checks TREE_DEPRECATED in
> > > build_standard_check (not sure if that is the right spot, or whether
> > > it shouldn't be checked also for variable and function concepts and
> > > how to write testcase coverage for that).
> > 
> > I wouldn't bother with var/fn concepts, they're obsolete.
> 
> Ok, so like this?
> The previous version passed bootstrap/regtest on x86_64-linux and i686-linux,
> I'll of course test this one as well.

Better with a patch.  Sorry.

2022-11-15  Jakub Jelinek  <jakub@redhat.com>

gcc/c-family/
	* c-common.def (CONCEPT_DECL): New tree, moved here from
	cp-tree.def.
	* c-common.cc (c_common_init_ts): Handle CONCEPT_DECL.
	* c-attribs.cc (handle_deprecated_attribute): Allow deprecated
	attribute on CONCEPT_DECL.
gcc/cp/
	* cp-tree.def (CONCEPT_DECL): Move to c-common.def.
	* cp-objcp-common.cc (cp_common_init_ts): Don't handle CONCEPT_DECL
	here.
	* cp-tree.h (finish_concept_definition): Add ATTRS parameter.
	* parser.cc (cp_parser_concept_definition): Parse attributes in
	between identifier and =.  Adjust finish_concept_definition
	caller.
	* pt.cc (finish_concept_definition): Add ATTRS parameter.  Call
	cplus_decl_attributes.
	* constraint.cc (build_standard_check): If CONCEPT_DECL is
	TREE_DEPRECATED, emit -Wdeprecated-declaration warnings.
gcc/testsuite/
	* g++.dg/cpp2a/concepts-dr2428.C: New test.

--- gcc/c-family/c-common.def.jj	2022-10-14 09:28:27.975164491 +0200
+++ gcc/c-family/c-common.def	2022-11-15 09:34:01.384591076 +0100
@@ -81,6 +81,14 @@ DEFTREECODE (CONTINUE_STMT, "continue_st
    SWITCH_STMT_SCOPE, respectively.  */
 DEFTREECODE (SWITCH_STMT, "switch_stmt", tcc_statement, 4)
 
+/* Extensions for C++ Concepts. */
+
+/* Concept definition. This is not entirely different than a VAR_DECL
+   except that a) it must be a template, and b) doesn't have the wide
+   range of value and linkage options available to variables.  Used
+   by C++ FE and in c-family attribute handling.  */
+DEFTREECODE (CONCEPT_DECL, "concept_decl", tcc_declaration, 0)
+
 /*
 Local variables:
 mode:c
--- gcc/c-family/c-common.cc.jj	2022-11-13 12:29:08.165504692 +0100
+++ gcc/c-family/c-common.cc	2022-11-15 09:34:48.828950083 +0100
@@ -8497,6 +8497,8 @@ c_common_init_ts (void)
   MARK_TS_EXP (FOR_STMT);
   MARK_TS_EXP (SWITCH_STMT);
   MARK_TS_EXP (WHILE_STMT);
+
+  MARK_TS_DECL_COMMON (CONCEPT_DECL);
 }
 
 /* Build a user-defined numeric literal out of an integer constant type VALUE
--- gcc/c-family/c-attribs.cc.jj	2022-11-14 13:35:34.184160348 +0100
+++ gcc/c-family/c-attribs.cc	2022-11-15 09:30:57.370081060 +0100
@@ -4211,7 +4211,8 @@ handle_deprecated_attribute (tree *node,
 	  || VAR_OR_FUNCTION_DECL_P (decl)
 	  || TREE_CODE (decl) == FIELD_DECL
 	  || TREE_CODE (decl) == CONST_DECL
-	  || objc_method_decl (TREE_CODE (decl)))
+	  || objc_method_decl (TREE_CODE (decl))
+	  || TREE_CODE (decl) == CONCEPT_DECL)
 	TREE_DEPRECATED (decl) = 1;
       else if (TREE_CODE (decl) == LABEL_DECL)
 	{
--- gcc/cp/cp-tree.def.jj	2022-09-29 18:11:34.836666800 +0200
+++ gcc/cp/cp-tree.def	2022-11-15 09:32:17.456996090 +0100
@@ -495,11 +495,6 @@ DEFTREECODE (OMP_DEPOBJ, "omp_depobj", t
 
 /* Extensions for Concepts. */
 
-/* Concept definition. This is not entirely different than a VAR_DECL
-   except that a) it must be a template, and b) doesn't have the wide
-   range of value and linkage options available to variables.  */
-DEFTREECODE (CONCEPT_DECL, "concept_decl", tcc_declaration, 0)
-
 /* Used to represent information associated with constrained declarations. */
 DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0)
 
--- gcc/cp/cp-objcp-common.cc.jj	2022-09-30 18:38:55.349607203 +0200
+++ gcc/cp/cp-objcp-common.cc	2022-11-15 09:34:21.963313049 +0100
@@ -473,7 +473,6 @@ cp_common_init_ts (void)
   /* New decls.  */
   MARK_TS_DECL_COMMON (TEMPLATE_DECL);
   MARK_TS_DECL_COMMON (WILDCARD_DECL);
-  MARK_TS_DECL_COMMON (CONCEPT_DECL);
 
   MARK_TS_DECL_NON_COMMON (USING_DECL);
 
--- gcc/cp/cp-tree.h.jj	2022-11-15 08:17:07.561388452 +0100
+++ gcc/cp/cp-tree.h	2022-11-15 09:30:57.371081046 +0100
@@ -8324,7 +8324,7 @@ struct diagnosing_failed_constraint
 extern cp_expr finish_constraint_or_expr	(location_t, cp_expr, cp_expr);
 extern cp_expr finish_constraint_and_expr	(location_t, cp_expr, cp_expr);
 extern cp_expr finish_constraint_primary_expr	(cp_expr);
-extern tree finish_concept_definition		(cp_expr, tree);
+extern tree finish_concept_definition		(cp_expr, tree, tree);
 extern tree combine_constraint_expressions      (tree, tree);
 extern tree append_constraint			(tree, tree);
 extern tree get_constraints                     (const_tree);
--- gcc/cp/parser.cc.jj	2022-11-14 13:35:34.380157682 +0100
+++ gcc/cp/parser.cc	2022-11-15 09:30:57.377080965 +0100
@@ -29672,6 +29672,8 @@ cp_parser_concept_definition (cp_parser
       return NULL_TREE;
     }
 
+  tree attrs = cp_parser_attributes_opt (parser);
+
   if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
     {
       cp_parser_skip_to_end_of_statement (parser);
@@ -29688,7 +29690,7 @@ cp_parser_concept_definition (cp_parser
      but continue as if it were.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
-  return finish_concept_definition (id, init);
+  return finish_concept_definition (id, init, attrs);
 }
 
 // -------------------------------------------------------------------------- //
--- gcc/cp/constraint.cc.jj	2022-11-14 13:35:34.269159192 +0100
+++ gcc/cp/constraint.cc	2022-11-15 09:30:57.382080897 +0100
@@ -1396,6 +1396,8 @@ build_standard_check (tree tmpl, tree ar
 {
   gcc_assert (standard_concept_p (tmpl));
   gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
+  if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
+    warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
   tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
   args = coerce_template_parms (parms, args, tmpl, complain);
   if (args == error_mark_node)
--- gcc/cp/pt.cc.jj	2022-11-15 07:56:05.130350281 +0100
+++ gcc/cp/pt.cc	2022-11-15 09:30:57.381080911 +0100
@@ -29030,7 +29030,7 @@ placeholder_type_constraint_dependent_p
    the TEMPLATE_DECL. */
 
 tree
-finish_concept_definition (cp_expr id, tree init)
+finish_concept_definition (cp_expr id, tree init, tree attrs)
 {
   gcc_assert (identifier_p (id));
   gcc_assert (processing_template_decl);
@@ -29064,6 +29064,9 @@ finish_concept_definition (cp_expr id, t
   DECL_CONTEXT (decl) = current_scope ();
   DECL_INITIAL (decl) = init;
 
+  if (attrs)
+    cplus_decl_attributes (&decl, attrs, 0);
+
   set_originating_module (decl, false);
 
   /* Push the enclosing template.  */
--- gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C.jj	2022-11-15 09:30:57.382080897 +0100
+++ gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C	2022-11-15 09:30:57.382080897 +0100
@@ -0,0 +1,22 @@
+// DR 2428
+// { dg-do compile { target c++20 } }
+
+template<typename T>
+concept C1 [[deprecated]] = true;
+
+template<typename T>
+concept C2 __attribute__((deprecated)) = false;
+
+template<typename T>
+concept C3 [[deprecated]] = true;
+
+template<typename T>
+concept C4 __attribute__((deprecated)) = false;
+
+static_assert(C3<int>);	// { dg-warning "'C3' is deprecated" }
+static_assert(C4<int>); // { dg-error "static assertion failed" }
+			// { dg-warning "'C4' is deprecated" "" { target *-*-* } .-1 }
+
+template<typename T>
+  requires C3<T>	// { dg-warning "'C3' is deprecated" }
+int fn1(T t) { return 0; }


	Jakub
  
Jason Merrill Nov. 15, 2022, 9:51 p.m. UTC | #4
On 11/14/22 22:54, Jakub Jelinek wrote:
> On Tue, Nov 15, 2022 at 09:54:00AM +0100, Jakub Jelinek via Gcc-patches wrote:
>> On Mon, Nov 14, 2022 at 07:00:54PM -0500, Jason Merrill wrote:
>>>> The following patch adds parsing of attributes to concept definition,
>>>> allows deprecated attribute to be specified (some ugliness needed
>>>> because CONCEPT_DECL is a cp/*.def attribute and so can't be mentioned
>>>> in c-family/ directly; used what is used for objc method decls,
>>>> an alternative would be a langhook)
>>>
>>> Several of the codes in c-common.def are C++-only, you might just move it
>>> over?
>>>
>>>> and checks TREE_DEPRECATED in
>>>> build_standard_check (not sure if that is the right spot, or whether
>>>> it shouldn't be checked also for variable and function concepts and
>>>> how to write testcase coverage for that).
>>>
>>> I wouldn't bother with var/fn concepts, they're obsolete.
>>
>> Ok, so like this?
>> The previous version passed bootstrap/regtest on x86_64-linux and i686-linux,
>> I'll of course test this one as well.
> 
> Better with a patch.  Sorry.

OK.

> 2022-11-15  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/c-family/
> 	* c-common.def (CONCEPT_DECL): New tree, moved here from
> 	cp-tree.def.
> 	* c-common.cc (c_common_init_ts): Handle CONCEPT_DECL.
> 	* c-attribs.cc (handle_deprecated_attribute): Allow deprecated
> 	attribute on CONCEPT_DECL.
> gcc/cp/
> 	* cp-tree.def (CONCEPT_DECL): Move to c-common.def.
> 	* cp-objcp-common.cc (cp_common_init_ts): Don't handle CONCEPT_DECL
> 	here.
> 	* cp-tree.h (finish_concept_definition): Add ATTRS parameter.
> 	* parser.cc (cp_parser_concept_definition): Parse attributes in
> 	between identifier and =.  Adjust finish_concept_definition
> 	caller.
> 	* pt.cc (finish_concept_definition): Add ATTRS parameter.  Call
> 	cplus_decl_attributes.
> 	* constraint.cc (build_standard_check): If CONCEPT_DECL is
> 	TREE_DEPRECATED, emit -Wdeprecated-declaration warnings.
> gcc/testsuite/
> 	* g++.dg/cpp2a/concepts-dr2428.C: New test.
> 
> --- gcc/c-family/c-common.def.jj	2022-10-14 09:28:27.975164491 +0200
> +++ gcc/c-family/c-common.def	2022-11-15 09:34:01.384591076 +0100
> @@ -81,6 +81,14 @@ DEFTREECODE (CONTINUE_STMT, "continue_st
>      SWITCH_STMT_SCOPE, respectively.  */
>   DEFTREECODE (SWITCH_STMT, "switch_stmt", tcc_statement, 4)
>   
> +/* Extensions for C++ Concepts. */
> +
> +/* Concept definition. This is not entirely different than a VAR_DECL
> +   except that a) it must be a template, and b) doesn't have the wide
> +   range of value and linkage options available to variables.  Used
> +   by C++ FE and in c-family attribute handling.  */
> +DEFTREECODE (CONCEPT_DECL, "concept_decl", tcc_declaration, 0)
> +
>   /*
>   Local variables:
>   mode:c
> --- gcc/c-family/c-common.cc.jj	2022-11-13 12:29:08.165504692 +0100
> +++ gcc/c-family/c-common.cc	2022-11-15 09:34:48.828950083 +0100
> @@ -8497,6 +8497,8 @@ c_common_init_ts (void)
>     MARK_TS_EXP (FOR_STMT);
>     MARK_TS_EXP (SWITCH_STMT);
>     MARK_TS_EXP (WHILE_STMT);
> +
> +  MARK_TS_DECL_COMMON (CONCEPT_DECL);
>   }
>   
>   /* Build a user-defined numeric literal out of an integer constant type VALUE
> --- gcc/c-family/c-attribs.cc.jj	2022-11-14 13:35:34.184160348 +0100
> +++ gcc/c-family/c-attribs.cc	2022-11-15 09:30:57.370081060 +0100
> @@ -4211,7 +4211,8 @@ handle_deprecated_attribute (tree *node,
>   	  || VAR_OR_FUNCTION_DECL_P (decl)
>   	  || TREE_CODE (decl) == FIELD_DECL
>   	  || TREE_CODE (decl) == CONST_DECL
> -	  || objc_method_decl (TREE_CODE (decl)))
> +	  || objc_method_decl (TREE_CODE (decl))
> +	  || TREE_CODE (decl) == CONCEPT_DECL)
>   	TREE_DEPRECATED (decl) = 1;
>         else if (TREE_CODE (decl) == LABEL_DECL)
>   	{
> --- gcc/cp/cp-tree.def.jj	2022-09-29 18:11:34.836666800 +0200
> +++ gcc/cp/cp-tree.def	2022-11-15 09:32:17.456996090 +0100
> @@ -495,11 +495,6 @@ DEFTREECODE (OMP_DEPOBJ, "omp_depobj", t
>   
>   /* Extensions for Concepts. */
>   
> -/* Concept definition. This is not entirely different than a VAR_DECL
> -   except that a) it must be a template, and b) doesn't have the wide
> -   range of value and linkage options available to variables.  */
> -DEFTREECODE (CONCEPT_DECL, "concept_decl", tcc_declaration, 0)
> -
>   /* Used to represent information associated with constrained declarations. */
>   DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0)
>   
> --- gcc/cp/cp-objcp-common.cc.jj	2022-09-30 18:38:55.349607203 +0200
> +++ gcc/cp/cp-objcp-common.cc	2022-11-15 09:34:21.963313049 +0100
> @@ -473,7 +473,6 @@ cp_common_init_ts (void)
>     /* New decls.  */
>     MARK_TS_DECL_COMMON (TEMPLATE_DECL);
>     MARK_TS_DECL_COMMON (WILDCARD_DECL);
> -  MARK_TS_DECL_COMMON (CONCEPT_DECL);
>   
>     MARK_TS_DECL_NON_COMMON (USING_DECL);
>   
> --- gcc/cp/cp-tree.h.jj	2022-11-15 08:17:07.561388452 +0100
> +++ gcc/cp/cp-tree.h	2022-11-15 09:30:57.371081046 +0100
> @@ -8324,7 +8324,7 @@ struct diagnosing_failed_constraint
>   extern cp_expr finish_constraint_or_expr	(location_t, cp_expr, cp_expr);
>   extern cp_expr finish_constraint_and_expr	(location_t, cp_expr, cp_expr);
>   extern cp_expr finish_constraint_primary_expr	(cp_expr);
> -extern tree finish_concept_definition		(cp_expr, tree);
> +extern tree finish_concept_definition		(cp_expr, tree, tree);
>   extern tree combine_constraint_expressions      (tree, tree);
>   extern tree append_constraint			(tree, tree);
>   extern tree get_constraints                     (const_tree);
> --- gcc/cp/parser.cc.jj	2022-11-14 13:35:34.380157682 +0100
> +++ gcc/cp/parser.cc	2022-11-15 09:30:57.377080965 +0100
> @@ -29672,6 +29672,8 @@ cp_parser_concept_definition (cp_parser
>         return NULL_TREE;
>       }
>   
> +  tree attrs = cp_parser_attributes_opt (parser);
> +
>     if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
>       {
>         cp_parser_skip_to_end_of_statement (parser);
> @@ -29688,7 +29690,7 @@ cp_parser_concept_definition (cp_parser
>        but continue as if it were.  */
>     cp_parser_consume_semicolon_at_end_of_statement (parser);
>   
> -  return finish_concept_definition (id, init);
> +  return finish_concept_definition (id, init, attrs);
>   }
>   
>   // -------------------------------------------------------------------------- //
> --- gcc/cp/constraint.cc.jj	2022-11-14 13:35:34.269159192 +0100
> +++ gcc/cp/constraint.cc	2022-11-15 09:30:57.382080897 +0100
> @@ -1396,6 +1396,8 @@ build_standard_check (tree tmpl, tree ar
>   {
>     gcc_assert (standard_concept_p (tmpl));
>     gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
> +  if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
> +    warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
>     tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
>     args = coerce_template_parms (parms, args, tmpl, complain);
>     if (args == error_mark_node)
> --- gcc/cp/pt.cc.jj	2022-11-15 07:56:05.130350281 +0100
> +++ gcc/cp/pt.cc	2022-11-15 09:30:57.381080911 +0100
> @@ -29030,7 +29030,7 @@ placeholder_type_constraint_dependent_p
>      the TEMPLATE_DECL. */
>   
>   tree
> -finish_concept_definition (cp_expr id, tree init)
> +finish_concept_definition (cp_expr id, tree init, tree attrs)
>   {
>     gcc_assert (identifier_p (id));
>     gcc_assert (processing_template_decl);
> @@ -29064,6 +29064,9 @@ finish_concept_definition (cp_expr id, t
>     DECL_CONTEXT (decl) = current_scope ();
>     DECL_INITIAL (decl) = init;
>   
> +  if (attrs)
> +    cplus_decl_attributes (&decl, attrs, 0);
> +
>     set_originating_module (decl, false);
>   
>     /* Push the enclosing template.  */
> --- gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C.jj	2022-11-15 09:30:57.382080897 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C	2022-11-15 09:30:57.382080897 +0100
> @@ -0,0 +1,22 @@
> +// DR 2428
> +// { dg-do compile { target c++20 } }
> +
> +template<typename T>
> +concept C1 [[deprecated]] = true;
> +
> +template<typename T>
> +concept C2 __attribute__((deprecated)) = false;
> +
> +template<typename T>
> +concept C3 [[deprecated]] = true;
> +
> +template<typename T>
> +concept C4 __attribute__((deprecated)) = false;
> +
> +static_assert(C3<int>);	// { dg-warning "'C3' is deprecated" }
> +static_assert(C4<int>); // { dg-error "static assertion failed" }
> +			// { dg-warning "'C4' is deprecated" "" { target *-*-* } .-1 }
> +
> +template<typename T>
> +  requires C3<T>	// { dg-warning "'C3' is deprecated" }
> +int fn1(T t) { return 0; }
> 
> 
> 	Jakub
>
  

Patch

--- gcc/c-family/c-common.h.jj	2022-10-27 21:00:53.698247586 -1200
+++ gcc/c-family/c-common.h	2022-11-13 21:49:37.934598359 -1200
@@ -831,6 +831,7 @@  extern tree (*make_fname_decl) (location
 
 /* In c-decl.cc and cp/tree.cc.  FIXME.  */
 extern void c_register_addr_space (const char *str, addr_space_t as);
+extern bool c_concept_decl (enum tree_code);
 
 /* In c-common.cc.  */
 extern bool in_late_binary_op;
--- gcc/c-family/c-attribs.cc.jj	2022-10-09 19:31:57.177988375 -1200
+++ gcc/c-family/c-attribs.cc	2022-11-13 21:52:37.920152731 -1200
@@ -4211,7 +4211,8 @@  handle_deprecated_attribute (tree *node,
 	  || VAR_OR_FUNCTION_DECL_P (decl)
 	  || TREE_CODE (decl) == FIELD_DECL
 	  || TREE_CODE (decl) == CONST_DECL
-	  || objc_method_decl (TREE_CODE (decl)))
+	  || objc_method_decl (TREE_CODE (decl))
+	  || (flag_concepts && c_concept_decl (TREE_CODE (decl))))
 	TREE_DEPRECATED (decl) = 1;
       else if (TREE_CODE (decl) == LABEL_DECL)
 	{
--- gcc/c/c-decl.cc.jj	2022-11-12 23:29:08.181504470 -1200
+++ gcc/c/c-decl.cc	2022-11-13 21:50:38.178779716 -1200
@@ -12987,6 +12987,14 @@  c_register_addr_space (const char *word,
   ridpointers [rid] = id;
 }
 
+/* C doesn't have CONCEPT_DECL.  */
+
+bool
+c_concept_decl (enum tree_code)
+{
+  return false;
+}
+
 /* Return identifier to look up for omp declare reduction.  */
 
 tree
--- gcc/cp/cp-tree.h.jj	2022-11-11 20:30:10.138056914 -1200
+++ gcc/cp/cp-tree.h	2022-11-13 20:58:39.443218815 -1200
@@ -8324,7 +8324,7 @@  struct diagnosing_failed_constraint
 extern cp_expr finish_constraint_or_expr	(location_t, cp_expr, cp_expr);
 extern cp_expr finish_constraint_and_expr	(location_t, cp_expr, cp_expr);
 extern cp_expr finish_constraint_primary_expr	(cp_expr);
-extern tree finish_concept_definition		(cp_expr, tree);
+extern tree finish_concept_definition		(cp_expr, tree, tree);
 extern tree combine_constraint_expressions      (tree, tree);
 extern tree append_constraint			(tree, tree);
 extern tree get_constraints                     (const_tree);
--- gcc/cp/parser.cc.jj	2022-11-08 22:39:13.325041007 -1200
+++ gcc/cp/parser.cc	2022-11-13 20:58:15.692542640 -1200
@@ -29672,6 +29672,8 @@  cp_parser_concept_definition (cp_parser
       return NULL_TREE;
     }
 
+  tree attrs = cp_parser_attributes_opt (parser);
+
   if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
     {
       cp_parser_skip_to_end_of_statement (parser);
@@ -29688,7 +29690,7 @@  cp_parser_concept_definition (cp_parser
      but continue as if it were.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
-  return finish_concept_definition (id, init);
+  return finish_concept_definition (id, init, attrs);
 }
 
 // -------------------------------------------------------------------------- //
--- gcc/cp/pt.cc.jj	2022-11-07 20:54:37.341399829 -1200
+++ gcc/cp/pt.cc	2022-11-13 21:01:18.333053377 -1200
@@ -29027,7 +29027,7 @@  placeholder_type_constraint_dependent_p
    the TEMPLATE_DECL. */
 
 tree
-finish_concept_definition (cp_expr id, tree init)
+finish_concept_definition (cp_expr id, tree init, tree attrs)
 {
   gcc_assert (identifier_p (id));
   gcc_assert (processing_template_decl);
@@ -29061,6 +29061,9 @@  finish_concept_definition (cp_expr id, t
   DECL_CONTEXT (decl) = current_scope ();
   DECL_INITIAL (decl) = init;
 
+  if (attrs)
+    cplus_decl_attributes (&decl, attrs, 0);
+
   set_originating_module (decl, false);
 
   /* Push the enclosing template.  */
--- gcc/cp/constraint.cc.jj	2022-11-04 05:11:41.491946435 -1200
+++ gcc/cp/constraint.cc	2022-11-13 22:24:55.314809969 -1200
@@ -1396,6 +1396,8 @@  build_standard_check (tree tmpl, tree ar
 {
   gcc_assert (standard_concept_p (tmpl));
   gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
+  if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
+    warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
   tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
   args = coerce_template_parms (parms, args, tmpl, complain);
   if (args == error_mark_node)
--- gcc/cp/tree.cc.jj	2022-11-08 22:39:13.318041103 -1200
+++ gcc/cp/tree.cc	2022-11-13 21:51:21.851186254 -1200
@@ -6103,6 +6103,14 @@  c_register_addr_space (const char * /*wo
 {
 }
 
+/* Return true if CODE is CONCEPT_DECL.  */
+
+bool
+c_concept_decl (enum tree_code code)
+{
+  return code == CONCEPT_DECL;
+}
+
 /* Return the number of operands in T that we care about for things like
    mangling.  */
 
--- gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C.jj	2022-11-13 22:27:56.977337907 -1200
+++ gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C	2022-11-13 22:28:07.767191065 -1200
@@ -0,0 +1,22 @@ 
+// DR 2428
+// { dg-do compile { target c++20 } }
+
+template<typename T>
+concept C1 [[deprecated]] = true;
+
+template<typename T>
+concept C2 __attribute__((deprecated)) = false;
+
+template<typename T>
+concept C3 [[deprecated]] = true;
+
+template<typename T>
+concept C4 __attribute__((deprecated)) = false;
+
+static_assert(C3<int>);	// { dg-warning "'C3' is deprecated" }
+static_assert(C4<int>); // { dg-error "static assertion failed" }
+			// { dg-warning "'C4' is deprecated" "" { target *-*-* } .-1 }
+
+template<typename T>
+  requires C3<T>	// { dg-warning "'C3' is deprecated" }
+int fn1(T t) { return 0; }