From patchwork Fri Aug 2 18:12:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1968466 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Lx26GjoG; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WbDTX2B7fz1yYq for ; Sat, 3 Aug 2024 04:13:04 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 06996385842C for ; Fri, 2 Aug 2024 18:13:02 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id E86D23858D26 for ; Fri, 2 Aug 2024 18:12:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E86D23858D26 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E86D23858D26 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722622360; cv=none; b=sdNhCUsi2hr/VHwNBPNi1Obn6ng/u4DvZO/gT1KM2RGvoM5V2O4Wq0Oss+e80BwfFBPxIvvhMywnvYz03O9BQe3tcgl26bfed/tsdXk1pjHS/9roaXk8XLnyvgI3oWABM0SpG+BF/J8X1xxmBGLQLkh6vCxCsZWenGRLEngJy+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722622360; c=relaxed/simple; bh=mfWAmFDd0GBSxM3oeA2mCxCmTMoJgBvAl+VA0pWmywk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=nkQVuW+Sm6o3UCytFWWMzIENazwbEGIVe5Ks+sKL2WgtqphDJSaO5kaR64svcdr3DsFSuEwh2Iic2Do/wsDwHF2b+eLY5UeuwXWTe2vHjmOCYI+uwugjEIOWvB6jlnxuyMCmdQwxhz9lrqPPR/iUoLadbMtiV9uoe0EOYiMxcBY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1722622353; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ZPa1U7sz7t4vGMGcNc4TDEs9B887NIY3QBs580iqmTo=; b=Lx26GjoGgc0Ibv94SRHDnSDQfIpQahB+BdHDdks4CXyaQjpgm6B7GhdNyp3cuukM7daqXM KmPPqlGAx42gfXlvT7rPYhpPHRadAnrH2XRVvQpTc0g+YqD621FIWfHwIWg0AjBu5VSRj4 nxlkuONS4qkAjrVj7HqYhrLN0AxwZYI= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-421-RknhMXJXPA2KAkpOkqGCng-1; Fri, 02 Aug 2024 14:12:30 -0400 X-MC-Unique: RknhMXJXPA2KAkpOkqGCng-1 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 83B3D19560B1 for ; Fri, 2 Aug 2024 18:12:29 +0000 (UTC) Received: from pdp-11.redhat.com (unknown [10.22.9.167]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 002C01955E80; Fri, 2 Aug 2024 18:12:27 +0000 (UTC) From: Marek Polacek To: GCC Patches , Jason Merrill , Patrick Palka Subject: [PATCH] c++: remove function/var concepts code Date: Fri, 2 Aug 2024 14:12:21 -0400 Message-ID: <20240802181221.18448-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped/regtested on x86_64-pc-linux-gnu. Comments? -- >8 -- This patch removes vestigial Concepts TS code as discussed in . 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) : 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(-) base-commit: a10436a8404ad2f0cc5aa4d6a0cc850abe5ef49e 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() - - 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_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_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()` 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 *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` 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` 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-% 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 %"); - return NULL_TREE; - } + error_at (declspecs->locations[ds_concept], + "a non-template variable cannot be %"); 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 **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 -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 - 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 - 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 - 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 -concept bool C() { return true; } // { dg-error "the .bool. keyword" } -template bool C(); // { dg-error "explicit instantiation of function concept" } +concept bool C() { return true; } // { dg-error "the .bool. keyword|function concepts" } +template bool C(); // { dg-error "template function|not a function template|expected" } template -concept bool D = true; // { dg-error "the .bool. keyword" } -template bool D; // { 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; // { 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 -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 -concept bool C1 = true; // { dg-error "bool" } +concept bool C1 = true; // { dg-error "bool|variable concepts" } template -bool concept C2 = true; // { dg-error "concept definition syntax" } +bool concept C2 = true; // { dg-error "concept definition syntax|variable concepts" } template concept C3 = true; // OK