From patchwork Wed Sep 16 14:19:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1365351 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=TFh53nRc; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Bs2KL5w9gz9sSn for ; Thu, 17 Sep 2020 00:19:17 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 824063986837; Wed, 16 Sep 2020 14:19:13 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qv1-xf2b.google.com (mail-qv1-xf2b.google.com [IPv6:2607:f8b0:4864:20::f2b]) by sourceware.org (Postfix) with ESMTPS id 72097386F01B for ; Wed, 16 Sep 2020 14:19:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 72097386F01B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qv1-xf2b.google.com with SMTP id z18so3590023qvp.6 for ; Wed, 16 Sep 2020 07:19:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=Xco2JhnESwt7TrTlVd+Ww2zqypE8bO7G9gMtyPJ1I8U=; b=TFh53nRcwcZmCK8pO+XdrYAbLIq8Va32jh/6R70VdpBHInvQm9DS7es4ybTiwy/41F J4EN9k4aujdznOxYkgwuE91bhQaJQ4p2tEIk/wTLHcz3FV4Iov3F9lijrqzx7IEsPhUm ejGvqRSSpFwjaTzWYmXEt/VjgoCY2ws2pomXGjJBMzFu0NQGK9Ce+sb3WP3F+5QFoYaU 9zdxRffAd+g1Ehc8oWAo8IDLeuL1X/wQBUxV1l3EzXDSz5FJKiZ2f9h9P+c6cOtEGFT1 adVfbZl61UPx2ENOVb+PGD1KcfhnepOH692mIYHO9bRtOI+5Ehw2zCpvrv2eg4bSSkX8 u3Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=Xco2JhnESwt7TrTlVd+Ww2zqypE8bO7G9gMtyPJ1I8U=; b=tZfvhD4N0Djlp2H3535NCT65wK1oZiY+CntA9D8G1CDKlJrLsSk9uxmxOTqK50sShF JvBzbdHFednbqX7VK157SmVAxdXC0XSDyA67+95TtHYXQ4BZAu4/pVhu4nZd+p1s3JrC jzZ2XoDM/73Xs51SujbU+6wUgOUZbQ5Ntfy0stswCsYdlspHg+dIC/wW4lyH8h2hpGGK b5i4/M7vLOEL1bVqH57mEzF7Jog9YWwEf23bT2BlsUyteWAybop6TUD4bXXgxb01g/b7 sMcMtaPu75Ny1j6k+ksgkm1XizSUWzKknba5RTg2YDld21CC+MAOzJK2TIwlNERbPY2z UzOA== X-Gm-Message-State: AOAM533EQGDMDtvnzHQ8lZr/6ZBLli4dS8tBEM+EMc3fIlZ+xx4gfBoD MtaEqVRQsmeF9D7VGjnlM5I= X-Google-Smtp-Source: ABdhPJxX5ByVoAdJPScKgv6n+A2SWv9PZBAUA7WIlCwom+3K+RH7M+pQ5fRds3GsyEWnf7jTZU8EQQ== X-Received: by 2002:a0c:e152:: with SMTP id c18mr7030708qvl.41.1600265943875; Wed, 16 Sep 2020 07:19:03 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a8:1102:3530:46e6:f8c5:7c9e? ([2620:10d:c091:480::1:c8a7]) by smtp.googlemail.com with ESMTPSA id g19sm18900015qka.84.2020.09.16.07.19.02 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 16 Sep 2020 07:19:02 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: c++: Break out actual instantiation from instantiate_decl Message-ID: <36ebaa46-0a54-bab1-d489-2702257da2b9@acm.org> Date: Wed, 16 Sep 2020 10:19:01 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This refactors instantiate_decl, breaking out the actual instantiation work to instantiate_body. That'll allow me to address the OMP UDR issue, but it also means we have slightly neater code in instantiate_decl anyway. gcc/cp/ * pt.c (instantiate_body): New, broken out of .. (instantiate_decl): ... here. Call it. pushing to trunk diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c index 1aea105edd5..e8aa950b8fa 100644 --- c/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -25447,6 +25447,158 @@ register_parameter_specializations (tree pattern, tree inst) gcc_assert (!spec_parm); } +/* Instantiate the body of D using PATTERN with ARGS. We have + already determined PATTERN is the correct template to use. */ + +static void +instantiate_body (tree pattern, tree args, tree d) +{ + gcc_checking_assert (TREE_CODE (pattern) == TEMPLATE_DECL); + + tree td = pattern; + tree code_pattern = DECL_TEMPLATE_RESULT (td); + + tree fn_context = decl_function_context (d); + if (LAMBDA_FUNCTION_P (d)) + /* tsubst_lambda_expr resolved any references to enclosing functions. */ + fn_context = NULL_TREE; + bool nested = current_function_decl != NULL_TREE; + bool push_to_top = !(nested && fn_context == current_function_decl); + + vec omp_privatization_save; + if (nested) + save_omp_privatization_clauses (omp_privatization_save); + + if (push_to_top) + push_to_top_level (); + else + { + gcc_assert (!processing_template_decl); + push_function_context (); + cp_unevaluated_operand = 0; + c_inhibit_evaluation_warnings = 0; + } + + if (VAR_P (d)) + { + /* The variable might be a lambda's extra scope, and that + lambda's visibility depends on D's. */ + maybe_commonize_var (d); + determine_visibility (d); + } + + /* Mark D as instantiated so that recursive calls to + instantiate_decl do not try to instantiate it again. */ + DECL_TEMPLATE_INSTANTIATED (d) = 1; + + /* Regenerate the declaration in case the template has been modified + by a subsequent redeclaration. */ + regenerate_decl_from_template (d, td, args); + + /* We already set the file and line above. Reset them now in case + they changed as a result of calling regenerate_decl_from_template. */ + input_location = DECL_SOURCE_LOCATION (d); + + if (VAR_P (d)) + { + tree init; + bool const_init = false; + + /* Clear out DECL_RTL; whatever was there before may not be right + since we've reset the type of the declaration. */ + SET_DECL_RTL (d, NULL); + DECL_IN_AGGR_P (d) = 0; + + /* The initializer is placed in DECL_INITIAL by + regenerate_decl_from_template so we don't need to + push/pop_access_scope again here. Pull it out so that + cp_finish_decl can process it. */ + init = DECL_INITIAL (d); + DECL_INITIAL (d) = NULL_TREE; + DECL_INITIALIZED_P (d) = 0; + + /* Clear DECL_EXTERNAL so that cp_finish_decl will process the + initializer. That function will defer actual emission until + we have a chance to determine linkage. */ + DECL_EXTERNAL (d) = 0; + + /* Enter the scope of D so that access-checking works correctly. */ + bool enter_context = DECL_CLASS_SCOPE_P (d); + if (enter_context) + push_nested_class (DECL_CONTEXT (d)); + + const_init = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern); + cp_finish_decl (d, init, const_init, NULL_TREE, 0); + + if (enter_context) + pop_nested_class (); + } + else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern)) + synthesize_method (d); + else if (TREE_CODE (d) == FUNCTION_DECL) + { + /* Set up the list of local specializations. */ + local_specialization_stack lss (push_to_top ? lss_blank : lss_copy); + tree block = NULL_TREE; + + /* Set up context. */ + if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern) + && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL) + block = push_stmt_list (); + else + start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED); + + perform_instantiation_time_access_checks (code_pattern, args); + + /* Create substitution entries for the parameters. */ + register_parameter_specializations (code_pattern, d); + + /* Substitute into the body of the function. */ + if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)) + tsubst_omp_udr (DECL_SAVED_TREE (code_pattern), args, + tf_warning_or_error, DECL_TI_TEMPLATE (d)); + else + { + tsubst_expr (DECL_SAVED_TREE (code_pattern), args, + tf_warning_or_error, DECL_TI_TEMPLATE (d), + /*integral_constant_expression_p=*/false); + + /* Set the current input_location to the end of the function + so that finish_function knows where we are. */ + input_location + = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus; + + /* Remember if we saw an infinite loop in the template. */ + current_function_infinite_loop + = DECL_STRUCT_FUNCTION (code_pattern)->language->infinite_loop; + } + + /* Finish the function. */ + if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern) + && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL) + DECL_SAVED_TREE (d) = pop_stmt_list (block); + else + { + d = finish_function (/*inline_p=*/false); + expand_or_defer_fn (d); + } + + if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)) + cp_check_omp_declare_reduction (d); + } + + /* We're not deferring instantiation any more. */ + TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0; + + if (push_to_top) + pop_from_top_level (); + else + pop_function_context (); + + if (nested) + restore_omp_privatization_clauses (omp_privatization_save); +} + /* Produce the definition of D, a _DECL generated from a template. If DEFER_OK is true, then we don't have to actually do the instantiation now; we just have to do it sometime. Normally it is @@ -25684,162 +25836,19 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p) /* If we're in unevaluated context, we just wanted to get the constant value; this isn't an odr use, so don't queue a full instantiation. */ - if (cp_unevaluated_operand != 0) - goto out; - /* ??? Historically, we have instantiated inline functions, even - when marked as "extern template". */ - if (!(external_p && VAR_P (d))) + if (!cp_unevaluated_operand + /* ??? Historically, we have instantiated inline functions, even + when marked as "extern template". */ + && !(external_p && VAR_P (d))) add_pending_template (d); - goto out; } - - bool push_to_top, nested; - tree fn_context; - fn_context = decl_function_context (d); - if (LAMBDA_FUNCTION_P (d)) - /* tsubst_lambda_expr resolved any references to enclosing functions. */ - fn_context = NULL_TREE; - nested = current_function_decl != NULL_TREE; - push_to_top = !(nested && fn_context == current_function_decl); - - vec omp_privatization_save; - if (nested) - save_omp_privatization_clauses (omp_privatization_save); - - if (push_to_top) - push_to_top_level (); else { - gcc_assert (!processing_template_decl); - push_function_context (); - cp_unevaluated_operand = 0; - c_inhibit_evaluation_warnings = 0; - } - - if (VAR_P (d)) - { - /* The variable might be a lambda's extra scope, and that - lambda's visibility depends on D's. */ - maybe_commonize_var (d); - determine_visibility (d); - } - - /* Mark D as instantiated so that recursive calls to - instantiate_decl do not try to instantiate it again. */ - DECL_TEMPLATE_INSTANTIATED (d) = 1; - - /* Regenerate the declaration in case the template has been modified - by a subsequent redeclaration. */ - regenerate_decl_from_template (d, td, args); - - /* We already set the file and line above. Reset them now in case - they changed as a result of calling regenerate_decl_from_template. */ - input_location = DECL_SOURCE_LOCATION (d); - - if (VAR_P (d)) - { - tree init; - bool const_init = false; - - /* Clear out DECL_RTL; whatever was there before may not be right - since we've reset the type of the declaration. */ - SET_DECL_RTL (d, NULL); - DECL_IN_AGGR_P (d) = 0; - - /* The initializer is placed in DECL_INITIAL by - regenerate_decl_from_template so we don't need to - push/pop_access_scope again here. Pull it out so that - cp_finish_decl can process it. */ - init = DECL_INITIAL (d); - DECL_INITIAL (d) = NULL_TREE; - DECL_INITIALIZED_P (d) = 0; - - /* Clear DECL_EXTERNAL so that cp_finish_decl will process the - initializer. That function will defer actual emission until - we have a chance to determine linkage. */ - DECL_EXTERNAL (d) = 0; - - /* Enter the scope of D so that access-checking works correctly. */ - bool enter_context = DECL_CLASS_SCOPE_P (d); - if (enter_context) - push_nested_class (DECL_CONTEXT (d)); - - const_init = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern); - cp_finish_decl (d, init, const_init, NULL_TREE, 0); - - if (enter_context) - pop_nested_class (); - if (variable_template_p (gen_tmpl)) note_variable_template_instantiation (d); - } - else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern)) - synthesize_method (d); - else if (TREE_CODE (d) == FUNCTION_DECL) - { - /* Set up the list of local specializations. */ - local_specialization_stack lss (push_to_top ? lss_blank : lss_copy); - tree block = NULL_TREE; - - /* Set up context. */ - if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern) - && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL) - block = push_stmt_list (); - else - start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED); - - perform_instantiation_time_access_checks (DECL_TEMPLATE_RESULT (td), - args); - - /* Create substitution entries for the parameters. */ - register_parameter_specializations (code_pattern, d); - - /* Substitute into the body of the function. */ - if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)) - tsubst_omp_udr (DECL_SAVED_TREE (code_pattern), args, - tf_warning_or_error, tmpl); - else - { - tsubst_expr (DECL_SAVED_TREE (code_pattern), args, - tf_warning_or_error, tmpl, - /*integral_constant_expression_p=*/false); - - /* Set the current input_location to the end of the function - so that finish_function knows where we are. */ - input_location - = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus; - - /* Remember if we saw an infinite loop in the template. */ - current_function_infinite_loop - = DECL_STRUCT_FUNCTION (code_pattern)->language->infinite_loop; - } - - /* Finish the function. */ - if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern) - && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL) - DECL_SAVED_TREE (d) = pop_stmt_list (block); - else - { - d = finish_function (/*inline_p=*/false); - expand_or_defer_fn (d); - } - - if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)) - cp_check_omp_declare_reduction (d); + instantiate_body (td, args, d); } - /* We're not deferring instantiation any more. */ - TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0; - - if (push_to_top) - pop_from_top_level (); - else - pop_function_context (); - - if (nested) - restore_omp_privatization_clauses (omp_privatization_save); - -out: pop_deferring_access_checks (); timevar_pop (TV_TEMPLATE_INST); pop_tinst_level ();