]> gcc.gnu.org Git - gcc.git/commitdiff
c++: Allow attributes on concepts - DR 2428
authorJakub Jelinek <jakub@redhat.com>
Wed, 16 Nov 2022 06:37:05 +0000 (07:37 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 16 Nov 2022 06:37:05 +0000 (07:37 +0100)
The following patch adds parsing of attributes to concept definition,
allows deprecated attribute to be specified (as CONCEPT_DECL now needs
to be checked in c-family/c-attribs.cc, I had to move its declaration
from cp/*.def to c-family/*.def) 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).

2022-11-16  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-attribs.cc
gcc/c-family/c-common.cc
gcc/c-family/c-common.def
gcc/cp/constraint.cc
gcc/cp/cp-objcp-common.cc
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/parser.cc
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C [new file with mode: 0644]

index 92ac93ba2cedd3ba5ef1be6c883b48eba95d15eb..07bca68e9b9425ed4631f110e2572eb99c1ee11c 100644 (file)
@@ -4211,7 +4211,8 @@ handle_deprecated_attribute (tree *node, tree name,
          || 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)
        {
index 71507d4cb0a9f93087e149da4a410560b5db6852..6f1f21bc4c173e15dfee6e7196ad97e4fe12d2d4 100644 (file)
@@ -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
index dd8be7fdd3dea936ec4e5ba1ad40a0ab2ec9728e..64956fc2ca1208535ef0e5f0603e37b6dffa140b 100644 (file)
@@ -81,6 +81,14 @@ DEFTREECODE (CONTINUE_STMT, "continue_stmt", tcc_statement, 0)
    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
index 3ddbd5353303b6f0f7a874e7d00114e1da89b38c..a113d3e269e5dc8340a9aab4cfbd77bf4e85d95c 100644 (file)
@@ -1396,6 +1396,8 @@ build_standard_check (tree tmpl, tree args, tsubst_flags_t complain)
 {
   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)
index e4df30d9720ea1f9dcb8df0fd8b65da581a3b32b..7f76f2c669a77b360d5d4b7f4efe5ca5827d3de6 100644 (file)
@@ -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);
 
index f83b4c54d43a64beef61d5693bb8f268d06c2fbd..3de8278e9f152d72e8fa6c4b86c17d20438fb3e7 100644 (file)
@@ -495,11 +495,6 @@ DEFTREECODE (OMP_DEPOBJ, "omp_depobj", tcc_statement, 2)
 
 /* 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)
 
index 8c9beb865680553bd59f32af7fcbc90708c71fd0..07f96ea861fb953c051e7954131c43c597c681a7 100644 (file)
@@ -8322,7 +8322,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);
index e4021835ed58034334dc5884db989d481a6fe3c9..c5929a6cc5fcd65a3f4a5c79f7148ad6b720e189 100644 (file)
@@ -29672,6 +29672,8 @@ cp_parser_concept_definition (cp_parser *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 *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);
 }
 
 // -------------------------------------------------------------------------- //
index e6017b34c0c9834bfd6703f4090f890546b0fff0..0310e38c9b955b09e11fb95355c25eddd0c83685 100644 (file)
@@ -28928,7 +28928,7 @@ placeholder_type_constraint_dependent_p (tree t)
    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);
@@ -28962,6 +28962,9 @@ finish_concept_definition (cp_expr id, tree init)
   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.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C b/gcc/testsuite/g++.dg/cpp2a/concepts-dr2428.C
new file mode 100644 (file)
index 0000000..d08ad36
--- /dev/null
@@ -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; }
This page took 0.128523 seconds and 5 git commands to generate.