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. --- 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