On Tue, 5 Nov 2024, Jason Merrill wrote:

> On 10/15/24 12:45 AM, Patrick Palka wrote:
> > This patch further cleans up the concepts code following the removal of
> > Concepts TS support:
> > 
> >    * concept-ids are now the only kind of "concept check", so we can
> >      simplify some code accordingly.  In particular resolve_concept_check
> >      seems like a no-op and can be removed.
> >    * In turn, deduce_constrained_parameter doesn't seem to do anything
> >      interesting.
> >    * In light of the above we might as well inline finish_type_constraints
> >      into its only caller.  Note that the "prototype parameter" of a
> >      concept is just the first template parameter which the caller can
> >      easily obtain itself.
> 
> But it's still a defined term in the language
> (https://eel.is/c++draft/temp#concept-7) so I think it's worth having an
> accessor function.  I agree with doing away with the function that returns a
> pair.

Done.

> 
> >    * placeholder_extract_concept_and_args is only ever called on a
> >      concept-id, so it's simpler to inline it into its callers.
> >    * There's no such thing as a template-template-parameter wtih a
> >      type-constraint, so we can remove such handling from the parser.
> >      This means is_constrained_parameter is currently equivalent to
> >      declares_constrained_template_template_parameter, so let's prefer
> >      to use the latter.
> 
> Why prefer the longer name?

"is_constrained_parameter" suggests it should return true for a
constrained non-type parameter, but that's currently not the case and
callers don't expect/want that behavior, so the longer name seems
more accurate.

> 
> > We might be able to remove WILDCARD_DECL and CONSTRAINED_PARM_PROTOTYPE
> > now as well, but I left that as future work.
> > 
> > @@ -18901,7 +18842,8 @@ cp_parser_template_parameter (cp_parser* parser,
> > bool *is_non_type,
> >       }
> >       /* The parameter may have been constrained type parameter.  */
> > -  if (is_constrained_parameter (parameter_declarator))
> > +  tree type = parameter_declarator->decl_specifiers.type;
> > +  if (declares_constrained_type_template_parameter (type))
> 
> Why not retain a function that takes the declarator?

I added another overload of declares_constrained_type_template_parameter
taking a cp_parameter_declarator.

> 
> >       return finish_constrained_parameter (parser,
> >                                            parameter_declarator,
> >                                            is_non_type);
> > @@ -20987,11 +20929,12 @@ cp_parser_placeholder_type_specifier (cp_parser
> > *parser, location_t loc,
> >     tsubst_flags_t complain = tentative ? tf_none : tf_warning_or_error;
> >       /* Get the concept and prototype parameter for the constraint.  */
> > -  tree_pair info = finish_type_constraints (tmpl, args, complain);
> > -  tree con = info.first;
> > -  tree proto = info.second;
> > -  if (con == error_mark_node)
> > +  tree check = build_type_constraint (tmpl, args, complain);
> > +  if (check == error_mark_node)
> >       return error_mark_node;
> > +  tree con = STRIP_TEMPLATE (tmpl);
> > +  tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
> > +  tree proto = TREE_VALUE (TREE_VEC_ELT (parms, 0));
> 
> And as mentioned above, let's have a small function that returns the prototype
> parameter of a concept, to use here.

Done.

> 
> Incidentally, why do we want to strip the template from con?  Is that also a
> relic of the different possible forms of concept?

Oops, I think we could use DECL_TEMPLATE_RESULT here instead of STRIP_TEMPLATE,
since 'tmpl' will always be a TEMPLATE_DECL.

Here's v2 which squashes the 3rd patch (removing WILDCARD_DECL) into
this one, and addresses your feedback.

-- >8 --

Subject: [PATCH] c++: some further concepts cleanups

This patch further cleans up the concepts code following the removal of
Concepts TS support:

  * concept-ids are now the only kind of "concept check", so we can
    simplify some code accordingly.  In particular resolve_concept_check
    seems like a no-op and can be removed.
  * In turn, deduce_constrained_parameter doesn't seem to do anything
    interesting.
  * In light of the above we might as well inline finish_type_constraints
    into its only caller.
  * Introduce and use a helper for obtaining the prototype parameter of
    a concept, i.e. its first template parameter.
  * placeholder_extract_concept_and_args is only ever called on a
    concept-id, so it's simpler to inline it into its callers.
  * There's no such thing as a template-template-parameter with a
    type-constraint, so we can remove such handling from the parser.
    This means is_constrained_parameter is currently equivalent to
    declares_constrained_type_template_parameter, so let's prefer
    to use the latter.
  * Remove WILDCARD_DECL and instead use the concept's prototype parameter
    as the dummy first argument of a type-constraint during template
    argument coercion.
  * Remove a redundant concept_definition_p overload.

gcc/cp/ChangeLog:

        * constraint.cc (resolve_concept_check): Remove.
        (deduce_constrained_parameter): Remove.
        (finish_type_constraints): Inline into its only caller
        cp_parser_placeholder_type_specifier and remove.
        (build_concept_check_arguments): Coding style tweaks.
        (build_standard_check): Inline into its only caller ...
        (build_concept_check): ... here.
        (build_type_constraint): Use the prototype parameter as the
        first template argument.
        (finish_shorthand_constraint): Remove function concept
        handling.  Use concept_prototype_parameter.
        (placeholder_extract_concept_and_args): Inline into its
        callers and remove.
        (equivalent_placeholder_constraints): Adjust after
        placeholder_extract_concept_and_args removal.
        (iterative_hash_placeholder_constraint): Likewise.
        * cp-objcp-common.cc (cp_common_init_ts): Remove WILDCARD_DECL
        handling.
        * cp-tree.def (WILDCARD_DECL): Remove.
        * cp-tree.h (WILDCARD_PACK_P): Remove.
        (type_uses_auto_or_concept): Remove declaration of nonexistent
        function.
        (append_type_to_template_for_access_check): Likewise.
        (finish_type_constraints): Remove declaration.
        (placeholder_extract_concept_and_args): Remove declaration.
        (deduce_constrained_parameter): Remove declaration.
        (resolve_constraint_check): Remove declaration.
        (valid_requirements_p): Remove declaration of nonexistent
        function.
        (finish_concept_name): Likewise.
        (concept_definition_p): Remove redundant overload.
        (concept_prototype_parameter): Define.
        * cxx-pretty-print.cc (pp_cxx_constrained_type_spec): Adjust
        after placeholder_extract_concept_and_args.
        * error.cc (dump_decl) <case WILDCARD_DECL>: Remove.
        (dump_expr) <case WILDCARD_DECL>: Likewise.
        * parser.cc (is_constrained_parameter): Inline into
        declares_constrained_type_template_parameter and remove.
        (cp_parser_check_constrained_type_parm): Declare static.
        (finish_constrained_template_template_parm): Remove.
        (cp_parser_constrained_template_template_parm): Remove.
        (finish_constrained_parameter): Remove dead code guarded by
        cp_parser_constrained_template_template_parm.
        (declares_constrained_type_template_parameter): Adjust after
        is_constrained_parameter removal.
        (declares_constrained_template_template_parameter): Remove.
        (cp_parser_placeholder_type_specifier): Adjust after
        finish_type_constraints removal.  Check the prototype parameter
        earlier, before build_type_constraint.
        Use concept_prototype_parameter.
        (cp_parser_parameter_declaration): Remove dead code guarded by
        declares_constrained_template_template_parameter.
        * pt.cc (convert_wildcard_argument): Remove.
        (convert_template_argument): Remove WILDCARD_DECL handling.
        (coerce_template_parameter_pack): Likewise.
        (tsubst) <case TEMPLATE_TYPE_PARM>: Likewise.
        (type_dependent_expression_p): Likewise.
        (make_constrained_placeholder_type): Remove function concept
        handling.
        (placeholder_type_constraint_dependent_p): Remove WILDCARD_DECL
        handling.
---
 gcc/cp/constraint.cc       | 185 ++++++-------------------------------
 gcc/cp/cp-objcp-common.cc  |   1 -
 gcc/cp/cp-tree.def         |   6 --
 gcc/cp/cp-tree.h           |  36 +++-----
 gcc/cp/cxx-pretty-print.cc |   4 +-
 gcc/cp/error.cc            |   5 -
 gcc/cp/parser.cc           | 114 ++++++-----------------
 gcc/cp/pt.cc               |  42 +--------
 8 files changed, 77 insertions(+), 316 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8a36b9c88c4..2dd7efdee76 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -242,88 +242,6 @@ get_concept_check_template (tree t)
   return TREE_OPERAND (t, 0);
 }
 
-/*---------------------------------------------------------------------------
-                    Resolution of qualified concept names
----------------------------------------------------------------------------*/
-
-/* This facility is used to resolve constraint checks from requirement
-   expressions.  A constraint check is a call to a function template declared
-   with the keyword 'concept'.
-
-   The result of resolution is a pair (a TREE_LIST) whose value is the
-   matched declaration, and whose purpose contains the coerced template
-   arguments that can be substituted into the call.  */
-
-/* Returns a pair containing the checked concept and its associated
-   prototype parameter.  The result is a TREE_LIST whose TREE_VALUE
-   is the concept (non-template) and whose TREE_PURPOSE contains
-   the converted template arguments, including the deduced prototype
-   parameter (in position 0).  */
-
-tree
-resolve_concept_check (tree check)
-{
-  gcc_assert (concept_check_p (check));
-  tree tmpl = TREE_OPERAND (check, 0);
-  tree args = TREE_OPERAND (check, 1);
-  tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
-  ++processing_template_decl;
-  tree result = coerce_template_parms (parms, args, tmpl, tf_none);
-  --processing_template_decl;
-  if (result == error_mark_node)
-    return error_mark_node;
-  return build_tree_list (result, DECL_TEMPLATE_RESULT (tmpl));
-}
-
-/* Given a call expression or template-id expression to a concept EXPR
-   possibly including a wildcard, deduce the concept being checked and
-   the prototype parameter.  Returns true if the constraint and prototype
-   can be deduced and false otherwise.  Note that the CHECK and PROTO
-   arguments are set to NULL_TREE if this returns false.  */
-
-bool
-deduce_constrained_parameter (tree expr, tree& check, tree& proto)
-{
-  tree info = resolve_concept_check (expr);
-  if (info && info != error_mark_node)
-    {
-      check = TREE_VALUE (info);
-      tree arg = TREE_VEC_ELT (TREE_PURPOSE (info), 0);
-      if (ARGUMENT_PACK_P (arg))
-       arg = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0);
-      proto = TREE_TYPE (arg);
-      return true;
-    }
-
-  check = proto = NULL_TREE;
-  return false;
-}
-
-/* Build a constrained placeholder type where SPEC is a type-constraint.
-   SPEC can be anything were concept_definition_p is true.
-
-   Returns a pair whose FIRST is the concept being checked and whose
-   SECOND is the prototype parameter.  */
-
-tree_pair
-finish_type_constraints (tree spec, tree args, tsubst_flags_t complain)
-{
-  gcc_assert (concept_definition_p (spec));
-
-  /* Build an initial concept check.  */
-  tree check = build_type_constraint (spec, args, complain);
-  if (check == error_mark_node)
-    return std::make_pair (error_mark_node, NULL_TREE);
-
-  /* Extract the concept and prototype parameter from the check.  */
-  tree con;
-  tree proto;
-  if (!deduce_constrained_parameter (check, con, proto))
-    return std::make_pair (error_mark_node, NULL_TREE);
-
-  return std::make_pair (con, proto);
-}
-
 /*---------------------------------------------------------------------------
                        Expansion of concept definitions
 ---------------------------------------------------------------------------*/
@@ -1162,10 +1080,11 @@ get_trailing_function_requirements (tree t)
 
 /* Construct a sequence of template arguments by prepending
    ARG to REST.  Either ARG or REST may be null.  */
+
 static tree
 build_concept_check_arguments (tree arg, tree rest)
 {
-  gcc_assert (rest ? TREE_CODE (rest) == TREE_VEC : true);
+  gcc_assert (!rest || TREE_CODE (rest) == TREE_VEC);
   tree args;
   if (arg)
     {
@@ -1179,49 +1098,32 @@ build_concept_check_arguments (tree arg, tree rest)
       SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, def + 1);
     }
   else
-    {
-      args = rest;
-    }
+    args = rest;
   return args;
 }
 
-/* Builds an id-expression of the form `C<Args...>` where C is a standard
-   concept.  */
-
-static tree
-build_standard_check (tree tmpl, tree args, tsubst_flags_t complain)
-{
-  gcc_assert (concept_definition_p (tmpl));
-  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
-  if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
-    warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
-  tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
-  args = coerce_template_parms (parms, args, tmpl, complain);
-  if (args == error_mark_node)
-    return error_mark_node;
-  return build2 (TEMPLATE_ID_EXPR, boolean_type_node, tmpl, args);
-}
-
-/* Construct an expression that checks TARGET using ARGS.  */
+/* Construct an expression that checks TMPL using ARGS.  */
 
 tree
-build_concept_check (tree target, tree args, tsubst_flags_t complain)
+build_concept_check (tree tmpl, tree args, tsubst_flags_t complain)
 {
-  return build_concept_check (target, NULL_TREE, args, complain);
+  return build_concept_check (tmpl, NULL_TREE, args, complain);
 }
 
-/* Construct an expression that checks the concept given by DECL.  If
-   concept_definition_p (DECL) is false, this returns null.  */
+/* Construct an expression that checks the concept given by TMPL.  */
 
 tree
-build_concept_check (tree decl, tree arg, tree rest, tsubst_flags_t complain)
+build_concept_check (tree tmpl, tree arg, tree rest, tsubst_flags_t complain)
 {
-  tree args = build_concept_check_arguments (arg, rest);
-
-  if (concept_definition_p (decl))
-    return build_standard_check (decl, args, complain);
+  if (TREE_DEPRECATED (DECL_TEMPLATE_RESULT (tmpl)))
+    warn_deprecated_use (DECL_TEMPLATE_RESULT (tmpl), NULL_TREE);
 
-  return error_mark_node;
+  tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
+  tree args = build_concept_check_arguments (arg, rest);
+  args = coerce_template_parms (parms, args, tmpl, complain);
+  if (args == error_mark_node)
+    return error_mark_node;
+  return build2 (TEMPLATE_ID_EXPR, boolean_type_node, tmpl, args);
 }
 
 /* Build a template-id that can participate in a concept check.  */
@@ -1253,9 +1155,9 @@ build_concept_id (tree expr)
 tree
 build_type_constraint (tree decl, tree args, tsubst_flags_t complain)
 {
-  tree wildcard = build_nt (WILDCARD_DECL);
+  tree proto = template_parm_to_arg (concept_prototype_parameter (decl));
   ++processing_template_decl;
-  tree check = build_concept_check (decl, wildcard, args, complain);
+  tree check = build_concept_check (decl, proto, args, complain);
   --processing_template_decl;
   return check;
 }
@@ -1313,10 +1215,7 @@ finish_shorthand_constraint (tree decl, tree constr)
 
   /* Build the concept constraint-expression.  */
   tree tmpl = DECL_TI_TEMPLATE (con);
-  tree check = tmpl;
-  if (TREE_CODE (con) == FUNCTION_DECL)
-    check = ovl_make (tmpl);
-  check = build_concept_check (check, arg, args, tf_warning_or_error);
+  tree check = build_concept_check (tmpl, arg, args, tf_warning_or_error);
 
   /* Make the check a fold-expression if needed.
      Use UNKNOWN_LOCATION so write_template_args can tell the
@@ -1346,32 +1245,6 @@ get_shorthand_constraints (tree parms)
   return result;
 }
 
-/* Given the concept check T from a constrained-type-specifier, extract
-   its TMPL and ARGS.  FIXME why do we need two different forms of
-   constrained-type-specifier?  */
-
-void
-placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args)
-{
-  if (concept_check_p (t))
-    {
-      tmpl = TREE_OPERAND (t, 0);
-      args = TREE_OPERAND (t, 1);
-      return;
-    }
-
-  if (TREE_CODE (t) == TYPE_DECL)
-    {
-      /* A constrained parameter.  Build a constraint check
-         based on the prototype parameter and then extract the
-         arguments from that.  */
-      tree proto = CONSTRAINED_PARM_PROTOTYPE (t);
-      tree check = finish_shorthand_constraint (proto, t);
-      placeholder_extract_concept_and_args (check, tmpl, args);
-      return;
-    }
-}
-
 /* Returns true iff the placeholders C1 and C2 are equivalent.  C1
    and C2 can be either TEMPLATE_TYPE_PARM or template-ids.  */
 
@@ -1394,9 +1267,11 @@ equivalent_placeholder_constraints (tree c1, tree c2)
        placeholder constraints.  */
     return false;
 
-  tree t1, t2, a1, a2;
-  placeholder_extract_concept_and_args (c1, t1, a1);
-  placeholder_extract_concept_and_args (c2, t2, a2);
+  gcc_assert (concept_check_p (c1) && concept_check_p (c2));
+  tree t1 = TREE_OPERAND (c1, 0);
+  tree a1 = TREE_OPERAND (c1, 1);
+  tree t2 = TREE_OPERAND (c2, 0);
+  tree a2 = TREE_OPERAND (c2, 1);
 
   if (t1 != t2)
     return false;
@@ -1409,12 +1284,9 @@ equivalent_placeholder_constraints (tree c1, tree c2)
   /* Skip the first argument so we don't infinitely recurse.
      Also, they may differ in template parameter index.  */
   for (int i = 1; i < len1; ++i)
-    {
-      tree t1 = TREE_VEC_ELT (a1, i);
-      tree t2 = TREE_VEC_ELT (a2, i);
-      if (!template_args_equal (t1, t2))
+    if (!template_args_equal (TREE_VEC_ELT (a1, i),
+                             TREE_VEC_ELT (a2, i)))
       return false;
-    }
   return true;
 }
 
@@ -1423,8 +1295,9 @@ equivalent_placeholder_constraints (tree c1, tree c2)
 hashval_t
 iterative_hash_placeholder_constraint (tree c, hashval_t val)
 {
-  tree t, a;
-  placeholder_extract_concept_and_args (c, t, a);
+  gcc_assert (concept_check_p (c));
+  tree t = TREE_OPERAND (c, 0);
+  tree a = TREE_OPERAND (c, 1);
 
   /* Like hash_tmpl_and_args, but skip the first argument.  */
   val = iterative_hash_object (DECL_UID (t), val);
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 921931b9846..02ba2649b3a 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -629,7 +629,6 @@ cp_common_init_ts (void)
 
   /* New decls.  */
   MARK_TS_DECL_COMMON (TEMPLATE_DECL);
-  MARK_TS_DECL_COMMON (WILDCARD_DECL);
 
   MARK_TS_DECL_NON_COMMON (USING_DECL);
 
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 3de6923f771..6b17ac78314 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -487,12 +487,6 @@ DEFTREECODE (OMP_DEPOBJ, "omp_depobj", tcc_statement, 2)
 /* Used to represent information associated with constrained declarations. */
 DEFTREECODE (CONSTRAINT_INFO, "constraint_info", tcc_exceptional, 0)
 
-/* A wildcard declaration is a placeholder for a template parameter
-   used to resolve constrained-type-names in concepts.  During
-   resolution, the matching argument is saved as the TREE_TYPE
-   of the wildcard.  */
-DEFTREECODE (WILDCARD_DECL, "wildcard_decl", tcc_declaration, 0)
-
 /* A requires-expr has three operands. The first operand is
    its parameter list (possibly NULL). The second is a list of
    requirements, which are denoted by the _REQ* tree codes
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b3c909b05c4..93dc5e7966b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -438,7 +438,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       TINFO_HAS_ACCESS_ERRORS (in TEMPLATE_INFO)
       SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR)
       COMPOUND_REQ_NOEXCEPT_P (in COMPOUND_REQ)
-      WILDCARD_PACK_P (in WILDCARD_DECL)
       BLOCK_OUTER_CURLY_BRACE_P (in BLOCK)
       FOLD_EXPR_MODIFY_P (*_FOLD_EXPR)
       IF_STMT_CONSTEXPR_P (IF_STMT)
@@ -4042,9 +4041,6 @@ struct GTY(()) lang_decl {
 #define PACK_EXPANSION_FORCE_EXTRA_ARGS_P(NODE) \
   TREE_LANG_FLAG_3 (PACK_EXPANSION_CHECK (NODE))
 
-/* True iff the wildcard can match a template parameter pack.  */
-#define WILDCARD_PACK_P(NODE) TREE_LANG_FLAG_0 (NODE)
-
 /* Determine if this is an argument pack.  */
 #define ARGUMENT_PACK_P(NODE)                          \
   (TREE_CODE (NODE) == TYPE_ARGUMENT_PACK              \
@@ -7532,9 +7528,6 @@ extern tree do_auto_deduction                   (tree, 
tree, tree,
                                                 int = LOOKUP_NORMAL,
                                                 tree = NULL_TREE);
 extern tree type_uses_auto                     (tree);
-extern tree type_uses_auto_or_concept          (tree);
-extern void append_type_to_template_for_access_check (tree, tree, tree,
-                                                     location_t);
 extern tree convert_generic_types_to_packs     (tree, int, int);
 extern tree splice_late_return_type            (tree, tree);
 extern bool is_auto                            (const_tree);
@@ -8598,15 +8591,9 @@ extern tree build_type_constraint                (tree, 
tree, tsubst_flags_t);
 extern tree build_concept_check                 (tree, tree, tsubst_flags_t);
 extern tree build_concept_check                 (tree, tree, tree, 
tsubst_flags_t);
 
-extern tree_pair finish_type_constraints       (tree, tree, tsubst_flags_t);
 extern tree build_constrained_parameter         (tree, tree, tree = NULL_TREE);
-extern void placeholder_extract_concept_and_args (tree, tree&, tree&);
 extern bool equivalent_placeholder_constraints  (tree, tree);
 extern hashval_t iterative_hash_placeholder_constraint (tree, hashval_t);
-extern bool deduce_constrained_parameter        (tree, tree&, tree&);
-extern tree resolve_constraint_check            (tree);
-extern bool valid_requirements_p                (tree);
-extern tree finish_concept_name                 (tree);
 extern tree finish_shorthand_constraint         (tree, tree);
 extern tree finish_requires_expr                (location_t, tree, tree);
 extern tree finish_simple_requirement           (location_t, tree);
@@ -8890,18 +8877,10 @@ variable_template_p (tree t)
 
 /* True iff T is a concept.  */
 
-inline bool
-concept_definition_p (tree t)
-{
-  return TREE_CODE (STRIP_TEMPLATE (t)) == CONCEPT_DECL;
-}
-
-/* Same as above, but for const trees.  */
-
 inline bool
 concept_definition_p (const_tree t)
 {
-  return concept_definition_p (const_cast<tree> (t));
+  return TREE_CODE (STRIP_TEMPLATE (t)) == CONCEPT_DECL;
 }
 
 /* True if t is an expression that checks a concept.  */
@@ -8914,6 +8893,19 @@ concept_check_p (const_tree t)
   return false;
 }
 
+/* Return the prototype parameter of the concept T,
+   i.e. its first declared template parameter.  */
+
+inline tree
+concept_prototype_parameter (const_tree t)
+{
+  gcc_checking_assert (concept_definition_p (t));
+  if (TREE_CODE (t) == CONCEPT_DECL)
+    t = DECL_TI_TEMPLATE (t);
+  tree parms = DECL_INNERMOST_TEMPLATE_PARMS (t);
+  return TREE_VALUE (TREE_VEC_ELT (parms, 0));
+}
+
 /* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference.  */
 
 inline bool
diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
index f4203123737..f42f6aeddbe 100644
--- a/gcc/cp/cxx-pretty-print.cc
+++ b/gcc/cp/cxx-pretty-print.cc
@@ -2336,8 +2336,8 @@ pp_cxx_constrained_type_spec (cxx_pretty_printer *pp, 
tree c)
       pp_cxx_ws_string(pp, "<unsatisfied-type-constraint>");
       return;
     }
-  tree t, a;
-  placeholder_extract_concept_and_args (c, t, a);
+  tree t = TREE_OPERAND (c, 0);
+  tree a = TREE_OPERAND (c, 1);
   pp->id_expression (t);
   pp_cxx_begin_template_argument_list (pp);
   pp_cxx_ws_string (pp, "<placeholder>");
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 7ef79b90868..193b560feca 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1536,10 +1536,6 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)
       dump_simple_decl (pp, t, TREE_TYPE (t), flags);
       break;
 
-    case WILDCARD_DECL:
-      pp_string (pp, "<wildcard>");
-      break;
-
     case TEMPLATE_ID_EXPR:
       {
        tree name = TREE_OPERAND (t, 0);
@@ -2339,7 +2335,6 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
     case TEMPLATE_DECL:
     case NAMESPACE_DECL:
     case LABEL_DECL:
-    case WILDCARD_DECL:
     case OVERLOAD:
     case TYPE_DECL:
     case USING_DECL:
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 07b12224615..cede9ddae5a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -18607,29 +18607,10 @@ get_unqualified_id (cp_declarator *declarator)
     return NULL_TREE;
 }
 
-/* Returns true if TYPE would declare a constrained constrained-parameter.  */
-
-static inline bool
-is_constrained_parameter (tree type)
-{
-  return (type
-          && TREE_CODE (type) == TYPE_DECL
-          && CONSTRAINED_PARM_CONCEPT (type)
-          && DECL_P (CONSTRAINED_PARM_CONCEPT (type)));
-}
-
-/* Returns true if PARM declares a constrained-parameter. */
-
-static inline bool
-is_constrained_parameter (cp_parameter_declarator *parm)
-{
-  return is_constrained_parameter (parm->decl_specifiers.type);
-}
-
 /* Check that the type parameter is only a declarator-id, and that its
    type is not cv-qualified. */
 
-bool
+static bool
 cp_parser_check_constrained_type_parm (cp_parser *parser,
                                       cp_parameter_declarator *parm)
 {
@@ -18667,36 +18648,6 @@ cp_parser_constrained_type_template_parm (cp_parser 
*parser,
     return error_mark_node;
 }
 
-static tree
-finish_constrained_template_template_parm (tree proto, tree id)
-{
-  /* FIXME: This should probably be copied, and we may need to adjust
-     the template parameter depths.  */
-  tree saved_parms = current_template_parms;
-  begin_template_parm_list ();
-  current_template_parms = DECL_TEMPLATE_PARMS (proto);
-  end_template_parm_list ();
-
-  tree parm = finish_template_template_parm (class_type_node, id);
-  current_template_parms = saved_parms;
-
-  return parm;
-}
-
-/* Finish parsing/processing a template template parameter by borrowing
-   the template parameter list from the prototype parameter.  */
-
-static tree
-cp_parser_constrained_template_template_parm (cp_parser *parser,
-                                              tree proto,
-                                              tree id,
-                                              cp_parameter_declarator 
*parmdecl)
-{
-  if (!cp_parser_check_constrained_type_parm (parser, parmdecl))
-    return error_mark_node;
-  return finish_constrained_template_template_parm (proto, id);
-}
-
 /* Create a new non-type template parameter from the given PARM
    declarator.  */
 
@@ -18730,9 +18681,6 @@ finish_constrained_parameter (cp_parser *parser,
   tree parm;
   if (TREE_CODE (proto) == TYPE_DECL)
     parm = cp_parser_constrained_type_template_parm (parser, id, parmdecl);
-  else if (TREE_CODE (proto) == TEMPLATE_DECL)
-    parm = cp_parser_constrained_template_template_parm (parser, proto, id,
-                                                        parmdecl);
   else
     parm = cp_parser_constrained_non_type_template_parm (is_non_type, 
parmdecl);
   if (parm == error_mark_node)
@@ -18746,24 +18694,26 @@ finish_constrained_parameter (cp_parser *parser,
   return parm;
 }
 
-/* Returns true if the parsed type actually represents the declaration
-   of a type template-parameter.  */
+/* Returns true if the TYPE would declare a constrained type
+   template-parameter.  */
 
 static bool
 declares_constrained_type_template_parameter (tree type)
 {
-  return (is_constrained_parameter (type)
+  return (type
+         && TREE_CODE (type) == TYPE_DECL
+         && CONSTRAINED_PARM_CONCEPT (type)
+         && DECL_P (CONSTRAINED_PARM_CONCEPT (type))
          && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TYPE_PARM);
 }
 
-/* Returns true if the parsed type actually represents the declaration of
-   a template template-parameter.  */
+/* Returns true if PARM declares a constrained type template-parameter.  */
 
 static bool
-declares_constrained_template_template_parameter (tree type)
+declares_constrained_type_template_parameter (cp_parameter_declarator *parm)
 {
-  return (is_constrained_parameter (type)
-         && TREE_CODE (TREE_TYPE (type)) == TEMPLATE_TEMPLATE_PARM);
+  tree type = parm->decl_specifiers.type;
+  return declares_constrained_type_template_parameter (type);
 }
 
 /* Parse a default argument for a type template-parameter.
@@ -18936,7 +18886,7 @@ cp_parser_template_parameter (cp_parser* parser, bool 
*is_non_type,
     }
 
   /* The parameter may have been constrained type parameter.  */
-  if (is_constrained_parameter (parameter_declarator))
+  if (declares_constrained_type_template_parameter (parameter_declarator))
     return finish_constrained_parameter (parser,
                                          parameter_declarator,
                                          is_non_type);
@@ -21019,13 +20969,26 @@ cp_parser_placeholder_type_specifier (cp_parser 
*parser, location_t loc,
     /* A concept-name with no arguments can't be an expression.  */
     tentative = false;
 
+  tree con = DECL_TEMPLATE_RESULT (tmpl);
+  tree proto = concept_prototype_parameter (con);
   tsubst_flags_t complain = tentative ? tf_none : tf_warning_or_error;
 
+  /* A type constraint constrains a contextually determined type or type
+     parameter pack.  */
+  if (TREE_CODE (proto) != TYPE_DECL)
+    {
+      if (!tentative)
+       {
+         auto_diagnostic_group d;
+         error_at (loc, "%qE does not constrain a type", DECL_NAME (con));
+         inform (DECL_SOURCE_LOCATION (con), "concept defined here");
+       }
+      return error_mark_node;
+    }
+
   /* Get the concept and prototype parameter for the constraint.  */
-  tree_pair info = finish_type_constraints (tmpl, args, complain);
-  tree con = info.first;
-  tree proto = info.second;
-  if (con == error_mark_node)
+  tree check = build_type_constraint (tmpl, args, complain);
+  if (check == error_mark_node)
     return error_mark_node;
 
   /* As per the standard, require auto or decltype(auto).  */
@@ -21041,19 +21004,6 @@ cp_parser_placeholder_type_specifier (cp_parser 
*parser, location_t loc,
       close_paren = parens.require_close (parser);
     }
 
-  /* A type constraint constrains a contextually determined type or type
-     parameter pack.  */
-  if (TREE_CODE (proto) != TYPE_DECL)
-    {
-      if (!tentative)
-       {
-         auto_diagnostic_group d;
-         error_at (loc, "%qE does not constrain a type", DECL_NAME (con));
-         inform (DECL_SOURCE_LOCATION (con), "concept defined here");
-       }
-      return error_mark_node;
-    }
-
   /* In a template parameter list, a type-parameter can be introduced
      by type-constraints alone.  */
   if (processing_template_parmlist && !placeholder)
@@ -26165,12 +26115,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
         default_argument
           = cp_parser_default_type_template_argument (parser);
 
-      /* A constrained-type-specifier may declare a
-        template-template-parameter.  */
-      else if (declares_constrained_template_template_parameter (type))
-        default_argument
-          = cp_parser_default_template_template_argument (parser);
-
       /* Outside of a class definition, we can just parse the
         assignment-expression.  */
       else
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 35ec7eba0ba..5ec498fb225 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8541,16 +8541,6 @@ is_compatible_template_arg (tree parm, tree arg, tree 
args)
   return ttp_subsumes (parm_cons, arg);
 }
 
-// Convert a placeholder argument into a binding to the original
-// parameter. The original parameter is saved as the TREE_TYPE of
-// ARG.
-static inline tree
-convert_wildcard_argument (tree parm, tree arg)
-{
-  TREE_TYPE (arg) = parm;
-  return arg;
-}
-
 /* We can't fully resolve ARG given as a non-type template argument to TYPE,
    because one of them is dependent.  But we need to represent the
    conversion for the benefit of cp_tree_equal.  */
@@ -8605,10 +8595,6 @@ convert_template_argument (tree parm,
   if (parm == error_mark_node || error_operand_p (arg))
     return error_mark_node;
 
-  /* Trivially convert placeholders. */
-  if (TREE_CODE (arg) == WILDCARD_DECL)
-    return convert_wildcard_argument (parm, arg);
-
   if (arg == any_targ_node)
     return arg;
 
@@ -8990,16 +8976,6 @@ coerce_template_parameter_pack (tree parms,
 
       packed_args = make_tree_vec (TREE_VEC_LENGTH (packed_parms));
     }
-  /* Check if we have a placeholder pack, which indicates we're
-     in the context of a introduction list.  In that case we want
-     to match this pack to the single placeholder.  */
-  else if (arg_idx < nargs
-           && TREE_CODE (TREE_VEC_ELT (inner_args, arg_idx)) == WILDCARD_DECL
-           && WILDCARD_PACK_P (TREE_VEC_ELT (inner_args, arg_idx)))
-    {
-      nargs = arg_idx + 1;
-      packed_args = make_tree_vec (1);
-    }
   else
     packed_args = make_tree_vec (nargs - arg_idx);
 
@@ -16494,13 +16470,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
              {
                int quals;
 
-               /* When building concept checks for the purpose of
-                  deducing placeholders, we can end up with wildcards
-                  where types are expected. Adjust this to the deduced
-                  value.  */
-               if (TREE_CODE (arg) == WILDCARD_DECL)
-                 arg = TREE_TYPE (TREE_TYPE (arg));
-
                gcc_assert (TYPE_P (arg));
 
                quals = cp_type_quals (arg) | cp_type_quals (t);
@@ -28589,8 +28558,7 @@ type_dependent_expression_p (tree expression)
 
   /* An unresolved name is always dependent.  */
   if (identifier_p (expression)
-      || TREE_CODE (expression) == USING_DECL
-      || TREE_CODE (expression) == WILDCARD_DECL)
+      || TREE_CODE (expression) == USING_DECL)
     return true;
 
   /* A lambda-expression in template context is dependent.  dependent_type_p is
@@ -29588,11 +29556,8 @@ make_constrained_placeholder_type (tree type, tree 
con, tree args)
 {
   /* Build the constraint. */
   tree tmpl = DECL_TI_TEMPLATE (con);
-  tree expr = tmpl;
-  if (TREE_CODE (con) == FUNCTION_DECL)
-    expr = ovl_make (tmpl);
   ++processing_template_decl;
-  expr = build_concept_check (expr, type, args, tf_warning_or_error);
+  tree expr = build_concept_check (tmpl, type, args, tf_warning_or_error);
   --processing_template_decl;
 
   PLACEHOLDER_TYPE_CONSTRAINTS_INFO (type)
@@ -29637,8 +29602,7 @@ placeholder_type_constraint_dependent_p (tree t)
       args = expand_template_argument_pack (args);
       first = TREE_VEC_ELT (args, 0);
     }
-  gcc_checking_assert (TREE_CODE (first) == WILDCARD_DECL
-                      || is_auto (first));
+  gcc_checking_assert (is_auto (first));
   for (int i = 1; i < TREE_VEC_LENGTH (args); ++i)
     if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
       return true;
-- 
2.47.1.313.gcc01bad4a9

Reply via email to