[3/2] c++: remove WILDCARD_DECL
Commit Message
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk?
-- >8 --
This tree code was added as part of the initial Concepts TS
implementation to support type-constraints introducing any kind
of template-parameter, not just type template-parameters, e.g.
template<int N> concept C = ...;
template<template<class> class TT> concept D = ...;
template<C T, D U> void f(); // T is an NTTP of type int, U is a TTP
When resolving the type-constraint we would use WILDCARD_DECL as the
dummy first argument during template argument coercion that is a valid
argument for any kind of template parameter.
But Concepts TS support has been removed, and C++20 type-constraints are
restricted to only introduce type template-parameters, and so we don't
need this catch-all WILDCARD_DECL anymore; we can instead use an auto
as the dummy first argument.
In passing introduce a helper for returning the prototype parameter
(i.e. first template parameter) of a concept and use it. Also remove a
redundant concept_definition_p overload.
gcc/cp/ChangeLog:
* constraint.cc (build_type_constraint): Use an auto as the
first template argument.
(finish_shorthand_constraint): Use concept_prototype_parameter.
* 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.
(concept_definition_p): Remove redundant overload.
(concept_prototype_parameter): Define.
* error.cc (dump_decl) <case WILDCARD_DECL>: Remove.
(dump_expr) <case WILDCARD_DECL>: Likewise.
* parser.cc (cp_parser_placeholder_type_specifier): Check
the prototype parameter earlier, before build_type_constraint.
Use concept_prototype_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.
(placeholder_type_constraint_dependent_p): Likewise.
---
gcc/cp/constraint.cc | 6 ++----
gcc/cp/cp-objcp-common.cc | 1 -
gcc/cp/cp-tree.def | 6 ------
gcc/cp/cp-tree.h | 27 ++++++++++++++-------------
gcc/cp/error.cc | 5 -----
gcc/cp/parser.cc | 31 +++++++++++++++----------------
gcc/cp/pt.cc | 37 ++-----------------------------------
7 files changed, 33 insertions(+), 80 deletions(-)
Comments
On Wed, 23 Oct 2024, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?
>
> -- >8 --
>
> This tree code was added as part of the initial Concepts TS
> implementation to support type-constraints introducing any kind
> of template-parameter, not just type template-parameters, e.g.
>
> template<int N> concept C = ...;
> template<template<class> class TT> concept D = ...;
>
> template<C T, D U> void f(); // T is an NTTP of type int, U is a TTP
>
> When resolving the type-constraint we would use WILDCARD_DECL as the
> dummy first argument during template argument coercion that is a valid
> argument for any kind of template parameter.
>
> But Concepts TS support has been removed, and C++20 type-constraints are
> restricted to only introduce type template-parameters, and so we don't
> need this catch-all WILDCARD_DECL anymore; we can instead use an auto
> as the dummy first argument.
>
> In passing introduce a helper for returning the prototype parameter
> (i.e. first template parameter) of a concept and use it. Also remove a
> redundant concept_definition_p overload.
>
> gcc/cp/ChangeLog:
>
> * constraint.cc (build_type_constraint): Use an auto as the
> first template argument.
> (finish_shorthand_constraint): Use concept_prototype_parameter.
> * 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.
> (concept_definition_p): Remove redundant overload.
> (concept_prototype_parameter): Define.
> * error.cc (dump_decl) <case WILDCARD_DECL>: Remove.
> (dump_expr) <case WILDCARD_DECL>: Likewise.
> * parser.cc (cp_parser_placeholder_type_specifier): Check
> the prototype parameter earlier, before build_type_constraint.
> Use concept_prototype_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.
> (placeholder_type_constraint_dependent_p): Likewise.
> ---
> gcc/cp/constraint.cc | 6 ++----
> gcc/cp/cp-objcp-common.cc | 1 -
> gcc/cp/cp-tree.def | 6 ------
> gcc/cp/cp-tree.h | 27 ++++++++++++++-------------
> gcc/cp/error.cc | 5 -----
> gcc/cp/parser.cc | 31 +++++++++++++++----------------
> gcc/cp/pt.cc | 37 ++-----------------------------------
> 7 files changed, 33 insertions(+), 80 deletions(-)
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 9394bea8835..d6a6ac03393 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -1154,9 +1154,8 @@ build_concept_id (tree expr)
> tree
> build_type_constraint (tree decl, tree args, tsubst_flags_t complain)
> {
> - tree wildcard = build_nt (WILDCARD_DECL);
> ++processing_template_decl;
> - tree check = build_concept_check (decl, wildcard, args, complain);
> + tree check = build_concept_check (decl, make_auto (), args, complain);
On second thought I think it's better simply use the prototype parameter
as its own argument here so that we don't have to allocate a new auto
for each type-constraint we build. And it's more in the spirit with how
WILDCARD_DECL behaved.
Like so:
-- >8 --
Subject: [PATCH v2] c++: remove WILDCARD_DECL
gcc/cp/ChangeLog:
* constraint.cc (build_type_constraint): Use the prototype
parameter as the first template argument.
(finish_shorthand_constraint): Use concept_prototype_parameter.
* 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.
(concept_definition_p): Remove redundant overload.
(concept_prototype_parameter): Define.
* error.cc (dump_decl) <case WILDCARD_DECL>: Remove.
(dump_expr) <case WILDCARD_DECL>: Likewise.
* parser.cc (cp_parser_placeholder_type_specifier): Check
the prototype parameter earlier, before build_type_constraint.
Use concept_prototype_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.
(placeholder_type_constraint_dependent_p): Likewise.
---
gcc/cp/constraint.cc | 7 +++----
gcc/cp/cp-objcp-common.cc | 1 -
gcc/cp/cp-tree.def | 6 ------
gcc/cp/cp-tree.h | 27 ++++++++++++++-------------
gcc/cp/error.cc | 5 -----
gcc/cp/parser.cc | 31 +++++++++++++++----------------
gcc/cp/pt.cc | 37 ++-----------------------------------
7 files changed, 34 insertions(+), 80 deletions(-)
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 9394bea8835..8b826cb240e 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1154,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;
}
@@ -1203,8 +1203,7 @@ finish_shorthand_constraint (tree decl, tree constr, bool is_non_type)
{
tree id = PLACEHOLDER_TYPE_CONSTRAINTS (constr);
tree tmpl = TREE_OPERAND (id, 0);
- tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
- proto = TREE_VALUE (TREE_VEC_ELT (parms, 0));
+ proto = concept_prototype_parameter (tmpl);
con = DECL_TEMPLATE_RESULT (tmpl);
args = TREE_OPERAND (id, 1);
}
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index cd379514991..69eed72a5a2 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -624,7 +624,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 18f75108c7b..53511a6d8cc 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 6dcf32b178e..c25dafd5981 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 \
@@ -8879,18 +8875,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. */
@@ -8903,6 +8891,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/error.cc b/gcc/cp/error.cc
index 65f70c595cf..c5b256f3907 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1542,10 +1542,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);
@@ -2376,7 +2372,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 0bad62978dc..16e05acd7b8 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -20918,15 +20918,27 @@ 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 = STRIP_TEMPLATE (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 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;
@@ -20941,19 +20953,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)
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ec4313090bd..9833b2bea5f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8539,16 +8539,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. */
@@ -8603,10 +8593,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;
@@ -8988,16 +8974,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);
@@ -16489,13 +16465,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);
@@ -28559,8 +28528,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
@@ -29603,8 +29571,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;
On Fri, 25 Oct 2024, Patrick Palka wrote:
> On Wed, 23 Oct 2024, Patrick Palka wrote:
>
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> > OK for trunk?
> >
> > -- >8 --
> >
> > This tree code was added as part of the initial Concepts TS
> > implementation to support type-constraints introducing any kind
> > of template-parameter, not just type template-parameters, e.g.
> >
> > template<int N> concept C = ...;
> > template<template<class> class TT> concept D = ...;
> >
> > template<C T, D U> void f(); // T is an NTTP of type int, U is a TTP
> >
> > When resolving the type-constraint we would use WILDCARD_DECL as the
> > dummy first argument during template argument coercion that is a valid
> > argument for any kind of template parameter.
> >
> > But Concepts TS support has been removed, and C++20 type-constraints are
> > restricted to only introduce type template-parameters, and so we don't
> > need this catch-all WILDCARD_DECL anymore; we can instead use an auto
> > as the dummy first argument.
> >
> > In passing introduce a helper for returning the prototype parameter
> > (i.e. first template parameter) of a concept and use it. Also remove a
> > redundant concept_definition_p overload.
> >
> > gcc/cp/ChangeLog:
> >
> > * constraint.cc (build_type_constraint): Use an auto as the
> > first template argument.
> > (finish_shorthand_constraint): Use concept_prototype_parameter.
> > * 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.
> > (concept_definition_p): Remove redundant overload.
> > (concept_prototype_parameter): Define.
> > * error.cc (dump_decl) <case WILDCARD_DECL>: Remove.
> > (dump_expr) <case WILDCARD_DECL>: Likewise.
> > * parser.cc (cp_parser_placeholder_type_specifier): Check
> > the prototype parameter earlier, before build_type_constraint.
> > Use concept_prototype_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.
> > (placeholder_type_constraint_dependent_p): Likewise.
> > ---
> > gcc/cp/constraint.cc | 6 ++----
> > gcc/cp/cp-objcp-common.cc | 1 -
> > gcc/cp/cp-tree.def | 6 ------
> > gcc/cp/cp-tree.h | 27 ++++++++++++++-------------
> > gcc/cp/error.cc | 5 -----
> > gcc/cp/parser.cc | 31 +++++++++++++++----------------
> > gcc/cp/pt.cc | 37 ++-----------------------------------
> > 7 files changed, 33 insertions(+), 80 deletions(-)
> >
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index 9394bea8835..d6a6ac03393 100644
> > --- a/gcc/cp/constraint.cc
> > +++ b/gcc/cp/constraint.cc
> > @@ -1154,9 +1154,8 @@ build_concept_id (tree expr)
> > tree
> > build_type_constraint (tree decl, tree args, tsubst_flags_t complain)
> > {
> > - tree wildcard = build_nt (WILDCARD_DECL);
> > ++processing_template_decl;
> > - tree check = build_concept_check (decl, wildcard, args, complain);
> > + tree check = build_concept_check (decl, make_auto (), args, complain);
>
> On second thought I think it's better simply use the prototype parameter
> as its own argument here so that we don't have to allocate a new auto
> for each type-constraint we build. And it's more in the spirit with how
> WILDCARD_DECL behaved.
>
> Like so:
Ping.
>
> -- >8 --
>
> Subject: [PATCH v2] c++: remove WILDCARD_DECL
>
> gcc/cp/ChangeLog:
>
> * constraint.cc (build_type_constraint): Use the prototype
> parameter as the first template argument.
> (finish_shorthand_constraint): Use concept_prototype_parameter.
> * 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.
> (concept_definition_p): Remove redundant overload.
> (concept_prototype_parameter): Define.
> * error.cc (dump_decl) <case WILDCARD_DECL>: Remove.
> (dump_expr) <case WILDCARD_DECL>: Likewise.
> * parser.cc (cp_parser_placeholder_type_specifier): Check
> the prototype parameter earlier, before build_type_constraint.
> Use concept_prototype_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.
> (placeholder_type_constraint_dependent_p): Likewise.
> ---
> gcc/cp/constraint.cc | 7 +++----
> gcc/cp/cp-objcp-common.cc | 1 -
> gcc/cp/cp-tree.def | 6 ------
> gcc/cp/cp-tree.h | 27 ++++++++++++++-------------
> gcc/cp/error.cc | 5 -----
> gcc/cp/parser.cc | 31 +++++++++++++++----------------
> gcc/cp/pt.cc | 37 ++-----------------------------------
> 7 files changed, 34 insertions(+), 80 deletions(-)
>
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 9394bea8835..8b826cb240e 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -1154,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;
> }
> @@ -1203,8 +1203,7 @@ finish_shorthand_constraint (tree decl, tree constr, bool is_non_type)
> {
> tree id = PLACEHOLDER_TYPE_CONSTRAINTS (constr);
> tree tmpl = TREE_OPERAND (id, 0);
> - tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
> - proto = TREE_VALUE (TREE_VEC_ELT (parms, 0));
> + proto = concept_prototype_parameter (tmpl);
> con = DECL_TEMPLATE_RESULT (tmpl);
> args = TREE_OPERAND (id, 1);
> }
> diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
> index cd379514991..69eed72a5a2 100644
> --- a/gcc/cp/cp-objcp-common.cc
> +++ b/gcc/cp/cp-objcp-common.cc
> @@ -624,7 +624,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 18f75108c7b..53511a6d8cc 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 6dcf32b178e..c25dafd5981 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 \
> @@ -8879,18 +8875,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. */
> @@ -8903,6 +8891,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/error.cc b/gcc/cp/error.cc
> index 65f70c595cf..c5b256f3907 100644
> --- a/gcc/cp/error.cc
> +++ b/gcc/cp/error.cc
> @@ -1542,10 +1542,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);
> @@ -2376,7 +2372,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 0bad62978dc..16e05acd7b8 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -20918,15 +20918,27 @@ 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 = STRIP_TEMPLATE (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 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;
> @@ -20941,19 +20953,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)
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index ec4313090bd..9833b2bea5f 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -8539,16 +8539,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. */
> @@ -8603,10 +8593,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;
>
> @@ -8988,16 +8974,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);
>
> @@ -16489,13 +16465,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);
> @@ -28559,8 +28528,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
> @@ -29603,8 +29571,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.0.118.gfd3785337b
>
>
> > --processing_template_decl;
> > return check;
> > }
> > @@ -1203,8 +1202,7 @@ finish_shorthand_constraint (tree decl, tree constr, bool is_non_type)
> > {
> > tree id = PLACEHOLDER_TYPE_CONSTRAINTS (constr);
> > tree tmpl = TREE_OPERAND (id, 0);
> > - tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
> > - proto = TREE_VALUE (TREE_VEC_ELT (parms, 0));
> > + proto = concept_prototype_parameter (tmpl);
> > con = DECL_TEMPLATE_RESULT (tmpl);
> > args = TREE_OPERAND (id, 1);
> > }
> > diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
> > index cd379514991..69eed72a5a2 100644
> > --- a/gcc/cp/cp-objcp-common.cc
> > +++ b/gcc/cp/cp-objcp-common.cc
> > @@ -624,7 +624,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 18f75108c7b..53511a6d8cc 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 6dcf32b178e..c25dafd5981 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 \
> > @@ -8879,18 +8875,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. */
> > @@ -8903,6 +8891,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/error.cc b/gcc/cp/error.cc
> > index 65f70c595cf..c5b256f3907 100644
> > --- a/gcc/cp/error.cc
> > +++ b/gcc/cp/error.cc
> > @@ -1542,10 +1542,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);
> > @@ -2376,7 +2372,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 0bad62978dc..16e05acd7b8 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -20918,15 +20918,27 @@ 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 = STRIP_TEMPLATE (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 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;
> > @@ -20941,19 +20953,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)
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index ec4313090bd..9833b2bea5f 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -8539,16 +8539,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. */
> > @@ -8603,10 +8593,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;
> >
> > @@ -8988,16 +8974,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);
> >
> > @@ -16489,13 +16465,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);
> > @@ -28559,8 +28528,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
> > @@ -29603,8 +29571,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.0.118.gfd3785337b
> >
> >
>
On 10/23/24 4:30 PM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?
>
> -- >8 --
>
> This tree code was added as part of the initial Concepts TS
> implementation to support type-constraints introducing any kind
> of template-parameter, not just type template-parameters, e.g.
>
> template<int N> concept C = ...;
> template<template<class> class TT> concept D = ...;
>
> template<C T, D U> void f(); // T is an NTTP of type int, U is a TTP
>
> When resolving the type-constraint we would use WILDCARD_DECL as the
> dummy first argument during template argument coercion that is a valid
> argument for any kind of template parameter.
>
> But Concepts TS support has been removed, and C++20 type-constraints are
> restricted to only introduce type template-parameters, and so we don't
> need this catch-all WILDCARD_DECL anymore; we can instead use an auto
> as the dummy first argument.
>
> In passing introduce a helper for returning the prototype parameter
> (i.e. first template parameter) of a concept and use it.
Ah, exactly what I was missing in the first patch; let's squash this
patch together with that one. Then there's just the
declares_constrained_type_template_parameter comment.
Jason
@@ -1154,9 +1154,8 @@ build_concept_id (tree expr)
tree
build_type_constraint (tree decl, tree args, tsubst_flags_t complain)
{
- tree wildcard = build_nt (WILDCARD_DECL);
++processing_template_decl;
- tree check = build_concept_check (decl, wildcard, args, complain);
+ tree check = build_concept_check (decl, make_auto (), args, complain);
--processing_template_decl;
return check;
}
@@ -1203,8 +1202,7 @@ finish_shorthand_constraint (tree decl, tree constr, bool is_non_type)
{
tree id = PLACEHOLDER_TYPE_CONSTRAINTS (constr);
tree tmpl = TREE_OPERAND (id, 0);
- tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
- proto = TREE_VALUE (TREE_VEC_ELT (parms, 0));
+ proto = concept_prototype_parameter (tmpl);
con = DECL_TEMPLATE_RESULT (tmpl);
args = TREE_OPERAND (id, 1);
}
@@ -624,7 +624,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);
@@ -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
@@ -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 \
@@ -8879,18 +8875,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. */
@@ -8903,6 +8891,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
@@ -1542,10 +1542,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);
@@ -2376,7 +2372,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:
@@ -20918,15 +20918,27 @@ 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 = STRIP_TEMPLATE (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 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;
@@ -20941,19 +20953,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)
@@ -8539,16 +8539,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. */
@@ -8603,10 +8593,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;
@@ -8988,16 +8974,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);
@@ -16489,13 +16465,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);
@@ -28559,8 +28528,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
@@ -29603,8 +29571,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;