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. Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
parent
cec97549b7
commit
73e7f63ffa
8 changed files with 78 additions and 317 deletions
|
@ -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,51 +1097,34 @@ 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. */
|
||||
/* Construct an expression that checks TMPL using ARGS. */
|
||||
|
||||
static tree
|
||||
build_standard_check (tree tmpl, tree args, tsubst_flags_t complain)
|
||||
tree
|
||||
build_concept_check (tree tmpl, tree args, tsubst_flags_t complain)
|
||||
{
|
||||
return build_concept_check (tmpl, NULL_TREE, args, complain);
|
||||
}
|
||||
|
||||
/* Construct an expression that checks the concept given by TMPL. */
|
||||
|
||||
tree
|
||||
build_concept_check (tree tmpl, tree arg, tree rest, 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));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Construct an expression that checks TARGET using ARGS. */
|
||||
|
||||
tree
|
||||
build_concept_check (tree target, tree args, tsubst_flags_t complain)
|
||||
{
|
||||
return build_concept_check (target, NULL_TREE, args, complain);
|
||||
}
|
||||
|
||||
/* Construct an expression that checks the concept given by DECL. If
|
||||
concept_definition_p (DECL) is false, this returns null. */
|
||||
|
||||
tree
|
||||
build_concept_check (tree decl, 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);
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Build a template-id that can participate in a concept check. */
|
||||
|
||||
static tree
|
||||
|
@ -1252,9 +1154,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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
|
|
@ -628,7 +628,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);
|
||||
|
||||
|
|
|
@ -495,12 +495,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
|
||||
|
|
|
@ -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)
|
||||
|
@ -4068,9 +4067,6 @@ struct GTY(()) lang_decl {
|
|||
#define PACK_INDEX_PARENTHESIZED_P(NODE) \
|
||||
TREE_LANG_FLAG_1 (TREE_CHECK (NODE, PACK_INDEX_EXPR))
|
||||
|
||||
/* 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 \
|
||||
|
@ -7558,9 +7554,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);
|
||||
|
@ -8627,15 +8620,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);
|
||||
|
@ -8919,18 +8906,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. */
|
||||
|
@ -8943,6 +8922,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
|
||||
|
|
|
@ -2349,8 +2349,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>");
|
||||
|
|
|
@ -1544,10 +1544,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);
|
||||
|
@ -2347,7 +2343,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:
|
||||
|
|
114
gcc/cp/parser.cc
114
gcc/cp/parser.cc
|
@ -18705,29 +18705,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)
|
||||
{
|
||||
|
@ -18765,36 +18746,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. */
|
||||
|
||||
|
@ -18828,9 +18779,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)
|
||||
|
@ -18844,24 +18792,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.
|
||||
|
@ -19034,7 +18984,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);
|
||||
|
@ -21123,13 +21073,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). */
|
||||
|
@ -21145,19 +21108,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)
|
||||
|
@ -26279,12 +26229,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
|
||||
|
|
42
gcc/cp/pt.cc
42
gcc/cp/pt.cc
|
@ -8584,16 +8584,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. */
|
||||
|
@ -8648,10 +8638,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;
|
||||
|
||||
|
@ -9033,16 +9019,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);
|
||||
|
||||
|
@ -16559,13 +16535,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);
|
||||
|
@ -28734,8 +28703,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
|
||||
|
@ -29738,11 +29706,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)
|
||||
|
@ -29787,8 +29752,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;
|
||||
|
|
Loading…
Add table
Reference in a new issue