From patchwork Mon Oct 2 19:37:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 147440 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2a8e:b0:403:3b70:6f57 with SMTP id in14csp1650529vqb; Mon, 2 Oct 2023 12:39:27 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE6K6gDZbZ7bbFi/wNzC2czQ7j1vTQpxnV+lP2EEcHS+sZQsv90ReRAZMJ65UStDzKbP5DE X-Received: by 2002:a17:907:2cd5:b0:9ae:68dc:d571 with SMTP id hg21-20020a1709072cd500b009ae68dcd571mr10890211ejc.46.1696275566740; Mon, 02 Oct 2023 12:39:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696275566; cv=none; d=google.com; s=arc-20160816; b=HhzGN+UvjRLCwisiwZwPqZuabuu+sIkf8Z9jRhln/FI77n7/y6pIIxm/KhqFr7JEio 9qajApInqLyYbONGqPwa8piJpLinWabbHPjC7xzGkYDnKf2W04X+tX68dvMXJU5u5uFO pHJ+do5NvbFIa09cZewrw4tuKbcOBJuy9d/fMdHC5gGB9WB4D5AC3id7YUIm4j9kboK5 BptNO5ngVw/qF7+QEd7plfKHm9QYD2SJuSMHjyt0m8m/DKntdOYuk9gG1vg8zg5do6kL bVg2w7F8NAJfH+wMqWSjXm4h+KdyCKltv9DYnCtL4uVhmu6ENewLLeTSrol5C8MvRNyW nLaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dmarc-filter:delivered-to; bh=sSDBg+fThOZAn1l/Sqlu7bfI9IIOAMj85Qxgb1YkWtI=; fh=1Hi9m88IqcWZGtfSxUrMGG+GBgL26N02X1SANXM6iTs=; b=k8X9HJd3eZdYi4kEf8xFCix7NlPADrqNnAo0fTZNKqh56d+LqKZFNLmHk0bELSMXbj Uj6Uqe5S8aJkDuhEmntwp0PeJTvc7/yJChj8V3U27EKXa5D2i9tWZYzydb9rLlyT5Bib SsvqLiCWrgX6nZite4Z14d/dFazSgyUahfM+zlP/VRReOIYdSoaGc4oAJs0ji9fIE0d3 djpzmkVfb7kAGgUyHXpzaMPmCc3s6oRA011NRwuPHDRElye9kWohndYJp/HqQcuZFDsw Mkp6Jh7gN+G9TI3V/1alu91MiANSq1Me+dKs6Ng2FvFMeKA6v2kCFUsPFVsuE50IBMdw JaGw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=aeepdbXL; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id h11-20020a170906590b00b00993150ec3c4si19500391ejq.970.2023.10.02.12.39.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Oct 2023 12:39:26 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=aeepdbXL; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 28BDD385414F for ; Mon, 2 Oct 2023 19:38:55 +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 ESMTPS id 9F9183858D32 for ; Mon, 2 Oct 2023 19:38:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9F9183858D32 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1696275499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sSDBg+fThOZAn1l/Sqlu7bfI9IIOAMj85Qxgb1YkWtI=; b=aeepdbXL92/TpyLP/48wW3wMhG5rnj2fBIrPeoIIjKiqiD8kf/BEEshzKde7Hp+fOegyH3 NpJif70ysPqKDh0HUKOVTPDIGS2ujR41QBR/klQC/UxpnFRoss2I1RjKGbzFXdvSmRijdI 9Z6WdevgkyfZmYyS+JYVNSPbZPomwg8= Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-459-JTZBjtdpMcezd12pQ2SDpQ-1; Mon, 02 Oct 2023 15:38:11 -0400 X-MC-Unique: JTZBjtdpMcezd12pQ2SDpQ-1 Received: by mail-qt1-f199.google.com with SMTP id d75a77b69052e-418099ca1c2so1767891cf.0 for ; Mon, 02 Oct 2023 12:38:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696275490; x=1696880290; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sSDBg+fThOZAn1l/Sqlu7bfI9IIOAMj85Qxgb1YkWtI=; b=vMZTjAcmsF5aCSKf7rthezyiZDOJ6S/kfhD7G974R5jodkdJ3JQ5NtXzAEkmjahABC qoAc6K+eesV0hB6C7CwvqWMKqNIg+Sv0q7AxQO9qD1SqX6pZmrBb5OtT6kyLfBQ7IOgJ MO7LAfbgVJwn1JewJyYA+fQBk5KEfyaw2iUz7+vT9e2ifdXIGfqB5K6e1QgQw2UzNyBI n3hQbbbkZ0VGPQ3oBvYU41FJIGzIG0eW5NukxiNJ8gPQUg4VNCbeE4Kve4Gr+oD2GkCj /pVOIHAPJd7c4b300iBQWl5+2Ce3w0AaPnnpO02X1znXIQJp+uKadixVhrQhZ53tMSwK Vkow== X-Gm-Message-State: AOJu0YwD/8pbwfn2gQ3ghYcCHfRRqJm8lRMBpC0dm704Mow3NfRs5CxG FW6K+Hbo9VTIEW/eaJ32TKdRgFlg7LIQdZDm348fUF6cknKeSXysu83FPfwAWNCrU0A85Ww+36N 9xMGnak905PKRwI1mhfVzFiSXruY2aukqP5jBVywoPRgqJI/SMaOc96QJYKyBq3NZfoW9sdJQts Q= X-Received: by 2002:ac8:4e43:0:b0:419:595a:c4fc with SMTP id e3-20020ac84e43000000b00419595ac4fcmr16179479qtw.32.1696275489439; Mon, 02 Oct 2023 12:38:09 -0700 (PDT) X-Received: by 2002:ac8:4e43:0:b0:419:595a:c4fc with SMTP id e3-20020ac84e43000000b00419595ac4fcmr16179430qtw.32.1696275488093; Mon, 02 Oct 2023 12:38:08 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id a28-20020ac844bc000000b003f6ac526568sm4899662qto.39.2023.10.02.12.38.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Oct 2023 12:38:07 -0700 (PDT) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] c++: merge tsubst_copy into tsubst_copy_and_build Date: Mon, 2 Oct 2023 15:37:38 -0400 Message-ID: <20231002193738.3900509-1-ppalka@redhat.com> X-Mailer: git-send-email 2.42.0.296.g493f462273 In-Reply-To: <20230925204302.1277285-2-ppalka@redhat.com> References: <20230925204302.1277285-2-ppalka@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, WEIRD_PORT 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+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778673848826841134 X-GMAIL-MSGID: 1778673848826841134 Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? -- >8 -- The relationship between tsubst_copy_and_build and tsubst_copy (two of the main template argument substitution routines for expression trees) is rather hazy. The former is mostly a superset of the latter, with some differences. The main difference is that they handle many tree codes differently, but much of the tree code handling in tsubst_copy appears to be dead code[1]. This is because tsubst_copy only gets directly called in a few places and mostly on id-expressions. The interesting exceptions are PARM_DECL, VAR_DECL, BIT_NOT_EXPR, SCOPE_REF, TEMPLATE_ID_EXPR and IDENTIFIER_NODE: * for PARM_DECL and VAR_DECL, tsubst_copy_and_build calls tsubst_copy followed by doing some extra handling of its own * for BIT_NOT_EXPR tsubst_copy implicitly handles unresolved destructor calls (i.e. the first operand is an identifier or a type) * for SCOPE_REF, TEMPLATE_ID_EXPR and IDENTIFIER_NODE tsubst_copy refrains from doing name lookup of the terminal name Other more minor differences are that tsubst_copy exits early when 'args' is null, and it calls maybe_dependent_member_ref, and finally it dispatches to tsubst for type trees. Thus tsubst_copy is (at this point) similar enough to tsubst_copy_and_build that it makes sense to merge the two functions, with the main difference being the name lookup behavior[2]. So this patch merges tsubst_copy into tsubst_copy_and_build via a new tsubst tf_no_name_lookup which controls name lookup and resolution of a (top-level) id-expression. [1]: http://thrifty.mooo.com:8008/gcc-lcov/gcc/cp/pt.cc.gcov.html#17231 [2]: I don't know the history of tsubst_copy but I would guess it was added before we settled on using processing_template_decl to control whether our AST building routines perform semantic checking and return non-templated trees, and so we needed a separate tsubst routine that avoids semantic checking and always returns a templated tree for e.g. partial substitution. gcc/cp/ChangeLog: * cp-tree.h (enum tsubst_flags): Add tf_no_name_lookup. * pt.cc (tsubst_copy): (tsubst_pack_expansion): Use tsubst for substituting BASES_TYPE. (tsubst_decl) : Use tsubst_copy_and_build with tf_no_name_lookup instead of tsubst_copy. (tsubst) : Use tsubst_copy_and_build instead of tsubst_copy for substituting CLASS_PLACEHOLDER_TEMPLATE. : Use tsubst_copy_and_build with tf_no_name_lookup instead of tsubst_copy for substituting TYPENAME_TYPE_FULLNAME. (tsubst_qualified_id): Likewise for substituting the component name of a SCOPE_REF. (tsubst_copy): Remove. (tsubst_copy_and_build): Clear tf_no_name_lookup at the start, and remember if it was set. Call maybe_dependent_member_ref. : Don't do name lookup if tf_no_name_lookup was set. : Don't finish a template-id if tf_no_name_lookup was set. : Handle identifier and type operand (if tf_no_name_lookup was set). : Avoid trying to resolve a SCOPE_REF if tf_no_name_lookup by calling build_qualified_name directly instead of tsubst_qualified_id. : Handling of sizeof... copied from tsubst_copy. : Use tsubst_copy_and_build with tf_no_name_lookup instead of tsubst_copy to substitute a TEMPLATE_ID_EXPR callee naming an unresolved template. : Likewise to substitute the member. : Copied from tsubst_copy and merged with ... : ... these. Initial handling copied from tsubst_copy. Optimize local variable substitution by trying retrieve_local_specialization before checking uses_template_parms. : Copied from tsubst_copy. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Use tsubst and tsubst_copy_and_build instead of tsubst_copy. : Copied from tsubst_copy. (tsubst_initializer_list): Use tsubst and tsubst_copy_and_build instead of tsubst_copy. --- gcc/cp/cp-tree.h | 3 + gcc/cp/pt.cc | 1742 +++++++++++++++++++--------------------------- 2 files changed, 719 insertions(+), 1026 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8b9a7d58462..919eab34803 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5619,6 +5619,9 @@ enum tsubst_flags { tf_qualifying_scope = 1 << 14, /* Substituting the LHS of the :: operator. Affects TYPENAME_TYPE resolution from make_typename_type. */ + tf_no_name_lookup = 1 << 15, /* Don't look up the terminal name of an + outermost id-expression, or resolve its + constituent template-ids or qualified-ids. */ /* Convenient substitution flags combinations. */ tf_warning_or_error = tf_warning | tf_error }; diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 4400d429b6f..e1fb20994e3 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -204,7 +204,6 @@ static void copy_default_args_to_explicit_spec (tree); static bool invalid_nontype_parm_type_p (tree, tsubst_flags_t); static bool dependent_template_arg_p (tree); static bool dependent_type_p_r (tree); -static tree tsubst_copy (tree, tree, tsubst_flags_t, tree); static tree tsubst_decl (tree, tree, tsubst_flags_t, bool = true); static tree tsubst_scope (tree, tree, tsubst_flags_t, tree); static void perform_instantiation_time_access_checks (tree, tree); @@ -13373,15 +13372,11 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, if (TREE_CODE (parm_pack) == BASES) { gcc_assert (parm_pack == pattern); + tree type = tsubst (BASES_TYPE (parm_pack), args, complain, in_decl); if (BASES_DIRECT (parm_pack)) - return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack), - args, complain, - in_decl), - complain); + return calculate_direct_bases (type, complain); else - return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack), - args, complain, in_decl), - complain); + return calculate_bases (type, complain); } else if (builtin_pack_call_p (parm_pack)) { @@ -15171,7 +15166,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, variadic_p = true; } else - name = tsubst_copy (name, args, complain, in_decl); + name = tsubst_copy_and_build (name, args, + complain | tf_no_name_lookup, in_decl); int len; if (!variadic_p) @@ -16108,7 +16104,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (template_placeholder_p (t)) { tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (t); - tmpl = tsubst_copy (tmpl, args, complain, in_decl); + tmpl = tsubst_copy_and_build (tmpl, args, complain, in_decl); if (TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM) tmpl = TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (tmpl); @@ -16592,8 +16588,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (ctx == error_mark_node) return error_mark_node; - tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, - complain, in_decl); + tree f = tsubst_copy_and_build (TYPENAME_TYPE_FULLNAME (t), args, + complain | tf_no_name_lookup, in_decl); if (f == error_mark_node) return error_mark_node; @@ -17045,7 +17041,8 @@ tsubst_qualified_id (tree qualified_id, tree args, if (args) { scope = tsubst_scope (scope, args, complain, in_decl); - expr = tsubst_copy (name, args, complain, in_decl); + expr = tsubst_copy_and_build (name, args, + complain | tf_no_name_lookup, in_decl); } else expr = name; @@ -17277,878 +17274,177 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain, TREE_CODE (t) == TEMPLATE_DECL); } -/* Like tsubst, but deals with expressions. This function just replaces - template parms; to finish processing the resultant expression, use - tsubst_copy_and_build or tsubst_expr. */ +/* Helper function for tsubst_omp_clauses, used for instantiation of + OMP_CLAUSE_DECL of clauses. */ static tree -tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) +tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain, + tree in_decl, tree *iterator_cache) { - enum tree_code code; - tree r; - - if (t == NULL_TREE || t == error_mark_node || args == NULL_TREE) - return t; - - if (TYPE_P (t)) - return tsubst (t, args, complain, in_decl); - - if (tree d = maybe_dependent_member_ref (t, args, complain, in_decl)) - return d; - - code = TREE_CODE (t); + if (decl == NULL_TREE || decl == ridpointers[RID_OMP_ALL_MEMORY]) + return decl; - switch (code) + /* Handle OpenMP iterators. */ + if (TREE_CODE (decl) == TREE_LIST + && TREE_PURPOSE (decl) + && TREE_CODE (TREE_PURPOSE (decl)) == TREE_VEC) { - case PARM_DECL: - r = retrieve_local_specialization (t); - - if (r == NULL_TREE) + tree ret; + if (iterator_cache[0] == TREE_PURPOSE (decl)) + ret = iterator_cache[1]; + else { - /* We get here for a use of 'this' in an NSDMI. */ - if (DECL_NAME (t) == this_identifier && current_class_ptr) - return current_class_ptr; - - /* This can happen for a parameter name used later in a function - declaration (such as in a late-specified return type). Just - make a dummy decl, since it's only used for its type. */ - gcc_assert (cp_unevaluated_operand); - r = tsubst_decl (t, args, complain); - /* Give it the template pattern as its context; its true context - hasn't been instantiated yet and this is good enough for - mangling. */ - DECL_CONTEXT (r) = DECL_CONTEXT (t); + tree *tp = &ret; + begin_scope (sk_omp, NULL); + for (tree it = TREE_PURPOSE (decl); it; it = TREE_CHAIN (it)) + { + *tp = copy_node (it); + TREE_VEC_ELT (*tp, 0) + = tsubst_decl (TREE_VEC_ELT (it, 0), args, complain); + DECL_CONTEXT (TREE_VEC_ELT (*tp, 0)) = current_function_decl; + pushdecl (TREE_VEC_ELT (*tp, 0)); + TREE_VEC_ELT (*tp, 1) + = tsubst_expr (TREE_VEC_ELT (it, 1), args, complain, in_decl); + TREE_VEC_ELT (*tp, 2) + = tsubst_expr (TREE_VEC_ELT (it, 2), args, complain, in_decl); + TREE_VEC_ELT (*tp, 3) + = tsubst_expr (TREE_VEC_ELT (it, 3), args, complain, in_decl); + TREE_CHAIN (*tp) = NULL_TREE; + tp = &TREE_CHAIN (*tp); + } + TREE_VEC_ELT (ret, 5) = poplevel (1, 1, 0); + iterator_cache[0] = TREE_PURPOSE (decl); + iterator_cache[1] = ret; } + return build_tree_list (ret, tsubst_omp_clause_decl (TREE_VALUE (decl), + args, complain, + in_decl, NULL)); + } - if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) - r = argument_pack_select_arg (r); - if (!mark_used (r, complain) && !(complain & tf_error)) - return error_mark_node; - return r; - - case CONST_DECL: - { - tree enum_type; - tree v; - - if (DECL_TEMPLATE_PARM_P (t)) - return tsubst_copy (DECL_INITIAL (t), args, complain, in_decl); - if (!uses_template_parms (DECL_CONTEXT (t))) - return t; - - /* Unfortunately, we cannot just call lookup_name here. - Consider: - - template int f() { - enum E { a = I }; - struct S { void g() { E e = a; } }; - }; - - When we instantiate f<7>::S::g(), say, lookup_name is not - clever enough to find f<7>::a. */ - enum_type - = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl, - /*entering_scope=*/0); - - for (v = TYPE_VALUES (enum_type); - v != NULL_TREE; - v = TREE_CHAIN (v)) - if (TREE_PURPOSE (v) == DECL_NAME (t)) - return TREE_VALUE (v); - - /* We didn't find the name. That should never happen; if - name-lookup found it during preliminary parsing, we - should find it again here during instantiation. */ - gcc_unreachable (); - } - return t; + /* Handle an OpenMP array section represented as a TREE_LIST (or + OMP_CLAUSE_DOACROSS_KIND). An OMP_CLAUSE_DOACROSS (with a depend + kind of OMP_CLAUSE_DOACROSS_SINK) can also be represented as a + TREE_LIST. We can handle it exactly the same as an array section + (purpose, value, and a chain), even though the nomenclature + (low_bound, length, etc) is different. */ + if (TREE_CODE (decl) == TREE_LIST) + { + tree low_bound + = tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl); + tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl); + tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain, + in_decl, NULL); + if (TREE_PURPOSE (decl) == low_bound + && TREE_VALUE (decl) == length + && TREE_CHAIN (decl) == chain) + return decl; + tree ret = tree_cons (low_bound, length, chain); + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (ret) + = OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl); + return ret; + } + tree ret = tsubst_expr (decl, args, complain, in_decl); + /* Undo convert_from_reference tsubst_expr could have called. */ + if (decl + && REFERENCE_REF_P (ret) + && !REFERENCE_REF_P (decl)) + ret = TREE_OPERAND (ret, 0); + return ret; +} - case FIELD_DECL: - if (DECL_CONTEXT (t)) - { - tree ctx; +/* Like tsubst_copy, but specifically for OpenMP clauses. */ - ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl, - /*entering_scope=*/1); - if (ctx != DECL_CONTEXT (t)) - { - tree r = lookup_field (ctx, DECL_NAME (t), 0, false); - if (!r) - { - if (complain & tf_error) - error ("using invalid field %qD", t); - return error_mark_node; - } - return r; - } - } +static tree +tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, + tree args, tsubst_flags_t complain, tree in_decl) +{ + tree new_clauses = NULL_TREE, nc, oc; + tree linear_no_step = NULL_TREE; + tree iterator_cache[2] = { NULL_TREE, NULL_TREE }; - return t; + for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc)) + { + nc = copy_node (oc); + OMP_CLAUSE_CHAIN (nc) = new_clauses; + new_clauses = nc; - case VAR_DECL: - case FUNCTION_DECL: - if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) - r = tsubst (t, args, complain, in_decl); - else if (DECL_LOCAL_DECL_P (t)) + switch (OMP_CLAUSE_CODE (nc)) { - /* Local specialization will usually have been created when - we instantiated the DECL_EXPR_DECL. */ - r = retrieve_local_specialization (t); - if (!r) + case OMP_CLAUSE_LASTPRIVATE: + if (OMP_CLAUSE_LASTPRIVATE_STMT (oc)) { - /* We're in a generic lambda referencing a local extern - from an outer block-scope of a non-template. */ - gcc_checking_assert (LAMBDA_FUNCTION_P (current_function_decl)); - r = t; + OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list (); + tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, + complain, in_decl); + OMP_CLAUSE_LASTPRIVATE_STMT (nc) + = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc)); } - } - else if (local_variable_p (t) - && uses_template_parms (DECL_CONTEXT (t))) - { - r = retrieve_local_specialization (t); - if (r == NULL_TREE) + /* FALLTHRU */ + case OMP_CLAUSE_PRIVATE: + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_COPYIN: + case OMP_CLAUSE_COPYPRIVATE: + case OMP_CLAUSE_UNIFORM: + case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: + case OMP_CLAUSE_AFFINITY: + case OMP_CLAUSE_FROM: + case OMP_CLAUSE_TO: + case OMP_CLAUSE_MAP: + case OMP_CLAUSE__CACHE_: + case OMP_CLAUSE_NONTEMPORAL: + case OMP_CLAUSE_USE_DEVICE_PTR: + case OMP_CLAUSE_USE_DEVICE_ADDR: + case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_HAS_DEVICE_ADDR: + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: + OMP_CLAUSE_DECL (nc) + = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain, + in_decl, iterator_cache); + break; + case OMP_CLAUSE_NUM_TEAMS: + if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc)) + OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (nc) + = tsubst_expr (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (oc), args, + complain, in_decl); + /* FALLTHRU */ + case OMP_CLAUSE_TILE: + case OMP_CLAUSE_IF: + case OMP_CLAUSE_NUM_THREADS: + case OMP_CLAUSE_SCHEDULE: + case OMP_CLAUSE_COLLAPSE: + case OMP_CLAUSE_FINAL: + case OMP_CLAUSE_DEVICE: + case OMP_CLAUSE_DIST_SCHEDULE: + case OMP_CLAUSE_THREAD_LIMIT: + case OMP_CLAUSE_SAFELEN: + case OMP_CLAUSE_SIMDLEN: + case OMP_CLAUSE_NUM_TASKS: + case OMP_CLAUSE_GRAINSIZE: + case OMP_CLAUSE_PRIORITY: + case OMP_CLAUSE_ORDERED: + case OMP_CLAUSE_HINT: + case OMP_CLAUSE_FILTER: + case OMP_CLAUSE_NUM_GANGS: + case OMP_CLAUSE_NUM_WORKERS: + case OMP_CLAUSE_VECTOR_LENGTH: + case OMP_CLAUSE_WORKER: + case OMP_CLAUSE_VECTOR: + case OMP_CLAUSE_ASYNC: + case OMP_CLAUSE_WAIT: + case OMP_CLAUSE_DETACH: + OMP_CLAUSE_OPERAND (nc, 0) + = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl); + break; + case OMP_CLAUSE_REDUCTION: + case OMP_CLAUSE_IN_REDUCTION: + case OMP_CLAUSE_TASK_REDUCTION: + if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (oc)) { - /* First try name lookup to find the instantiation. */ - r = lookup_name (DECL_NAME (t)); - if (r) - { - if (!VAR_P (r)) - { - /* During error-recovery we may find a non-variable, - even an OVERLOAD: just bail out and avoid ICEs and - duplicate diagnostics (c++/62207). */ - gcc_assert (seen_error ()); - return error_mark_node; - } - if (!is_capture_proxy (r)) - { - /* Make sure the one we found is the one we want. */ - tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t)); - if (ctx != DECL_CONTEXT (r)) - r = NULL_TREE; - } - } - - if (r) - /* OK */; - else - { - /* This can happen for a variable used in a - late-specified return type of a local lambda, or for a - local static or constant. Building a new VAR_DECL - should be OK in all those cases. */ - r = tsubst_decl (t, args, complain); - if (local_specializations) - /* Avoid infinite recursion (79640). */ - register_local_specialization (r, t); - if (decl_maybe_constant_var_p (r)) - { - /* We can't call cp_finish_decl, so handle the - initializer by hand. */ - tree init = tsubst_init (DECL_INITIAL (t), r, args, - complain, in_decl); - if (!processing_template_decl) - init = maybe_constant_init (init); - if (processing_template_decl - ? potential_constant_expression (init) - : reduced_constant_expression_p (init)) - DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) - = TREE_CONSTANT (r) = true; - DECL_INITIAL (r) = init; - if (tree auto_node = type_uses_auto (TREE_TYPE (r))) - TREE_TYPE (r) - = do_auto_deduction (TREE_TYPE (r), init, auto_node, - complain, adc_variable_type); - } - gcc_assert (cp_unevaluated_operand - || processing_contract_condition - || TREE_STATIC (r) - || decl_constant_var_p (r) - || seen_error ()); - if (!processing_template_decl - && !TREE_STATIC (r)) - r = process_outer_var_ref (r, complain); - } - /* Remember this for subsequent uses. */ - if (local_specializations) - register_local_specialization (r, t); - } - if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) - r = argument_pack_select_arg (r); - } - else - r = t; - if (!mark_used (r, complain)) - return error_mark_node; - return r; - - case NAMESPACE_DECL: - return t; - - case OVERLOAD: - return t; - - case BASELINK: - return tsubst_baselink (t, current_nonlambda_class_type (), - args, complain, in_decl); - - case TEMPLATE_DECL: - if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) - return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)), - args, complain, in_decl); - else if (DECL_FUNCTION_TEMPLATE_P (t) && DECL_MEMBER_TEMPLATE_P (t)) - return tsubst (t, args, complain, in_decl); - else if (DECL_CLASS_SCOPE_P (t) - && uses_template_parms (DECL_CONTEXT (t))) - { - /* Template template argument like the following example need - special treatment: - - template