On Fri, 2 Aug 2024, Marek Polacek wrote:

> Bootstrapped/regtested on x86_64-pc-linux-gnu.  Comments?
> 
> -- >8 --
> This patch removes vestigial Concepts TS code as discussed in
> <https://gcc.gnu.org/pipermail/gcc-patches/2024-July/657937.html>.

Yay!  FWIW I think we can also remove the concept_check_p checks in

    cxx_eval_call_expression
    cxx_eval_outermost_constant_expr
    cp_genericize_r <case CALL_EXPR>
    check_noexcept_r

And perhaps we could rename *concept_check* to *concept_id* throughout
to match the standard terminology.

> 
> In particular, it removes code related to function/variable concepts.
> That includes variable_concept_p and function_concept_p, which then
> cascades into removing DECL_DECLARED_CONCEPT_P etc.  So I think we
> no longer need to say "standard concept" since there are no non-standard
> ones anymore.
> 
> I've added two new errors saying that "variable/function concepts are
> no longer supported".
> 
> gcc/cp/ChangeLog:
> 
>       * constexpr.cc (cxx_eval_constant_expression): Don't call
>       unpack_concept_check.  Add a concept_check_p assert.  Remove
>       function_concept_p code.
>       * constraint.cc (check_constraint_atom): Remove function concepts code.
>       (unpack_concept_check): Remove.
>       (get_concept_check_template): Remove Concepts TS code.
>       (resolve_function_concept_overload): Remove.
>       (resolve_function_concept_check): Remove.
>       (resolve_concept_check): Remove Concepts TS code.
>       (get_returned_expression): Remove.
>       (get_variable_initializer): Remove.
>       (get_concept_definition): Remove Concepts TS code.
>       (normalize_concept_check): Likewise.
>       (build_function_check): Remove.
>       (build_variable_check): Remove.
>       (build_standard_check): Use concept_definition_p instead of
>       standard_concept_p.
>       (build_concept_check): Remove variable_concept_p/function_concept_p
>       code.
>       (build_concept_id): Simplify.
>       (build_type_constraint): Likewise.
>       (placeholder_extract_concept_and_args): Likewise.
>       (satisfy_nondeclaration_constraints): Likewise.
>       (check_function_concept): Remove.
>       (get_constraint_error_location): Remove Concepts TS code.
>       * cp-tree.h (DECL_DECLARED_CONCEPT_P): Remove.
>       (check_function_concept): Remove.
>       (unpack_concept_check): Remove.
>       (standard_concept_p): Remove.
>       (variable_concept_p): Remove.
>       (function_concept_p): Remove.
>       (concept_definition_p): Simplify.
>       (concept_check_p): Don't check for CALL_EXPR.
>       * decl.cc (check_concept_refinement): Remove.
>       (duplicate_decls): Remove check_concept_refinement code.
>       (is_concept_var): Remove.
>       (cp_finish_decl): Remove is_concept_var.
>       (check_concept_fn): Remove.
>       (grokfndecl): Give an error about function concepts not being supported
>       anymore.  Remove unused code.
>       (grokvardecl): Give an error about variable concepts not being
>       supported anymore.
>       (finish_function): Remove DECL_DECLARED_CONCEPT_P code.
>       * decl2.cc (min_vis_expr_r): Use concept_definition_p instead of
>       standard_concept_p.
>       (maybe_instantiate_decl): Remove DECL_DECLARED_CONCEPT_P check.
>       (mark_used): Likewise.
>       * error.cc (dump_simple_decl): Use concept_definition_p instead of
>       standard_concept_p.
>       (dump_function_decl): Remove DECL_DECLARED_CONCEPT_P code.
>       (print_concept_check_info): Don't call unpack_concept_check.
>       * mangle.cc (write_type_constraint): Likewise.
>       * parser.cc (cp_parser_nested_name_specifier_opt): Remove
>       function_concept_p code.  Only check concept_definition_p, not
>       variable_concept_p/standard_concept_p.
>       (add_debug_begin_stmt): Remove DECL_DECLARED_CONCEPT_P code.
>       (cp_parser_template_declaration_after_parameters): Remove a stale
>       comment.
>       * pt.cc (check_explicit_specialization): Remove
>       DECL_DECLARED_CONCEPT_P code.
>       (process_partial_specialization): Remove variable_concept_p code.
>       (lookup_template_variable): Likewise.
>       (tsubst_expr) <case CALL_EXPR>: Remove Concepts TS code and simplify.
>       (do_decl_instantiation): Remove DECL_DECLARED_CONCEPT_P code.
>       (instantiate_decl): Likewise.
>       (placeholder_type_constraint_dependent_p): Don't call
>       unpack_concept_check.  Add a concept_check_p assert.
>       (convert_generic_types_to_packs): Likewise.
>       * semantics.cc (finish_call_expr): Remove Concepts TS code and simplify.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/concepts/decl-diagnose.C: Adjust dg-error.
>       * g++.dg/concepts/fn-concept2.C: Likewise.
>       * g++.dg/concepts/pr71128.C: Likewise.
>       * g++.dg/concepts/var-concept6.C: Likewise.
>       * g++.dg/cpp2a/concepts.C: Likewise.
> ---
>  gcc/cp/constexpr.cc                           |  13 +-
>  gcc/cp/constraint.cc                          | 346 +-----------------
>  gcc/cp/cp-tree.h                              |  71 +---
>  gcc/cp/decl.cc                                | 118 +-----
>  gcc/cp/decl2.cc                               |   4 +-
>  gcc/cp/error.cc                               |  10 +-
>  gcc/cp/mangle.cc                              |   4 +-
>  gcc/cp/parser.cc                              |  16 +-
>  gcc/cp/pt.cc                                  |  60 +--
>  gcc/cp/semantics.cc                           |  17 +-
>  gcc/testsuite/g++.dg/concepts/decl-diagnose.C |   8 +-
>  gcc/testsuite/g++.dg/concepts/fn-concept2.C   |   4 +-
>  gcc/testsuite/g++.dg/concepts/pr71128.C       |   8 +-
>  gcc/testsuite/g++.dg/concepts/var-concept6.C  |   2 +-
>  gcc/testsuite/g++.dg/cpp2a/concepts.C         |   4 +-
>  15 files changed, 65 insertions(+), 620 deletions(-)
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 8277b3b79ba..b079be1b3d5 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -8508,20 +8508,11 @@ cxx_eval_constant_expression (const constexpr_ctx 
> *ctx, tree t,
>        {
>          /* We can evaluate template-id that refers to a concept only if
>          the template arguments are non-dependent.  */
> -     tree id = unpack_concept_check (t);
> -     tree tmpl = TREE_OPERAND (id, 0);
> +     gcc_assert (concept_check_p (t));
> +     tree tmpl = TREE_OPERAND (t, 0);
>       if (!concept_definition_p (tmpl))
>         internal_error ("unexpected template-id %qE", t);
>  
> -     if (function_concept_p (tmpl))
> -       {
> -         if (!ctx->quiet)
> -           error_at (cp_expr_loc_or_input_loc (t),
> -                     "function concept must be called");
> -         r = error_mark_node;
> -         break;
> -       }
> -
>       if (!value_dependent_expression_p (t)
>           && !uid_sensitive_constexpr_evaluation_p ())
>         r = evaluate_concept_check (t);
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 853ea8c4b93..2da482cc93d 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -167,19 +167,6 @@ check_constraint_atom (cp_expr expr)
>        return false;
>      }
>  
> -  /* Check that we're using function concepts correctly.  */
> -  if (concept_check_p (expr))
> -    {
> -      tree id = unpack_concept_check (expr);
> -      tree tmpl = TREE_OPERAND (id, 0);
> -      if (OVL_P (tmpl) && TREE_CODE (expr) == TEMPLATE_ID_EXPR)
> -        {
> -       error_at (EXPR_LOC_OR_LOC (expr, input_location),
> -                 "function concept must be called");
> -       return false;
> -     }
> -    }
> -
>    return true;
>  }
>  
> @@ -245,32 +232,13 @@ combine_constraint_expressions (tree lhs, tree rhs)
>    return finish_constraint_and_expr (UNKNOWN_LOCATION, lhs, rhs);
>  }
>  
> -/* Extract the template-id from a concept check.  For standard and variable
> -   checks, this is simply T.  For function concept checks, this is the
> -   called function.  */
> -
> -tree
> -unpack_concept_check (tree t)
> -{
> -  gcc_assert (concept_check_p (t));
> -
> -  if (TREE_CODE (t) == CALL_EXPR)
> -    t = CALL_EXPR_FN (t);
> -
> -  gcc_assert (TREE_CODE (t) == TEMPLATE_ID_EXPR);
> -  return t;
> -}
> -
>  /* Extract the TEMPLATE_DECL from a concept check.  */
>  
>  tree
>  get_concept_check_template (tree t)
>  {
> -  tree id = unpack_concept_check (t);
> -  tree tmpl = TREE_OPERAND (id, 0);
> -  if (OVL_P (tmpl))
> -    tmpl = OVL_FIRST (tmpl);
> -  return tmpl;
> +  gcc_assert (concept_check_p (t));
> +  return TREE_OPERAND (t, 0);
>  }
>  
>  /*---------------------------------------------------------------------------
> @@ -285,101 +253,6 @@ get_concept_check_template (tree t)
>     matched declaration, and whose purpose contains the coerced template
>     arguments that can be substituted into the call.  */
>  
> -/* Given an overload set OVL, try to find a unique definition that can be
> -   instantiated by the template arguments ARGS.
> -
> -   This function is not called for arbitrary call expressions.  In 
> particular,
> -   the call expression must be written with explicit template arguments
> -   and no function arguments.  For example:
> -
> -        f<T, U>()
> -
> -   If a single match is found, this returns a TREE_LIST whose VALUE
> -   is the constraint function (not the template), and its PURPOSE is
> -   the complete set of arguments substituted into the parameter list.  */
> -
> -static tree
> -resolve_function_concept_overload (tree ovl, tree args)
> -{
> -  int nerrs = 0;
> -  tree cands = NULL_TREE;
> -  for (lkp_iterator iter (ovl); iter; ++iter)
> -    {
> -      tree tmpl = *iter;
> -      if (TREE_CODE (tmpl) != TEMPLATE_DECL)
> -        continue;
> -
> -      /* Don't try to deduce checks for non-concepts.  We often end up trying
> -         to resolve constraints in functional casts as part of a
> -      postfix-expression.  We can save time and headaches by not
> -         instantiating those declarations.
> -
> -         NOTE: This masks a potential error, caused by instantiating
> -      non-deduced contexts using placeholder arguments.  */
> -      tree fn = DECL_TEMPLATE_RESULT (tmpl);
> -      if (DECL_ARGUMENTS (fn))
> -        continue;
> -      if (!DECL_DECLARED_CONCEPT_P (fn))
> -        continue;
> -
> -      /* Remember the candidate if we can deduce a substitution.  */
> -      ++processing_template_decl;
> -      tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (tmpl));
> -      if (tree subst = coerce_template_parms (parms, args, tmpl, tf_none))
> -        {
> -          if (subst == error_mark_node)
> -            ++nerrs;
> -          else
> -         cands = tree_cons (subst, fn, cands);
> -        }
> -      --processing_template_decl;
> -    }
> -
> -  if (!cands)
> -    /* We either had no candidates or failed deductions.  */
> -    return nerrs ? error_mark_node : NULL_TREE;
> -  else if (TREE_CHAIN (cands))
> -    /* There are multiple candidates.  */
> -    return error_mark_node;
> -
> -  return cands;
> -}
> -
> -/* Determine if the call expression CALL is a constraint check, and
> -   return the concept declaration and arguments being checked.  If CALL
> -   does not denote a constraint check, return NULL.  */
> -
> -tree
> -resolve_function_concept_check (tree call)
> -{
> -  gcc_assert (TREE_CODE (call) == CALL_EXPR);
> -
> -  /* A constraint check must be only a template-id expression.
> -     If it's a call to a base-link, its function(s) should be a
> -     template-id expression.  If this is not a template-id, then
> -     it cannot be a concept-check.  */
> -  tree target = CALL_EXPR_FN (call);
> -  if (BASELINK_P (target))
> -    target = BASELINK_FUNCTIONS (target);
> -  if (TREE_CODE (target) != TEMPLATE_ID_EXPR)
> -    return NULL_TREE;
> -
> -  /* Get the overload set and template arguments and try to
> -     resolve the target.  */
> -  tree ovl = TREE_OPERAND (target, 0);
> -
> -  /* This is a function call of a variable concept... ill-formed.  */
> -  if (TREE_CODE (ovl) == TEMPLATE_DECL)
> -    {
> -      error_at (location_of (call),
> -             "function call of variable concept %qE", call);
> -      return error_mark_node;
> -    }
> -
> -  tree args = TREE_OPERAND (target, 1);
> -  return resolve_function_concept_overload (ovl, args);
> -}
> -
>  /* 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
> @@ -390,20 +263,8 @@ tree
>  resolve_concept_check (tree check)
>  {
>    gcc_assert (concept_check_p (check));
> -  tree id = unpack_concept_check (check);
> -  tree tmpl = TREE_OPERAND (id, 0);
> -
> -  /* If this is an overloaded function concept, perform overload
> -     resolution (this only happens when deducing prototype parameters
> -     and template introductions).  */
> -  if (TREE_CODE (tmpl) == OVERLOAD)
> -    {
> -      if (OVL_CHAIN (tmpl))
> -     return resolve_function_concept_check (check);
> -      tmpl = OVL_FIRST (tmpl);
> -    }
> -
> -  tree args = TREE_OPERAND (id, 1);
> +  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);
> @@ -466,55 +327,13 @@ finish_type_constraints (tree spec, tree args, 
> tsubst_flags_t complain)
>                         Expansion of concept definitions
>  ---------------------------------------------------------------------------*/
>  
> -/* Returns the expression of a function concept.  */
> -
> -static tree
> -get_returned_expression (tree fn)
> -{
> -  /* Extract the body of the function minus the return expression.  */
> -  tree body = DECL_SAVED_TREE (fn);
> -  if (!body)
> -    return error_mark_node;
> -  if (TREE_CODE (body) == BIND_EXPR)
> -    body = BIND_EXPR_BODY (body);
> -  if (TREE_CODE (body) != RETURN_EXPR)
> -    return error_mark_node;
> -
> -  return TREE_OPERAND (body, 0);
> -}
> -
> -/* Returns the initializer of a variable concept.  */
> -
> -static tree
> -get_variable_initializer (tree var)
> -{
> -  tree init = DECL_INITIAL (var);
> -  if (!init)
> -    return error_mark_node;
> -  if (BRACE_ENCLOSED_INITIALIZER_P (init)
> -      && CONSTRUCTOR_NELTS (init) == 1)
> -    init = CONSTRUCTOR_ELT (init, 0)->value;
> -  return init;
> -}
> -
> -/* Returns the definition of a variable or function concept.  */
> +/* Returns the definition of a concept.  */
>  
>  static tree
>  get_concept_definition (tree decl)
>  {
> -  if (TREE_CODE (decl) == OVERLOAD)
> -    decl = OVL_FIRST (decl);
> -
> -  if (TREE_CODE (decl) == TEMPLATE_DECL)
> -    decl = DECL_TEMPLATE_RESULT (decl);
> -
> -  if (TREE_CODE (decl) == CONCEPT_DECL)
> -    return DECL_INITIAL (decl);
> -  if (VAR_P (decl))
> -    return get_variable_initializer (decl);
> -  if (TREE_CODE (decl) == FUNCTION_DECL)
> -    return get_returned_expression (decl);
> -  gcc_unreachable ();
> +  gcc_assert (TREE_CODE (decl) == CONCEPT_DECL);
> +  return DECL_INITIAL (decl);
>  }
>  
>  /*---------------------------------------------------------------------------
> @@ -729,19 +548,9 @@ static GTY((deletable)) hash_table<norm_hasher> 
> *norm_cache;
>  static tree
>  normalize_concept_check (tree check, tree args, norm_info info)
>  {
> -  tree id = unpack_concept_check (check);
> -  tree tmpl = TREE_OPERAND (id, 0);
> -  tree targs = TREE_OPERAND (id, 1);
> -
> -  /* A function concept is wrapped in an overload.  */
> -  if (TREE_CODE (tmpl) == OVERLOAD)
> -    {
> -      /* TODO: Can we diagnose this error during parsing?  */
> -      if (TREE_CODE (check) == TEMPLATE_ID_EXPR)
> -     error_at (EXPR_LOC_OR_LOC (check, input_location),
> -               "function concept must be called");
> -      tmpl = OVL_FIRST (tmpl);
> -    }
> +  gcc_assert (concept_check_p (check));
> +  tree tmpl = TREE_OPERAND (check, 0);
> +  tree targs = TREE_OPERAND (check, 1);
>  
>    /* Substitute through the arguments of the concept check.  */
>    if (args)
> @@ -789,11 +598,7 @@ normalize_concept_check (tree check, tree args, 
> norm_info info)
>  
>  static GTY((deletable)) hash_table<atom_hasher> *atom_cache;
>  
> -/* The normal form of an atom depends on the expression.  The normal
> -   form of a function call to a function concept is a check constraint
> -   for that concept.  The normal form of a reference to a variable
> -   concept is a check constraint for that concept.  Otherwise, the
> -   constraint is a predicate constraint.  */
> +/* The normal form of an atom is a predicate constraint.  */
>  
>  static tree
>  normalize_atom (tree t, tree args, norm_info info)
> @@ -1378,77 +1183,13 @@ build_concept_check_arguments (tree arg, tree rest)
>    return args;
>  }
>  
> -/* Builds an id-expression of the form `C<Args...>()` where C is a function
> -   concept.  */
> -
> -static tree
> -build_function_check (tree tmpl, tree args, tsubst_flags_t /*complain*/)
> -{
> -  if (TREE_CODE (tmpl) == TEMPLATE_DECL)
> -    {
> -      /* If we just got a template, wrap it in an overload so it looks like 
> any
> -      other template-id.  */
> -      tmpl = ovl_make (tmpl);
> -      TREE_TYPE (tmpl) = boolean_type_node;
> -    }
> -
> -  /* Perform function concept resolution now so we always have a single
> -     function of the overload set (even if we started with only one; the
> -     resolution function converts template arguments).  Note that we still
> -     wrap this in an overload set so we don't upset other parts of the
> -     compiler that expect template-ids referring to function concepts
> -     to have an overload set.  */
> -  tree info = resolve_function_concept_overload (tmpl, args);
> -  if (info == error_mark_node)
> -    return error_mark_node;
> -  if (!info)
> -    {
> -      error ("no matching concepts for %qE", tmpl);
> -      return error_mark_node;
> -    }
> -  args = TREE_PURPOSE (info);
> -  tmpl = DECL_TI_TEMPLATE (TREE_VALUE (info));
> -
> -  /* Rebuild the singleton overload set; mark the type bool.  */
> -  tmpl = ovl_make (tmpl, NULL_TREE);
> -  TREE_TYPE (tmpl) = boolean_type_node;
> -
> -  /* Build the id-expression around the overload set.  */
> -  tree id = build2 (TEMPLATE_ID_EXPR, boolean_type_node, tmpl, args);
> -
> -  /* Finally, build the call expression around the overload.  */
> -  ++processing_template_decl;
> -  vec<tree, va_gc> *fargs = make_tree_vector ();
> -  tree call = build_min_nt_call_vec (id, fargs);
> -  TREE_TYPE (call) = boolean_type_node;
> -  release_tree_vector (fargs);
> -  --processing_template_decl;
> -
> -  return call;
> -}
> -
> -/* Builds an id-expression of the form `C<Args...>` where C is a variable
> -   concept.  */
> -
> -static tree
> -build_variable_check (tree tmpl, tree args, tsubst_flags_t complain)
> -{
> -  gcc_assert (variable_concept_p (tmpl));
> -  gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL);
> -  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);
> -}
> -
>  /* 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 (standard_concept_p (tmpl));
> +  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);
> @@ -1475,12 +1216,8 @@ build_concept_check (tree decl, tree arg, tree rest, 
> tsubst_flags_t complain)
>  {
>    tree args = build_concept_check_arguments (arg, rest);
>  
> -  if (standard_concept_p (decl))
> +  if (concept_definition_p (decl))
>      return build_standard_check (decl, args, complain);
> -  if (variable_concept_p (decl))
> -    return build_variable_check (decl, args, complain);
> -  if (function_concept_p (decl))
> -    return build_function_check (decl, args, complain);
>  
>    return error_mark_node;
>  }
> @@ -1490,10 +1227,7 @@ build_concept_check (tree decl, tree arg, tree rest, 
> tsubst_flags_t complain)
>  static tree
>  build_concept_id (tree decl, tree args)
>  {
> -  tree check = build_concept_check (decl, args, tf_warning_or_error);
> -  if (check == error_mark_node)
> -    return error_mark_node;
> -  return unpack_concept_check (check);
> +  return build_concept_check (decl, args, tf_warning_or_error);
>  }
>  
>  /* Build a template-id that can participate in a concept check, preserving
> @@ -1521,9 +1255,7 @@ build_type_constraint (tree decl, tree args, 
> tsubst_flags_t complain)
>    ++processing_template_decl;
>    tree check = build_concept_check (decl, wildcard, args, complain);
>    --processing_template_decl;
> -  if (check == error_mark_node)
> -    return error_mark_node;
> -  return unpack_concept_check (check);
> +  return check;
>  }
>  
>  /* Returns a TYPE_DECL that contains sufficient information to
> @@ -1621,10 +1353,7 @@ placeholder_extract_concept_and_args (tree t, tree 
> &tmpl, tree &args)
>  {
>    if (concept_check_p (t))
>      {
> -      t = unpack_concept_check (t);
>        tmpl = TREE_OPERAND (t, 0);
> -      if (TREE_CODE (tmpl) == OVERLOAD)
> -        tmpl = OVL_FIRST (tmpl);
>        args = TREE_OPERAND (t, 1);
>        return;
>      }
> @@ -2938,9 +2667,8 @@ satisfy_nondeclaration_constraints (tree t, tree args, 
> sat_info info)
>    if (concept_check_p (t))
>      {
>        gcc_assert (!args);
> -      tree id = unpack_concept_check (t);
> -      args = TREE_OPERAND (id, 1);
> -      tree tmpl = get_concept_check_template (id);
> +      args = TREE_OPERAND (t, 1);
> +      tree tmpl = get_concept_check_template (t);
>        norm = normalize_concept_definition (tmpl, info.noisy ());
>      }
>    else if (TREE_CODE (t) == NESTED_REQ)
> @@ -3255,41 +2983,6 @@ finish_nested_requirement (location_t loc, tree expr)
>    return r;
>  }
>  
> -/* Check that FN satisfies the structural requirements of a
> -   function concept definition.  */
> -tree
> -check_function_concept (tree fn)
> -{
> -  /* Check that the function is comprised of only a return statement.  */
> -  tree body = DECL_SAVED_TREE (fn);
> -  if (TREE_CODE (body) == BIND_EXPR)
> -    body = BIND_EXPR_BODY (body);
> -
> -  /* Sometimes a function call results in the creation of clean up
> -     points.  Allow these to be preserved in the body of the
> -     constraint, as we might actually need them for some constexpr
> -     evaluations.  */
> -  if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
> -    body = TREE_OPERAND (body, 0);
> -
> -  /* Check that the definition is written correctly.  */
> -  if (TREE_CODE (body) != RETURN_EXPR)
> -    {
> -      location_t loc = DECL_SOURCE_LOCATION (fn);
> -      if (TREE_CODE (body) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (body))
> -     {
> -       if (seen_error ())
> -         /* The definition was probably erroneous, not empty.  */;
> -       else
> -         error_at (loc, "definition of concept %qD is empty", fn);
> -     }
> -      else
> -        error_at (loc, "definition of concept %qD has multiple statements", 
> fn);
> -    }
> -
> -  return NULL_TREE;
> -}
> -
>  /*---------------------------------------------------------------------------
>                          Equivalence of constraints
>  ---------------------------------------------------------------------------*/
> @@ -3403,10 +3096,7 @@ get_constraint_error_location (tree t)
>    /* Otherwise, give the location as the defining concept.  */
>    else if (concept_check_p (src))
>      {
> -      tree id = unpack_concept_check (src);
> -      tree tmpl = TREE_OPERAND (id, 0);
> -      if (OVL_P (tmpl))
> -     tmpl = OVL_FIRST (tmpl);
> +      tree tmpl = TREE_OPERAND (src, 0);
>        return DECL_SOURCE_LOCATION (tmpl);
>      }
>  
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 238d786b067..c92ff707e3f 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -3524,12 +3524,6 @@ struct GTY(()) lang_decl {
>    (retrofit_lang_decl (FUNCTION_DECL_CHECK (NODE)),                  \
>     LANG_DECL_FN_CHECK (NODE)->immediate_fn_p = true)
>  
> -// True if NODE was declared as 'concept'.  The flag implies that the
> -// declaration is constexpr, that the declaration cannot be specialized or
> -// refined, and that the result type must be convertible to bool.
> -#define DECL_DECLARED_CONCEPT_P(NODE) \
> -  (DECL_LANG_SPECIFIC (NODE)->u.base.concept_p)
> -
>  /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
>     template function.  */
>  #define DECL_PRETTY_FUNCTION_P(NODE) \
> @@ -8582,7 +8576,6 @@ 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 tree check_function_concept              (tree);
>  extern bool valid_requirements_p                (tree);
>  extern tree finish_concept_name                 (tree);
>  extern tree finish_shorthand_constraint         (tree, tree);
> @@ -8605,7 +8598,6 @@ struct processing_constraint_expression_sentinel
>  
>  extern bool processing_constraint_expression_p       ();
>  
> -extern tree unpack_concept_check             (tree);
>  extern tree get_concept_check_template               (tree);
>  extern tree evaluate_concept_check              (tree);
>  extern bool constraints_satisfied_p          (tree, tree = NULL_TREE);
> @@ -8867,69 +8859,12 @@ variable_template_p (tree t)
>    return false;
>  }
>  
> -/* True iff T is a standard concept definition. This will return
> -   true for both the template and underlying declaration.  */
> -
> -inline bool
> -standard_concept_p (tree t)
> -{
> -  if (TREE_CODE (t) == TEMPLATE_DECL)
> -    t = DECL_TEMPLATE_RESULT (t);
> -  return TREE_CODE (t) == CONCEPT_DECL;
> -}
> -
> -/* True iff T is a variable concept definition. This will return
> -   true for both the template and the underlying declaration.  */
> -
> -inline bool
> -variable_concept_p (tree t)
> -{
> -  if (TREE_CODE (t) == TEMPLATE_DECL)
> -    t = DECL_TEMPLATE_RESULT (t);
> -  return VAR_P (t) && DECL_DECLARED_CONCEPT_P (t);
> -}
> -
> -/* True iff T is a function concept definition or an overload set
> -   containing multiple function concepts. This will return true for
> -   both the template and the underlying declaration.  */
> -
> -inline bool
> -function_concept_p (tree t)
> -{
> -  if (TREE_CODE (t) == OVERLOAD)
> -    t = OVL_FIRST (t);
> -  if (TREE_CODE (t) == TEMPLATE_DECL)
> -    t = DECL_TEMPLATE_RESULT (t);
> -  return TREE_CODE (t) == FUNCTION_DECL && DECL_DECLARED_CONCEPT_P (t);
> -}
> -
> -/* True iff T is a standard, variable, or function concept.  */
> +/* True iff T is a concept.  */
>  
>  inline bool
>  concept_definition_p (tree t)
>  {
> -  if (t == error_mark_node)
> -    return false;
> -
> -  /* Adjust for function concept overloads.  */
> -  if (TREE_CODE (t) == OVERLOAD)
> -    t = OVL_FIRST (t);
> -
> -  /* See through templates.  */
> -  if (TREE_CODE (t) == TEMPLATE_DECL)
> -    t = DECL_TEMPLATE_RESULT (t);
> -
> -  /* The obvious and easy case.  */
> -  if (TREE_CODE (t) == CONCEPT_DECL)
> -    return true;
> -
> -  /* Definitely not a concept.  */
> -  if (!VAR_OR_FUNCTION_DECL_P (t))
> -    return false;
> -  if (!DECL_LANG_SPECIFIC (t))
> -    return false;
> -
> -  return DECL_DECLARED_CONCEPT_P (t);
> +  return TREE_CODE (STRIP_TEMPLATE (t)) == CONCEPT_DECL;
>  }
>  
>  /* Same as above, but for const trees.  */
> @@ -8945,8 +8880,6 @@ concept_definition_p (const_tree t)
>  inline bool
>  concept_check_p (const_tree t)
>  {
> -  if (TREE_CODE (t) == CALL_EXPR)
> -    t = CALL_EXPR_FN (t);
>    if (t && TREE_CODE (t) == TEMPLATE_ID_EXPR)
>      return concept_definition_p (TREE_OPERAND (t, 0));
>    return false;
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 687ae6937f5..04877087dc7 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -1467,36 +1467,6 @@ validate_constexpr_redeclaration (tree old_decl, tree 
> new_decl)
>    return true;
>  }
>  
> -// If OLDDECL and NEWDECL are concept declarations with the same type
> -// (i.e., and template parameters), but different requirements,
> -// emit diagnostics and return true. Otherwise, return false.
> -static inline bool
> -check_concept_refinement (tree olddecl, tree newdecl)
> -{
> -  if (!DECL_DECLARED_CONCEPT_P (olddecl) || !DECL_DECLARED_CONCEPT_P 
> (newdecl))
> -    return false;
> -
> -  tree d1 = DECL_TEMPLATE_RESULT (olddecl);
> -  tree d2 = DECL_TEMPLATE_RESULT (newdecl);
> -  if (TREE_CODE (d1) != TREE_CODE (d2))
> -    return false;
> -
> -  tree t1 = TREE_TYPE (d1);
> -  tree t2 = TREE_TYPE (d2);
> -  if (TREE_CODE (d1) == FUNCTION_DECL)
> -    {
> -      if (compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2))
> -          && comp_template_parms (DECL_TEMPLATE_PARMS (olddecl),
> -                                  DECL_TEMPLATE_PARMS (newdecl))
> -          && !equivalently_constrained (olddecl, newdecl))
> -        {
> -          error ("cannot specialize concept %q#D", olddecl);
> -          return true;
> -        }
> -    }
> -  return false;
> -}
> -
>  /* DECL is a redeclaration of a function or function template.  If
>     it does have default arguments issue a diagnostic.  Note: this
>     function is used to enforce the requirements in C++11 8.3.6 about
> @@ -1990,8 +1960,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
> hiding, bool was_hidden)
>               return error_mark_node;
>             return NULL_TREE;
>           }
> -          else if (check_concept_refinement (olddecl, newdecl))
> -         return error_mark_node;
>         return NULL_TREE;
>       }
>        if (TREE_CODE (newdecl) == FUNCTION_DECL)
> @@ -8224,16 +8192,6 @@ value_dependent_init_p (tree init)
>    return false;
>  }
>  
> -// Returns true if a DECL is VAR_DECL with the concept specifier.
> -static inline bool
> -is_concept_var (tree decl)
> -{
> -  return (VAR_P (decl)
> -       // Not all variables have DECL_LANG_SPECIFIC.
> -          && DECL_LANG_SPECIFIC (decl)
> -          && DECL_DECLARED_CONCEPT_P (decl));
> -}
> -
>  /* A helper function to be called via walk_tree.  If any label exists
>     under *TP, it is (going to be) forced.  Set has_forced_label_in_static.  
> */
>  
> @@ -8751,11 +8709,6 @@ cp_finish_decl (tree decl, tree init, bool 
> init_const_expr_p,
>  
>        if (!VAR_P (decl) || type_dependent_p)
>       /* We can't do anything if the decl has dependent type.  */;
> -      else if (!init && is_concept_var (decl))
> -     {
> -       error ("variable concept has no initializer");
> -       init = boolean_true_node;
> -     }
>        else if (init
>              && (init_const_expr_p || DECL_DECLARED_CONSTEXPR_P (decl))
>              && !TYPE_REF_P (type)
> @@ -10547,26 +10500,6 @@ check_static_quals (tree decl, cp_cv_quals quals)
>          decl);
>  }
>  
> -// Check that FN takes no arguments and returns bool.
> -static void
> -check_concept_fn (tree fn)
> -{
> -  // A constraint is nullary.
> -  if (DECL_ARGUMENTS (fn))
> -    error_at (DECL_SOURCE_LOCATION (fn),
> -           "concept %q#D declared with function parameters", fn);
> -
> -  // The declared return type of the concept shall be bool, and
> -  // it shall not be deduced from it definition.
> -  tree type = TREE_TYPE (TREE_TYPE (fn));
> -  if (is_auto (type))
> -    error_at (DECL_SOURCE_LOCATION (fn),
> -           "concept %q#D declared with a deduced return type", fn);
> -  else if (type != boolean_type_node)
> -    error_at (DECL_SOURCE_LOCATION (fn),
> -           "concept %q#D with non-%<bool%> return type %qT", fn, type);
> -}
> -
>  /* Helper function.  Replace the temporary this parameter injected
>     during cp_finish_omp_declare_simd with the real this parameter.  */
>  
> @@ -10637,10 +10570,9 @@ grokfndecl (tree ctype,
>    /* Was the concept specifier present?  */
>    bool concept_p = inlinep & 4;
>  
> -  /* Concept declarations must have a corresponding definition.  */
> -  if (concept_p && !funcdef_flag)
> +  if (concept_p)
>      {
> -      error_at (location, "concept %qD has no definition", declarator);
> +      error_at (location, "function concepts are no longer supported");
>        return NULL_TREE;
>      }
>  
> @@ -10667,11 +10599,6 @@ grokfndecl (tree ctype,
>           tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
>       }
>        tree ci = build_constraints (tmpl_reqs, decl_reqs);
> -      if (concept_p && ci)
> -        {
> -          error_at (location, "a function concept cannot be constrained");
> -          ci = NULL_TREE;
> -        }
>        /* C++20 CA378: Remove non-templated constrained functions.  */
>        /* [temp.friend]/9 A non-template friend declaration with a
>        requires-clause shall be a definition. A friend function template with
> @@ -10903,14 +10830,6 @@ grokfndecl (tree ctype,
>        SET_DECL_IMMEDIATE_FUNCTION_P (decl);
>      }
>  
> -  // If the concept declaration specifier was found, check
> -  // that the declaration satisfies the necessary requirements.
> -  if (concept_p)
> -    {
> -      DECL_DECLARED_CONCEPT_P (decl) = true;
> -      check_concept_fn (decl);
> -    }
> -
>    DECL_EXTERNAL (decl) = 1;
>    if (TREE_CODE (type) == FUNCTION_TYPE)
>      {
> @@ -11072,8 +10991,7 @@ grokfndecl (tree ctype,
>    decl = check_explicit_specialization (orig_declarator, decl,
>                                       template_count,
>                                       2 * funcdef_flag +
> -                                     4 * (friendp != 0) +
> -                                     8 * concept_p,
> +                                     4 * (friendp != 0),
>                                       *attrlist);
>    if (decl == error_mark_node)
>      return NULL_TREE;
> @@ -11365,29 +11283,19 @@ grokvardecl (tree type,
>                 "C language linkage");
>      }
>  
> -  /* Check that the variable can be safely declared as a concept.
> -     Note that this also forbids explicit specializations.  */
> +  /* Check if a variable is being declared as a concept.  */
>    if (conceptp)
>      {
>        if (!processing_template_decl)
> -        {
> -          error_at (declspecs->locations[ds_concept],
> -                 "a non-template variable cannot be %<concept%>");
> -          return NULL_TREE;
> -        }
> +     error_at (declspecs->locations[ds_concept],
> +               "a non-template variable cannot be %<concept%>");
>        else if (!at_namespace_scope_p ())
> -     {
> -       error_at (declspecs->locations[ds_concept],
> -                 "concept must be defined at namespace scope");
> -       return NULL_TREE;
> -     }
> +     error_at (declspecs->locations[ds_concept],
> +               "concept must be defined at namespace scope");
>        else
> -        DECL_DECLARED_CONCEPT_P (decl) = true;
> -      if (TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
> -        {
> -          error_at (location, "a variable concept cannot be constrained");
> -          TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = NULL_TREE;
> -        }
> +     error_at (declspecs->locations[ds_concept],
> +               "variable concepts are no longer supported");
> +      return NULL_TREE;
>      }
>    else if (flag_concepts
>          && current_template_depth > template_class_depth (scope))
> @@ -18808,10 +18716,6 @@ finish_function (bool inline_p)
>        goto cleanup;
>      }
>  
> -  // If this is a concept, check that the definition is reasonable.
> -  if (DECL_DECLARED_CONCEPT_P (fndecl))
> -    check_function_concept (fndecl);
> -
>    if (flag_openmp)
>      if (tree attr = lookup_attribute ("omp declare variant base",
>                                     DECL_ATTRIBUTES (fndecl)))
> diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
> index 6d674684931..695d5f8d790 100644
> --- a/gcc/cp/decl2.cc
> +++ b/gcc/cp/decl2.cc
> @@ -2723,7 +2723,7 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
> *data)
>        break;
>  
>      case TEMPLATE_DECL:
> -      if (DECL_ALIAS_TEMPLATE_P (t) || standard_concept_p (t))
> +      if (DECL_ALIAS_TEMPLATE_P (t) || concept_definition_p (t))
>       /* FIXME: We don't maintain TREE_PUBLIC / DECL_VISIBILITY for
>          alias templates so we can't trust it here (PR107906).  Ditto
>          for concepts.  */
> @@ -5687,7 +5687,6 @@ maybe_instantiate_decl (tree decl)
>    if (VAR_OR_FUNCTION_DECL_P (decl)
>        && DECL_LANG_SPECIFIC (decl)
>        && DECL_TEMPLATE_INFO (decl)
> -      && !DECL_DECLARED_CONCEPT_P (decl)
>        && !uses_template_parms (DECL_TI_ARGS (decl)))
>      {
>        /* Instantiating a function will result in garbage collection.  We
> @@ -6084,7 +6083,6 @@ mark_used (tree decl, tsubst_flags_t complain /* = 
> tf_warning_or_error */)
>      }
>    else if (VAR_OR_FUNCTION_DECL_P (decl)
>          && DECL_TEMPLATE_INFO (decl)
> -           && !DECL_DECLARED_CONCEPT_P (decl)
>          && (!DECL_EXPLICIT_INSTANTIATION (decl)
>              || always_instantiate_p (decl)))
>      /* If this is a function or variable that is an instance of some
> diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
> index d80bac822ba..aecbc4ff0d9 100644
> --- a/gcc/cp/error.cc
> +++ b/gcc/cp/error.cc
> @@ -1163,7 +1163,7 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree 
> type, int flags)
>        else if (VAR_P (t) && DECL_DECLARED_CONSTEXPR_P (t))
>       pp_cxx_ws_string (pp, "constexpr");
>  
> -      if (!standard_concept_p (t))
> +      if (!concept_definition_p (t))
>       dump_type_prefix (pp, type, flags & ~TFF_UNQUALIFIED_NAME);
>        pp_maybe_space (pp);
>      }
> @@ -1806,9 +1806,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
> flags)
>  
>        if (constexpr_p)
>          {
> -          if (DECL_DECLARED_CONCEPT_P (t))
> -            pp_cxx_ws_string (pp, "concept");
> -       else if (DECL_IMMEDIATE_FUNCTION_P (t))
> +       if (DECL_IMMEDIATE_FUNCTION_P (t))
>           pp_cxx_ws_string (pp, "consteval");
>         else
>           pp_cxx_ws_string (pp, "constexpr");
> @@ -3952,8 +3950,8 @@ print_concept_check_info (diagnostic_context *context, 
> tree expr, tree map, tree
>  {
>    gcc_assert (concept_check_p (expr));
>  
> -  tree id = unpack_concept_check (expr);
> -  tree tmpl = TREE_OPERAND (id, 0);
> +  tree tmpl = TREE_OPERAND (expr, 0);
> +  // ??? Can this go now that fn/var concepts have been removed?
>    if (OVL_P (tmpl))
>      tmpl = OVL_FIRST (tmpl);
>  
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index e7391220234..46dc6923add 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -901,9 +901,9 @@ write_tparms_constraints (tree constraints)
>  static void
>  write_type_constraint (tree cnst)
>  {
> -  if (!cnst) return;
> +  if (!cnst)
> +    return;
>  
> -  cnst = unpack_concept_check (cnst);
>    gcc_checking_assert (TREE_CODE (cnst) == TEMPLATE_ID_EXPR);
>  
>    tree concept_decl = get_concept_check_template (cnst);
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index eb102dea829..f625b0a310c 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -7161,18 +7161,13 @@ cp_parser_nested_name_specifier_opt (cp_parser 
> *parser,
>                     tree fns = get_fns (tid);
>                     if (OVL_SINGLE_P (fns))
>                       tmpl = OVL_FIRST (fns);
> -                   if (function_concept_p (fns))
> -                     error_at (token->location, "concept-id %qD "
> -                               "in nested-name-specifier", tid);
> -                   else
> -                     error_at (token->location, "function template-id "
> -                               "%qD in nested-name-specifier", tid);
> +                   error_at (token->location, "function template-id "
> +                             "%qD in nested-name-specifier", tid);
>                   }
>                 else
>                   {
>                     tmpl = TREE_OPERAND (tid, 0);
> -                   if (variable_concept_p (tmpl)
> -                       || standard_concept_p (tmpl))
> +                   if (concept_definition_p (tmpl))
>                       error_at (token->location, "concept-id %qD "
>                                 "in nested-name-specifier", tid);
>                     else
> @@ -12224,9 +12219,6 @@ add_debug_begin_stmt (location_t loc)
>  {
>    if (!MAY_HAVE_DEBUG_MARKER_STMTS)
>      return;
> -  if (DECL_DECLARED_CONCEPT_P (current_function_decl))
> -    /* A concept is never expanded normally.  */
> -    return;
>  
>    tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
>    SET_EXPR_LOCATION (stmt, loc);
> @@ -33087,8 +33079,6 @@ cp_parser_template_declaration_after_parameters 
> (cp_parser* parser,
>    else if (flag_concepts
>             && cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT)
>          && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
> -    /* -fconcept-ts 'concept bool' syntax is handled below, in
> -     cp_parser_single_declaration.  */
>      decl = cp_parser_concept_definition (parser);
>    else
>      {
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 77fa5907c3d..35a9c5619f9 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -3232,14 +3232,6 @@ check_explicit_specialization (tree declarator,
>                tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
>                gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
>  
> -              /* A concept cannot be specialized.  */
> -              if (DECL_DECLARED_CONCEPT_P (tmpl_func))
> -                {
> -                  error ("explicit specialization of function concept %qD",
> -                         gen_tmpl);
> -                  return error_mark_node;
> -                }
> -
>                /* This specialization has the same linkage and visibility as
>                   the function template it specializes.  */
>                TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
> @@ -5150,13 +5142,6 @@ process_partial_specialization (tree decl)
>  
>    gcc_assert (current_template_parms);
>  
> -  /* A concept cannot be specialized.  */
> -  if (flag_concepts && variable_concept_p (maintmpl))
> -    {
> -      error ("specialization of variable concept %q#D", maintmpl);
> -      return error_mark_node;
> -    }
> -
>    inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
>    ntparms = TREE_VEC_LENGTH (inner_parms);
>  
> @@ -10532,9 +10517,6 @@ lookup_template_class (tree d1, tree arglist, tree 
> in_decl, tree context,
>  tree
>  lookup_template_variable (tree templ, tree arglist, tsubst_flags_t complain)
>  {
> -  if (flag_concepts && variable_concept_p (templ))
> -    return build_concept_check (templ, arglist, tf_none);
> -
>    tree gen_templ = most_general_template (templ);
>    tree parms = DECL_INNERMOST_TEMPLATE_PARMS (gen_templ);
>    arglist = add_outermost_template_args (templ, arglist);
> @@ -20119,14 +20101,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
> complain, tree in_decl)
>           tree check = build_concept_check (templ, targs, complain);
>           if (check == error_mark_node)
>             RETURN (error_mark_node);
> -
> -         tree id = unpack_concept_check (check);
> -
> -         /* If we built a function concept check, return the underlying
> -            template-id. So we can evaluate it as a function call.  */
> -         if (function_concept_p (TREE_OPERAND (id, 0)))
> -           RETURN (id);
> -
>           RETURN (check);
>         }
>  
> @@ -21096,19 +21070,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
> complain, tree in_decl)
>         ret = build_offset_ref_call_from_tree (function, &call_args,
>                                                complain);
>       else if (concept_check_p (function))
> -       {
> -         /* FUNCTION is a template-id referring to a concept definition.  */
> -         tree id = unpack_concept_check (function);
> -         tree tmpl = TREE_OPERAND (id, 0);
> -         tree args = TREE_OPERAND (id, 1);
> -
> -         /* Calls to standard and variable concepts should have been
> -            previously diagnosed.  */
> -         gcc_assert (function_concept_p (tmpl));
> -
> -         /* Ensure the result is wrapped as a call expression.  */
> -         ret = build_concept_check (tmpl, args, tf_warning_or_error);
> -       }
> +       /* Calls to concepts should have been previously diagnosed.  */
> +       gcc_assert (false);
>       else
>         ret = finish_call_expr (function, &call_args,
>                                 /*disallow_virtual=*/qualified_p,
> @@ -26414,14 +26377,6 @@ do_decl_instantiation (tree decl, tree storage)
>        error ("explicit instantiation of non-template %q#D", decl);
>        return;
>      }
> -  else if (DECL_DECLARED_CONCEPT_P (decl))
> -    {
> -      if (VAR_P (decl))
> -     error ("explicit instantiation of variable concept %q#D", decl);
> -      else
> -     error ("explicit instantiation of function concept %q#D", decl);
> -      return;
> -    }
>  
>    bool var_templ = (DECL_TEMPLATE_INFO (decl)
>                      && variable_template_p (DECL_TI_TEMPLATE (decl)));
> @@ -27211,9 +27166,6 @@ instantiate_decl (tree d, bool defer_ok, bool 
> expl_inst_class_mem_p)
>       functions and static member variables.  */
>    gcc_assert (VAR_OR_FUNCTION_DECL_P (d));
>  
> -  /* A concept is never instantiated. */
> -  gcc_assert (!DECL_DECLARED_CONCEPT_P (d));
> -
>    gcc_checking_assert (!DECL_FUNCTION_SCOPE_P (d));
>  
>    if (modules_p ())
> @@ -29492,8 +29444,8 @@ make_constrained_decltype_auto (tree con, tree args)
>  static bool
>  placeholder_type_constraint_dependent_p (tree t)
>  {
> -  tree id = unpack_concept_check (t);
> -  tree args = TREE_OPERAND (id, 1);
> +  gcc_assert (concept_check_p (t));
> +  tree args = TREE_OPERAND (t, 1);
>    tree first = TREE_VEC_ELT (args, 0);
>    if (ARGUMENT_PACK_P (first))
>      {
> @@ -31452,8 +31404,8 @@ convert_generic_types_to_packs (tree parm, int 
> start_idx, int end_idx)
>           requirements.  */
>        if (tree constr = TEMPLATE_PARM_CONSTRAINTS (node))
>       {
> -       tree id = unpack_concept_check (constr);
> -       TREE_VEC_ELT (TREE_OPERAND (id, 1), 0) = t;
> +       gcc_assert (concept_check_p (constr));
> +       TREE_VEC_ELT (TREE_OPERAND (constr, 1), 0) = t;
>         /* Use UNKNOWN_LOCATION so write_template_args can tell the
>            difference between this and a fold the user wrote.  */
>         location_t loc = UNKNOWN_LOCATION;
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 669da4ad969..e58612660c9 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -3067,20 +3067,9 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, 
> bool disallow_virtual,
>      }
>    else if (concept_check_p (fn))
>      {
> -      /* FN is actually a template-id referring to a concept definition.  */
> -      tree id = unpack_concept_check (fn);
> -      tree tmpl = TREE_OPERAND (id, 0);
> -      tree args = TREE_OPERAND (id, 1);
> -
> -      if (!function_concept_p (tmpl))
> -     {
> -       error_at (EXPR_LOC_OR_LOC (fn, input_location),
> -                 "cannot call a concept as a function");
> -       return error_mark_node;
> -     }
> -
> -      /* Ensure the result is wrapped as a call expression.  */
> -      result = build_concept_check (tmpl, args, tf_warning_or_error);
> +      error_at (EXPR_LOC_OR_LOC (fn, input_location),
> +             "cannot call a concept as a function");
> +      return error_mark_node;
>      }
>    else if (is_overloaded_fn (fn))
>      {
> diff --git a/gcc/testsuite/g++.dg/concepts/decl-diagnose.C 
> b/gcc/testsuite/g++.dg/concepts/decl-diagnose.C
> index 0d10ce1ea9f..2bf1cd5ab17 100644
> --- a/gcc/testsuite/g++.dg/concepts/decl-diagnose.C
> +++ b/gcc/testsuite/g++.dg/concepts/decl-diagnose.C
> @@ -7,8 +7,8 @@ typedef concept int CINT; // { dg-error "'concept' cannot 
> appear in a typedef de
>  void f(concept int); // { dg-error "a parameter cannot be declared 
> 'concept'" }
>  
>  template<typename T>
> -concept int f2() { return 0; } // { dg-error "return type" }
> -concept bool f3(); // { dg-error "14:concept .f3. has no definition" }
> +concept int f2() { return 0; } // { dg-error "function concepts are no 
> longer supported" }
> +concept bool f3(); // { dg-error "14:function concepts are no longer 
> supported" }
>                  // { dg-error "keyword is not allowed" "" { target *-*-* } 
> .-1 }
>  
>  struct X
> @@ -26,11 +26,11 @@ struct X
>    concept X(); // { dg-error "a constructor cannot be 'concept'" }
>  };
>  
> -concept bool X2; // { dg-error "non-template variable" }
> +concept bool X2; // { dg-error "variable" }
>                // { dg-error "keyword is not allowed" "" { target *-*-* } .-1 
> }
>  
>  template<typename T>
> -  concept bool X3; // { dg-error "has no initializer" }
> +  concept bool X3; // { dg-error "variable concepts" }
>                  // { dg-error "keyword is not allowed" "" { target *-*-* } 
> .-1 }
>  
>  struct S {
> diff --git a/gcc/testsuite/g++.dg/concepts/fn-concept2.C 
> b/gcc/testsuite/g++.dg/concepts/fn-concept2.C
> index 799e85de955..52ca8245c76 100644
> --- a/gcc/testsuite/g++.dg/concepts/fn-concept2.C
> +++ b/gcc/testsuite/g++.dg/concepts/fn-concept2.C
> @@ -3,7 +3,7 @@
>  // { dg-prune-output "concept definition syntax is" }
>  
>  template<typename T>
> -  concept auto C1() { return 0; } // { dg-error "16:concept .concept auto 
> C1\\(\\). declared with a deduced return type" }
> +  concept auto C1() { return 0; } // { dg-error "16:function concepts are no 
> longer supported" }
>  
>  template<typename T>
> -  concept int C2() { return 0; } // { dg-error "15:concept .concept int 
> C2\\(\\). with non-.bool. return type .int." }
> +  concept int C2() { return 0; } // { dg-error "15:function concepts are no 
> longer supported" }
> diff --git a/gcc/testsuite/g++.dg/concepts/pr71128.C 
> b/gcc/testsuite/g++.dg/concepts/pr71128.C
> index 63b3d1dff78..a3d5357d432 100644
> --- a/gcc/testsuite/g++.dg/concepts/pr71128.C
> +++ b/gcc/testsuite/g++.dg/concepts/pr71128.C
> @@ -2,9 +2,9 @@
>  // { dg-options "-fconcepts" }
>  
>  template<typename T>
> -concept bool C() { return true; } // { dg-error "the .bool. keyword" }
> -template bool C<int>();  // { dg-error "explicit instantiation of function 
> concept" }
> +concept bool C() { return true; } // { dg-error "the .bool. keyword|function 
> concepts" }
> +template bool C<int>();  // { dg-error "template function|not a function 
> template|expected" }
>  
>  template<typename T>
> -concept bool D = true;       // { dg-error "the .bool. keyword" }
> -template bool D<int>;  // { dg-error "explicit instantiation of variable 
> concept" }
> +concept bool D = true;       // { dg-error "the .bool. keyword|variable 
> concepts are no longer supported" }
> +template bool D<int>;  // { dg-error "not a template function|expected" }
> diff --git a/gcc/testsuite/g++.dg/concepts/var-concept6.C 
> b/gcc/testsuite/g++.dg/concepts/var-concept6.C
> index 04298f47a92..062007a1291 100644
> --- a/gcc/testsuite/g++.dg/concepts/var-concept6.C
> +++ b/gcc/testsuite/g++.dg/concepts/var-concept6.C
> @@ -2,4 +2,4 @@
>  // { dg-options "-fconcepts" }
>  
>  template <class T>
> -concept int C = true;                // { dg-error "concept definition 
> syntax" }
> +concept int C = true;                // { dg-error "concept definition 
> syntax|variable concepts are no longer supported" }
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts.C 
> b/gcc/testsuite/g++.dg/cpp2a/concepts.C
> index ebeeebf60bb..1b7a708659b 100644
> --- a/gcc/testsuite/g++.dg/cpp2a/concepts.C
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts.C
> @@ -18,9 +18,9 @@ void f3(T)
>  { }
>  
>  template<typename T>
> -concept bool C1 = true; // { dg-error "bool" }
> +concept bool C1 = true; // { dg-error "bool|variable concepts" }
>  template<typename T>
> -bool concept C2 = true; // { dg-error "concept definition syntax" }
> +bool concept C2 = true; // { dg-error "concept definition syntax|variable 
> concepts" }
>  
>  template<typename T>
>  concept C3 = true; // OK
> 
> base-commit: a10436a8404ad2f0cc5aa4d6a0cc850abe5ef49e
> -- 
> 2.45.2
> 
> 

Reply via email to