On Tue, 15 Oct 2024, Patrick Palka wrote:
> This patch further cleans up the concepts code following the removal of
> Concepts TS support:
>
> * concept-ids are now the only kind of "concept check", so we can
> simplify some code accordingly. In particular resolve_concept_check
> seems like a no-op and can be removed.
> * In turn, deduce_constrained_parameter doesn't seem to do anything
> interesting.
> * In light of the above we might as well inline finish_type_constraints
> into its only caller. Note that the "prototype parameter" of a
> concept is just the first template parameter which the caller can
> easily obtain itself.
> * placeholder_extract_concept_and_args is only ever called on a
> concept-id, so it's simpler to inline it into its callers.
> * There's no such thing as a template-template-parameter wtih a
> type-constraint, so we can remove such handling from the parser.
> This means is_constrained_parameter is currently equivalent to
> declares_constrained_template_template_parameter, so let's prefer
> to use the latter.
>
> We might be able to remove WILDCARD_DECL and CONSTRAINED_PARM_PROTOTYPE
> now as well, but I left that as future work.
>
> gcc/cp/ChangeLog:
>
> * constraint.cc (resolve_concept_check): Remove.
> (deduce_constrained_parameter): Remove.
> (finish_type_constraints): Inline into its only caller
> cp_parser_placeholder_type_specifier and remove.
> (build_concept_check_arguments): Coding style tweaks.
> (build_standard_check): Inline into its only caller ...
> (build_concept_check): ... here.
> (finish_shorthand_constraint): Remove function concept
> handling.
> (placeholder_extract_concept_and_args): Inline into its
> callers and remove.
> (equivalent_placeholder_constraints): Adjust after
> placeholder_extract_concept_and_args removal.
> (iterative_hash_placeholder_constraint): Likewise.
> * cp-tree.h (type_uses_auto_or_concept): Remove declaration
> of nonexistent function.
> (append_type_to_template_for_access_check): Likewise.
> (finish_type_constraints): Remove declaration.
> (placeholder_extract_concept_and_args): Remove declaration.
> (deduce_constrained_parameter): Remove declaration.
> (resolve_constraint_check): Remove declaration.
> (valid_requirements_p): Remove declaration of nonexistent
> function.
> (finish_concept_name): Likewise.
> * cxx-pretty-print.cc (pp_cxx_constrained_type_spec): Adjust
> after placeholder_extract_concept_and_args.
> * parser.cc (is_constrained_parameter): Inline into
> declares_constrained_type_template_parameter and remove.
> (cp_parser_check_constrained_type_parm): Declare static.
> (finish_constrained_template_template_parm): Remove.
> (cp_parser_constrained_template_template_parm): Remove.
> (finish_constrained_parameter): Remove dead code guarded by
> cp_parser_constrained_template_template_parm.
> (declares_constrained_type_template_parameter): Adjust after
> is_constrained_parameter removal.
> (declares_constrained_template_template_parameter): Remove.
> (cp_parser_placeholder_type_specifier): Adjust after
> finish_type_constraints removal.
> (cp_parser_parameter_declaration): Remove dead code guarded by
> declares_constrained_template_template_parameter.
> * pt.cc (make_constrained_placeholder_type): Remove function
> concept handling.
Ping.
> ---
> gcc/cp/constraint.cc | 181 ++++++-------------------------------
> gcc/cp/cp-tree.h | 9 --
> gcc/cp/cxx-pretty-print.cc | 4 +-
> gcc/cp/parser.cc | 87 +++---------------
> gcc/cp/pt.cc | 5 +-
> 5 files changed, 42 insertions(+), 244 deletions(-)
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index cf0e5d37571..35be9cc2b41 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -241,88 +241,6 @@ get_concept_check_template (tree t)
> return TREE_OPERAND (t, 0);
> }
>
> -/*---------------------------------------------------------------------------
> - Resolution of qualified concept names
> ----------------------------------------------------------------------------*/
> -
> -/* This facility is used to resolve constraint checks from requirement
> - expressions. A constraint check is a call to a function template declared
> - with the keyword 'concept'.
> -
> - The result of resolution is a pair (a TREE_LIST) whose value is the
> - matched declaration, and whose purpose contains the coerced template
> - arguments that can be substituted into the call. */
> -
> -/* Returns a pair containing the checked concept and its associated
> - prototype parameter. The result is a TREE_LIST whose TREE_VALUE
> - is the concept (non-template) and whose TREE_PURPOSE contains
> - the converted template arguments, including the deduced prototype
> - parameter (in position 0). */
> -
> -tree
> -resolve_concept_check (tree check)
> -{
> - gcc_assert (concept_check_p (check));
> - tree tmpl = TREE_OPERAND (check, 0);
> - tree args = TREE_OPERAND (check, 1);
> - tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
> - ++processing_template_decl;
> - tree result = coerce_template_parms (parms, args, tmpl, tf_none);
> - --processing_template_decl;
> - if (result == error_mark_node)
> - return error_mark_node;
> - return build_tree_list (result, DECL_TEMPLATE_RESULT (tmpl));
> -}
> -
> -/* Given a call expression or template-id expression to a concept EXPR
> - possibly including a wildcard, deduce the concept being checked and
> - the prototype parameter. Returns true if the constraint and prototype
> - can be deduced and false otherwise. Note that the CHECK and PROTO
> - arguments are set to NULL_TREE if this returns false. */
> -
> -bool
> -deduce_constrained_parameter (tree expr, tree& check, tree& proto)
> -{
> - tree info = resolve_concept_check (expr);
> - if (info && info != error_mark_node)
> - {
> - check = TREE_VALUE (info);
> - tree arg = TREE_VEC_ELT (TREE_PURPOSE (info), 0);
> - if (ARGUMENT_PACK_P (arg))
> - arg = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0);
> - proto = TREE_TYPE (arg);
> - return true;
> - }
> -
> - check = proto = NULL_TREE;
> - return false;
> -}
> -
> -/* Build a constrained placeholder type where SPEC is a type-constraint.
> - SPEC can be anything were concept_definition_p is true.
> -
> - Returns a pair whose FIRST is the concept being checked and whose
> - SECOND is the prototype parameter. */
> -
> -tree_pair
> -finish_type_constraints (tree spec, tree args, tsubst_flags_t complain)
> -{
> - gcc_assert (concept_definition_p (spec));
> -
> - /* Build an initial concept check. */
> - tree check = build_type_constraint (spec, args, complain);
> - if (check == error_mark_node)
> - return std::make_pair (error_mark_node, NULL_TREE);
> -
> - /* Extract the concept and prototype parameter from the check. */
> - tree con;
> - tree proto;
> - if (!deduce_constrained_parameter (check, con, proto))
> - return std::make_pair (error_mark_node, NULL_TREE);
> -
> - return std::make_pair (con, proto);
> -}
> -
> /*---------------------------------------------------------------------------
> Expansion of concept definitions
> ---------------------------------------------------------------------------*/
> @@ -1161,10 +1079,11 @@ get_trailing_function_requirements (tree t)
>
> /* Construct a sequence of template arguments by prepending
> ARG to REST. Either ARG or REST may be null. */
> +
> static tree
> build_concept_check_arguments (tree arg, tree rest)
> {
> - gcc_assert (rest ? TREE_CODE (rest) == TREE_VEC : true);
> + gcc_assert (!rest || TREE_CODE (rest) == TREE_VEC);
> tree args;
> if (arg)
> {
> @@ -1178,49 +1097,32 @@ build_concept_check_arguments (tree arg, tree rest)
> SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, def + 1);
> }
> else
> - {
> - args = rest;
> - }
> + args = rest;
> return args;
> }
>
> -/* Builds an id-expression of the form `C<Args...>` where C is a standard
> - concept. */
> -
> -static tree
> -build_standard_check (tree tmpl, tree args, tsubst_flags_t complain)
> -{
> - gcc_assert (concept_definition_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)
> - return error_mark_node;
> - return build2 (TEMPLATE_ID_EXPR, boolean_type_node, tmpl, args);
> -}
> -
> -/* Construct an expression that checks TARGET using ARGS. */
> +/* Construct an expression that checks TMPL using ARGS. */
>
> tree
> -build_concept_check (tree target, tree args, tsubst_flags_t complain)
> +build_concept_check (tree tmpl, tree args, tsubst_flags_t complain)
> {
> - return build_concept_check (target, NULL_TREE, args, complain);
> + return build_concept_check (tmpl, NULL_TREE, args, complain);
> }
>
> -/* Construct an expression that checks the concept given by DECL. If
> - concept_definition_p (DECL) is false, this returns null. */
> +/* Construct an expression that checks the concept given by TMPL. */
>
> tree
> -build_concept_check (tree decl, tree arg, tree rest, tsubst_flags_t complain)
> +build_concept_check (tree tmpl, tree arg, tree rest, tsubst_flags_t complain)
> {
> - tree args = build_concept_check_arguments (arg, rest);
> -
> - if (concept_definition_p (decl))
> - return build_standard_check (decl, args, complain);
> + if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
> + warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
>
> - return error_mark_node;
> + tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
> + tree args = build_concept_check_arguments (arg, rest);
> + args = coerce_template_parms (parms, args, tmpl, complain);
> + if (args == error_mark_node)
> + return error_mark_node;
> + return build2 (TEMPLATE_ID_EXPR, boolean_type_node, tmpl, args);
> }
>
> /* Build a template-id that can participate in a concept check. */
> @@ -1312,10 +1214,7 @@ finish_shorthand_constraint (tree decl, tree constr)
>
> /* Build the concept constraint-expression. */
> tree tmpl = DECL_TI_TEMPLATE (con);
> - tree check = tmpl;
> - if (TREE_CODE (con) == FUNCTION_DECL)
> - check = ovl_make (tmpl);
> - check = build_concept_check (check, arg, args, tf_warning_or_error);
> + tree check = build_concept_check (tmpl, arg, args, tf_warning_or_error);
>
> /* Make the check a fold-expression if needed.
> Use UNKNOWN_LOCATION so write_template_args can tell the
> @@ -1345,32 +1244,6 @@ get_shorthand_constraints (tree parms)
> return result;
> }
>
> -/* Given the concept check T from a constrained-type-specifier, extract
> - its TMPL and ARGS. FIXME why do we need two different forms of
> - constrained-type-specifier? */
> -
> -void
> -placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args)
> -{
> - if (concept_check_p (t))
> - {
> - tmpl = TREE_OPERAND (t, 0);
> - args = TREE_OPERAND (t, 1);
> - return;
> - }
> -
> - if (TREE_CODE (t) == TYPE_DECL)
> - {
> - /* A constrained parameter. Build a constraint check
> - based on the prototype parameter and then extract the
> - arguments from that. */
> - tree proto = CONSTRAINED_PARM_PROTOTYPE (t);
> - tree check = finish_shorthand_constraint (proto, t);
> - placeholder_extract_concept_and_args (check, tmpl, args);
> - return;
> - }
> -}
> -
> /* Returns true iff the placeholders C1 and C2 are equivalent. C1
> and C2 can be either TEMPLATE_TYPE_PARM or template-ids. */
>
> @@ -1393,9 +1266,11 @@ equivalent_placeholder_constraints (tree c1, tree c2)
> placeholder constraints. */
> return false;
>
> - tree t1, t2, a1, a2;
> - placeholder_extract_concept_and_args (c1, t1, a1);
> - placeholder_extract_concept_and_args (c2, t2, a2);
> + gcc_assert (concept_check_p (c1) && concept_check_p (c2));
> + tree t1 = TREE_OPERAND (c1, 0);
> + tree a1 = TREE_OPERAND (c1, 1);
> + tree t2 = TREE_OPERAND (c2, 0);
> + tree a2 = TREE_OPERAND (c2, 1);
>
> if (t1 != t2)
> return false;
> @@ -1408,12 +1283,9 @@ equivalent_placeholder_constraints (tree c1, tree c2)
> /* Skip the first argument so we don't infinitely recurse.
> Also, they may differ in template parameter index. */
> for (int i = 1; i < len1; ++i)
> - {
> - tree t1 = TREE_VEC_ELT (a1, i);
> - tree t2 = TREE_VEC_ELT (a2, i);
> - if (!template_args_equal (t1, t2))
> + if (!template_args_equal (TREE_VEC_ELT (a1, i),
> + TREE_VEC_ELT (a2, i)))
> return false;
> - }
> return true;
> }
>
> @@ -1422,8 +1294,9 @@ equivalent_placeholder_constraints (tree c1, tree c2)
> hashval_t
> iterative_hash_placeholder_constraint (tree c, hashval_t val)
> {
> - tree t, a;
> - placeholder_extract_concept_and_args (c, t, a);
> + gcc_assert (concept_check_p (c));
> + tree t = TREE_OPERAND (c, 0);
> + tree a = TREE_OPERAND (c, 1);
>
> /* Like hash_tmpl_and_args, but skip the first argument. */
> val = iterative_hash_object (DECL_UID (t), val);
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 94ee550bd9c..1864ab205ae 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7531,9 +7531,6 @@ extern tree do_auto_deduction (tree,
> tree, tree,
> int = LOOKUP_NORMAL,
> tree = NULL_TREE);
> extern tree type_uses_auto (tree);
> -extern tree type_uses_auto_or_concept (tree);
> -extern void append_type_to_template_for_access_check (tree, tree, tree,
> - location_t);
> extern tree convert_generic_types_to_packs (tree, int, int);
> extern tree splice_late_return_type (tree, tree);
> extern bool is_auto (const_tree);
> @@ -8598,15 +8595,9 @@ extern tree build_type_constraint (tree,
> tree, tsubst_flags_t);
> extern tree build_concept_check (tree, tree, tsubst_flags_t);
> extern tree build_concept_check (tree, tree, tree,
> tsubst_flags_t);
>
> -extern tree_pair finish_type_constraints (tree, tree, tsubst_flags_t);
> extern tree build_constrained_parameter (tree, tree, tree =
> NULL_TREE);
> -extern void placeholder_extract_concept_and_args (tree, tree&, tree&);
> extern bool equivalent_placeholder_constraints (tree, tree);
> extern hashval_t iterative_hash_placeholder_constraint (tree,
> hashval_t);
> -extern bool deduce_constrained_parameter (tree, tree&, tree&);
> -extern tree resolve_constraint_check (tree);
> -extern bool valid_requirements_p (tree);
> -extern tree finish_concept_name (tree);
> extern tree finish_shorthand_constraint (tree, tree);
> extern tree finish_requires_expr (location_t, tree, tree);
> extern tree finish_simple_requirement (location_t, tree);
> diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
> index 41e6bdfdda5..bf3772d5ac5 100644
> --- a/gcc/cp/cxx-pretty-print.cc
> +++ b/gcc/cp/cxx-pretty-print.cc
> @@ -2334,8 +2334,8 @@ pp_cxx_constrained_type_spec (cxx_pretty_printer *pp,
> tree c)
> pp_cxx_ws_string(pp, "<unsatisfied-type-constraint>");
> return;
> }
> - tree t, a;
> - placeholder_extract_concept_and_args (c, t, a);
> + tree t = TREE_OPERAND (c, 0);
> + tree a = TREE_OPERAND (c, 1);
> pp->id_expression (t);
> pp_cxx_begin_template_argument_list (pp);
> pp_cxx_ws_string (pp, "<placeholder>");
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index 9d31a975dcf..856508e3e4f 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -18572,29 +18572,10 @@ get_unqualified_id (cp_declarator *declarator)
> return NULL_TREE;
> }
>
> -/* Returns true if TYPE would declare a constrained constrained-parameter.
> */
> -
> -static inline bool
> -is_constrained_parameter (tree type)
> -{
> - return (type
> - && TREE_CODE (type) == TYPE_DECL
> - && CONSTRAINED_PARM_CONCEPT (type)
> - && DECL_P (CONSTRAINED_PARM_CONCEPT (type)));
> -}
> -
> -/* Returns true if PARM declares a constrained-parameter. */
> -
> -static inline bool
> -is_constrained_parameter (cp_parameter_declarator *parm)
> -{
> - return is_constrained_parameter (parm->decl_specifiers.type);
> -}
> -
> /* Check that the type parameter is only a declarator-id, and that its
> type is not cv-qualified. */
>
> -bool
> +static bool
> cp_parser_check_constrained_type_parm (cp_parser *parser,
> cp_parameter_declarator *parm)
> {
> @@ -18632,36 +18613,6 @@ cp_parser_constrained_type_template_parm (cp_parser
> *parser,
> return error_mark_node;
> }
>
> -static tree
> -finish_constrained_template_template_parm (tree proto, tree id)
> -{
> - /* FIXME: This should probably be copied, and we may need to adjust
> - the template parameter depths. */
> - tree saved_parms = current_template_parms;
> - begin_template_parm_list ();
> - current_template_parms = DECL_TEMPLATE_PARMS (proto);
> - end_template_parm_list ();
> -
> - tree parm = finish_template_template_parm (class_type_node, id);
> - current_template_parms = saved_parms;
> -
> - return parm;
> -}
> -
> -/* Finish parsing/processing a template template parameter by borrowing
> - the template parameter list from the prototype parameter. */
> -
> -static tree
> -cp_parser_constrained_template_template_parm (cp_parser *parser,
> - tree proto,
> - tree id,
> - cp_parameter_declarator
> *parmdecl)
> -{
> - if (!cp_parser_check_constrained_type_parm (parser, parmdecl))
> - return error_mark_node;
> - return finish_constrained_template_template_parm (proto, id);
> -}
> -
> /* Create a new non-type template parameter from the given PARM
> declarator. */
>
> @@ -18695,9 +18646,6 @@ finish_constrained_parameter (cp_parser *parser,
> tree parm;
> if (TREE_CODE (proto) == TYPE_DECL)
> parm = cp_parser_constrained_type_template_parm (parser, id, parmdecl);
> - else if (TREE_CODE (proto) == TEMPLATE_DECL)
> - parm = cp_parser_constrained_template_template_parm (parser, proto, id,
> - parmdecl);
> else
> parm = cp_parser_constrained_non_type_template_parm (is_non_type,
> parmdecl);
> if (parm == error_mark_node)
> @@ -18717,20 +18665,13 @@ finish_constrained_parameter (cp_parser *parser,
> static bool
> declares_constrained_type_template_parameter (tree type)
> {
> - return (is_constrained_parameter (type)
> + return (type
> + && TREE_CODE (type) == TYPE_DECL
> + && CONSTRAINED_PARM_CONCEPT (type)
> + && DECL_P (CONSTRAINED_PARM_CONCEPT (type))
> && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TYPE_PARM);
> }
>
> -/* Returns true if the parsed type actually represents the declaration of
> - a template template-parameter. */
> -
> -static bool
> -declares_constrained_template_template_parameter (tree type)
> -{
> - return (is_constrained_parameter (type)
> - && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TEMPLATE_PARM);
> -}
> -
> /* Parse a default argument for a type template-parameter.
> Note that diagnostics are handled in cp_parser_template_parameter. */
>
> @@ -18901,7 +18842,8 @@ cp_parser_template_parameter (cp_parser* parser, bool
> *is_non_type,
> }
>
> /* The parameter may have been constrained type parameter. */
> - if (is_constrained_parameter (parameter_declarator))
> + tree type = parameter_declarator->decl_specifiers.type;
> + if (declares_constrained_type_template_parameter (type))
> return finish_constrained_parameter (parser,
> parameter_declarator,
> is_non_type);
> @@ -20987,11 +20929,12 @@ cp_parser_placeholder_type_specifier (cp_parser
> *parser, location_t loc,
> tsubst_flags_t complain = tentative ? tf_none : tf_warning_or_error;
>
> /* Get the concept and prototype parameter for the constraint. */
> - tree_pair info = finish_type_constraints (tmpl, args, complain);
> - tree con = info.first;
> - tree proto = info.second;
> - if (con == error_mark_node)
> + tree check = build_type_constraint (tmpl, args, complain);
> + if (check == error_mark_node)
> return error_mark_node;
> + tree con = STRIP_TEMPLATE (tmpl);
> + tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
> + tree proto = TREE_VALUE (TREE_VEC_ELT (parms, 0));
>
> /* As per the standard, require auto or decltype(auto). */
> cp_token *placeholder = NULL, *close_paren = NULL;
> @@ -26130,12 +26073,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
> default_argument
> = cp_parser_default_type_template_argument (parser);
>
> - /* A constrained-type-specifier may declare a
> - template-template-parameter. */
> - else if (declares_constrained_template_template_parameter (type))
> - default_argument
> - = cp_parser_default_template_template_argument (parser);
> -
> /* Outside of a class definition, we can just parse the
> assignment-expression. */
> else
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index c0a37a51cba..3d037bd6948 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -29556,11 +29556,8 @@ make_constrained_placeholder_type (tree type, tree
> con, tree args)
> {
> /* Build the constraint. */
> tree tmpl = DECL_TI_TEMPLATE (con);
> - tree expr = tmpl;
> - if (TREE_CODE (con) == FUNCTION_DECL)
> - expr = ovl_make (tmpl);
> ++processing_template_decl;
> - expr = build_concept_check (expr, type, args, tf_warning_or_error);
> + tree expr = build_concept_check (tmpl, type, args, tf_warning_or_error);
> --processing_template_decl;
>
> PLACEHOLDER_TYPE_CONSTRAINTS_INFO (type)
> --
> 2.47.0.72.gef8ce8f3d4
>
>