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.
|| VAR_OR_FUNCTION_DECL_P (decl)
|| TREE_CODE (decl) == FIELD_DECL
|| TREE_CODE (decl) == CONST_DECL
|| 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)
{
TREE_DEPRECATED (decl) = 1;
else if (TREE_CODE (decl) == LABEL_DECL)
{
MARK_TS_EXP (FOR_STMT);
MARK_TS_EXP (SWITCH_STMT);
MARK_TS_EXP (WHILE_STMT);
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
}
/* Build a user-defined numeric literal out of an integer constant type VALUE
SWITCH_STMT_SCOPE, respectively. */
DEFTREECODE (SWITCH_STMT, "switch_stmt", tcc_statement, 4)
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
/*
Local variables:
mode:c
{
gcc_assert (standard_concept_p (tmpl));
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
{
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)
tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
args = coerce_template_parms (parms, args, tmpl, complain);
if (args == error_mark_node)
/* New decls. */
MARK_TS_DECL_COMMON (TEMPLATE_DECL);
MARK_TS_DECL_COMMON (WILDCARD_DECL);
/* 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);
MARK_TS_DECL_NON_COMMON (USING_DECL);
/* Extensions for Concepts. */
/* 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)
/* Used to represent information associated with constrained declarations. */
DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0)
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 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);
extern tree combine_constraint_expressions (tree, tree);
extern tree append_constraint (tree, tree);
extern tree get_constraints (const_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);
if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
{
cp_parser_skip_to_end_of_statement (parser);
but continue as if it were. */
cp_parser_consume_semicolon_at_end_of_statement (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);
}
// -------------------------------------------------------------------------- //
}
// -------------------------------------------------------------------------- //
the TEMPLATE_DECL. */
tree
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);
{
gcc_assert (identifier_p (id));
gcc_assert (processing_template_decl);
DECL_CONTEXT (decl) = current_scope ();
DECL_INITIAL (decl) = 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. */
set_originating_module (decl, false);
/* Push the enclosing template. */
--- /dev/null
+// 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; }