On Tue, 5 Nov 2024, Jason Merrill wrote: > On 10/15/24 12:45 AM, 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. > > But it's still a defined term in the language > (https://eel.is/c++draft/temp#concept-7) so I think it's worth having an > accessor function. I agree with doing away with the function that returns a > pair.
Done. > > > * 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. > > Why prefer the longer name? "is_constrained_parameter" suggests it should return true for a constrained non-type parameter, but that's currently not the case and callers don't expect/want that behavior, so the longer name seems more accurate. > > > We might be able to remove WILDCARD_DECL and CONSTRAINED_PARM_PROTOTYPE > > now as well, but I left that as future work. > > > > @@ -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)) > > Why not retain a function that takes the declarator? I added another overload of declares_constrained_type_template_parameter taking a cp_parameter_declarator. > > > 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)); > > And as mentioned above, let's have a small function that returns the prototype > parameter of a concept, to use here. Done. > > Incidentally, why do we want to strip the template from con? Is that also a > relic of the different possible forms of concept? Oops, I think we could use DECL_TEMPLATE_RESULT here instead of STRIP_TEMPLATE, since 'tmpl' will always be a TEMPLATE_DECL. Here's v2 which squashes the 3rd patch (removing WILDCARD_DECL) into this one, and addresses your feedback. -- >8 -- Subject: [PATCH] c++: some further concepts cleanups 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. * Introduce and use a helper for obtaining the prototype parameter of a concept, i.e. its first template parameter. * 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 with a type-constraint, so we can remove such handling from the parser. This means is_constrained_parameter is currently equivalent to declares_constrained_type_template_parameter, so let's prefer to use the latter. * Remove WILDCARD_DECL and instead use the concept's prototype parameter as the dummy first argument of a type-constraint during template argument coercion. * Remove a redundant concept_definition_p overload. 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. (build_type_constraint): Use the prototype parameter as the first template argument. (finish_shorthand_constraint): Remove function concept handling. Use concept_prototype_parameter. (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-objcp-common.cc (cp_common_init_ts): Remove WILDCARD_DECL handling. * cp-tree.def (WILDCARD_DECL): Remove. * cp-tree.h (WILDCARD_PACK_P): Remove. (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. (concept_definition_p): Remove redundant overload. (concept_prototype_parameter): Define. * cxx-pretty-print.cc (pp_cxx_constrained_type_spec): Adjust after placeholder_extract_concept_and_args. * error.cc (dump_decl) <case WILDCARD_DECL>: Remove. (dump_expr) <case WILDCARD_DECL>: Likewise. * 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. Check the prototype parameter earlier, before build_type_constraint. Use concept_prototype_parameter. (cp_parser_parameter_declaration): Remove dead code guarded by declares_constrained_template_template_parameter. * pt.cc (convert_wildcard_argument): Remove. (convert_template_argument): Remove WILDCARD_DECL handling. (coerce_template_parameter_pack): Likewise. (tsubst) <case TEMPLATE_TYPE_PARM>: Likewise. (type_dependent_expression_p): Likewise. (make_constrained_placeholder_type): Remove function concept handling. (placeholder_type_constraint_dependent_p): Remove WILDCARD_DECL handling. --- gcc/cp/constraint.cc | 185 ++++++------------------------------- gcc/cp/cp-objcp-common.cc | 1 - gcc/cp/cp-tree.def | 6 -- gcc/cp/cp-tree.h | 36 +++----- gcc/cp/cxx-pretty-print.cc | 4 +- gcc/cp/error.cc | 5 - gcc/cp/parser.cc | 114 ++++++----------------- gcc/cp/pt.cc | 42 +-------- 8 files changed, 77 insertions(+), 316 deletions(-) diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 8a36b9c88c4..2dd7efdee76 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -242,88 +242,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 ---------------------------------------------------------------------------*/ @@ -1162,10 +1080,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) { @@ -1179,49 +1098,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. */ @@ -1253,9 +1155,9 @@ build_concept_id (tree expr) tree build_type_constraint (tree decl, tree args, tsubst_flags_t complain) { - tree wildcard = build_nt (WILDCARD_DECL); + tree proto = template_parm_to_arg (concept_prototype_parameter (decl)); ++processing_template_decl; - tree check = build_concept_check (decl, wildcard, args, complain); + tree check = build_concept_check (decl, proto, args, complain); --processing_template_decl; return check; } @@ -1313,10 +1215,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 @@ -1346,32 +1245,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. */ @@ -1394,9 +1267,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; @@ -1409,12 +1284,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; } @@ -1423,8 +1295,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-objcp-common.cc b/gcc/cp/cp-objcp-common.cc index 921931b9846..02ba2649b3a 100644 --- a/gcc/cp/cp-objcp-common.cc +++ b/gcc/cp/cp-objcp-common.cc @@ -629,7 +629,6 @@ cp_common_init_ts (void) /* New decls. */ MARK_TS_DECL_COMMON (TEMPLATE_DECL); - MARK_TS_DECL_COMMON (WILDCARD_DECL); MARK_TS_DECL_NON_COMMON (USING_DECL); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 3de6923f771..6b17ac78314 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -487,12 +487,6 @@ DEFTREECODE (OMP_DEPOBJ, "omp_depobj", tcc_statement, 2) /* Used to represent information associated with constrained declarations. */ DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0) -/* A wildcard declaration is a placeholder for a template parameter - used to resolve constrained-type-names in concepts. During - resolution, the matching argument is saved as the TREE_TYPE - of the wildcard. */ -DEFTREECODE (WILDCARD_DECL, "wildcard_decl", tcc_declaration, 0) - /* A requires-expr has three operands. The first operand is its parameter list (possibly NULL). The second is a list of requirements, which are denoted by the _REQ* tree codes diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b3c909b05c4..93dc5e7966b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -438,7 +438,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TINFO_HAS_ACCESS_ERRORS (in TEMPLATE_INFO) SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR) COMPOUND_REQ_NOEXCEPT_P (in COMPOUND_REQ) - WILDCARD_PACK_P (in WILDCARD_DECL) BLOCK_OUTER_CURLY_BRACE_P (in BLOCK) FOLD_EXPR_MODIFY_P (*_FOLD_EXPR) IF_STMT_CONSTEXPR_P (IF_STMT) @@ -4042,9 +4041,6 @@ struct GTY(()) lang_decl { #define PACK_EXPANSION_FORCE_EXTRA_ARGS_P(NODE) \ TREE_LANG_FLAG_3 (PACK_EXPANSION_CHECK (NODE)) -/* True iff the wildcard can match a template parameter pack. */ -#define WILDCARD_PACK_P(NODE) TREE_LANG_FLAG_0 (NODE) - /* Determine if this is an argument pack. */ #define ARGUMENT_PACK_P(NODE) \ (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK \ @@ -7532,9 +7528,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 +8591,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); @@ -8890,18 +8877,10 @@ variable_template_p (tree t) /* True iff T is a concept. */ -inline bool -concept_definition_p (tree t) -{ - return TREE_CODE (STRIP_TEMPLATE (t)) == CONCEPT_DECL; -} - -/* Same as above, but for const trees. */ - inline bool concept_definition_p (const_tree t) { - return concept_definition_p (const_cast<tree> (t)); + return TREE_CODE (STRIP_TEMPLATE (t)) == CONCEPT_DECL; } /* True if t is an expression that checks a concept. */ @@ -8914,6 +8893,19 @@ concept_check_p (const_tree t) return false; } +/* Return the prototype parameter of the concept T, + i.e. its first declared template parameter. */ + +inline tree +concept_prototype_parameter (const_tree t) +{ + gcc_checking_assert (concept_definition_p (t)); + if (TREE_CODE (t) == CONCEPT_DECL) + t = DECL_TI_TEMPLATE (t); + tree parms = DECL_INNERMOST_TEMPLATE_PARMS (t); + return TREE_VALUE (TREE_VEC_ELT (parms, 0)); +} + /* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */ inline bool diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc index f4203123737..f42f6aeddbe 100644 --- a/gcc/cp/cxx-pretty-print.cc +++ b/gcc/cp/cxx-pretty-print.cc @@ -2336,8 +2336,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/error.cc b/gcc/cp/error.cc index 7ef79b90868..193b560feca 100644 --- a/gcc/cp/error.cc +++ b/gcc/cp/error.cc @@ -1536,10 +1536,6 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) dump_simple_decl (pp, t, TREE_TYPE (t), flags); break; - case WILDCARD_DECL: - pp_string (pp, "<wildcard>"); - break; - case TEMPLATE_ID_EXPR: { tree name = TREE_OPERAND (t, 0); @@ -2339,7 +2335,6 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags) case TEMPLATE_DECL: case NAMESPACE_DECL: case LABEL_DECL: - case WILDCARD_DECL: case OVERLOAD: case TYPE_DECL: case USING_DECL: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 07b12224615..cede9ddae5a 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -18607,29 +18607,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) { @@ -18667,36 +18648,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. */ @@ -18730,9 +18681,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) @@ -18746,24 +18694,26 @@ finish_constrained_parameter (cp_parser *parser, return parm; } -/* Returns true if the parsed type actually represents the declaration - of a type template-parameter. */ +/* Returns true if the TYPE would declare a constrained type + template-parameter. */ 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. */ +/* Returns true if PARM declares a constrained type template-parameter. */ static bool -declares_constrained_template_template_parameter (tree type) +declares_constrained_type_template_parameter (cp_parameter_declarator *parm) { - return (is_constrained_parameter (type) - && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TEMPLATE_PARM); + tree type = parm->decl_specifiers.type; + return declares_constrained_type_template_parameter (type); } /* Parse a default argument for a type template-parameter. @@ -18936,7 +18886,7 @@ 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)) + if (declares_constrained_type_template_parameter (parameter_declarator)) return finish_constrained_parameter (parser, parameter_declarator, is_non_type); @@ -21019,13 +20969,26 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, /* A concept-name with no arguments can't be an expression. */ tentative = false; + tree con = DECL_TEMPLATE_RESULT (tmpl); + tree proto = concept_prototype_parameter (con); tsubst_flags_t complain = tentative ? tf_none : tf_warning_or_error; + /* A type constraint constrains a contextually determined type or type + parameter pack. */ + if (TREE_CODE (proto) != TYPE_DECL) + { + if (!tentative) + { + auto_diagnostic_group d; + error_at (loc, "%qE does not constrain a type", DECL_NAME (con)); + inform (DECL_SOURCE_LOCATION (con), "concept defined here"); + } + return error_mark_node; + } + /* 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; /* As per the standard, require auto or decltype(auto). */ @@ -21041,19 +21004,6 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, close_paren = parens.require_close (parser); } - /* A type constraint constrains a contextually determined type or type - parameter pack. */ - if (TREE_CODE (proto) != TYPE_DECL) - { - if (!tentative) - { - auto_diagnostic_group d; - error_at (loc, "%qE does not constrain a type", DECL_NAME (con)); - inform (DECL_SOURCE_LOCATION (con), "concept defined here"); - } - return error_mark_node; - } - /* In a template parameter list, a type-parameter can be introduced by type-constraints alone. */ if (processing_template_parmlist && !placeholder) @@ -26165,12 +26115,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 35ec7eba0ba..5ec498fb225 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -8541,16 +8541,6 @@ is_compatible_template_arg (tree parm, tree arg, tree args) return ttp_subsumes (parm_cons, arg); } -// Convert a placeholder argument into a binding to the original -// parameter. The original parameter is saved as the TREE_TYPE of -// ARG. -static inline tree -convert_wildcard_argument (tree parm, tree arg) -{ - TREE_TYPE (arg) = parm; - return arg; -} - /* We can't fully resolve ARG given as a non-type template argument to TYPE, because one of them is dependent. But we need to represent the conversion for the benefit of cp_tree_equal. */ @@ -8605,10 +8595,6 @@ convert_template_argument (tree parm, if (parm == error_mark_node || error_operand_p (arg)) return error_mark_node; - /* Trivially convert placeholders. */ - if (TREE_CODE (arg) == WILDCARD_DECL) - return convert_wildcard_argument (parm, arg); - if (arg == any_targ_node) return arg; @@ -8990,16 +8976,6 @@ coerce_template_parameter_pack (tree parms, packed_args = make_tree_vec (TREE_VEC_LENGTH (packed_parms)); } - /* Check if we have a placeholder pack, which indicates we're - in the context of a introduction list. In that case we want - to match this pack to the single placeholder. */ - else if (arg_idx < nargs - && TREE_CODE (TREE_VEC_ELT (inner_args, arg_idx)) == WILDCARD_DECL - && WILDCARD_PACK_P (TREE_VEC_ELT (inner_args, arg_idx))) - { - nargs = arg_idx + 1; - packed_args = make_tree_vec (1); - } else packed_args = make_tree_vec (nargs - arg_idx); @@ -16494,13 +16470,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { int quals; - /* When building concept checks for the purpose of - deducing placeholders, we can end up with wildcards - where types are expected. Adjust this to the deduced - value. */ - if (TREE_CODE (arg) == WILDCARD_DECL) - arg = TREE_TYPE (TREE_TYPE (arg)); - gcc_assert (TYPE_P (arg)); quals = cp_type_quals (arg) | cp_type_quals (t); @@ -28589,8 +28558,7 @@ type_dependent_expression_p (tree expression) /* An unresolved name is always dependent. */ if (identifier_p (expression) - || TREE_CODE (expression) == USING_DECL - || TREE_CODE (expression) == WILDCARD_DECL) + || TREE_CODE (expression) == USING_DECL) return true; /* A lambda-expression in template context is dependent. dependent_type_p is @@ -29588,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) @@ -29637,8 +29602,7 @@ placeholder_type_constraint_dependent_p (tree t) args = expand_template_argument_pack (args); first = TREE_VEC_ELT (args, 0); } - gcc_checking_assert (TREE_CODE (first) == WILDCARD_DECL - || is_auto (first)); + gcc_checking_assert (is_auto (first)); for (int i = 1; i < TREE_VEC_LENGTH (args); ++i) if (dependent_template_arg_p (TREE_VEC_ELT (args, i))) return true; -- 2.47.1.313.gcc01bad4a9