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:
Patrick Palka 2024-12-02 10:58:50 -05:00
parent cec97549b7
commit 73e7f63ffa
8 changed files with 78 additions and 317 deletions

View file

@ -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);

View file

@ -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);

View file

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

View file

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

View file

@ -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>");

View file

@ -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:

View file

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

View file

@ -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;