From patchwork Mon Feb 12 01:21:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 871838 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-473044-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="PjrZIoOc"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zfnvc2JrTz9t3R for ; Mon, 12 Feb 2018 12:22:01 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=YJIBpz6X1nU2AxP4UBMYWQSRluZPOltTKtogn2L2j9rn5w CAXIsCkwMd7xAwjfD2UCP152u/Ffg4yYdQ9TB7EhBP3NXFE20kOPs8C1bHEBF4zR sS1b2+ViKbSxZNFU5AwKMydLjd/9XFItzsvnPflJHrgx1C952cHSAXXbIIY6E= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=6b7Jg5ZhBDaYgv8jG5kniY+1De4=; b=PjrZIoOcdxsE0u5aV6Pi 1uvK0dAn9fh8wB8ZRB+97W/XInrYVJ+7E8R0hmWPfbHvWx0HLMVcUZldJZob/4g3 iqll0thmIQZqKz8Rcz80Z5RHVE1rmCXqqBkCI9FE1JLWD//lgW5CwHhu4zqLozHO +2VxuSq/4dr4pebXlGxz7Vw= Received: (qmail 21115 invoked by alias); 12 Feb 2018 01:21:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 20823 invoked by uid 89); 12 Feb 2018 01:21:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=focusing, 0102, ppd X-HELO: mail-it0-f42.google.com Received: from mail-it0-f42.google.com (HELO mail-it0-f42.google.com) (209.85.214.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 12 Feb 2018 01:21:50 +0000 Received: by mail-it0-f42.google.com with SMTP id e1so4732230ita.0 for ; Sun, 11 Feb 2018 17:21:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=TRb+OV2+53dz3g//eCQAkCdmfOCEVDQuYGIEn3iMQW8=; b=No/K1okJDQtCj1bkLGSwKYYou+EfKVVVSYHlbkSaPlNrPRItnUMiLL8sPW+2s37pPL GGkteALCgbmSLfbmBsfEpws2ghZ0veMOmHQ/xQmd9KiCbYyjVc5/of4EceW1lE3e/PCX eNEm4yFH13DRhTzxg4UU2LklsvD/ryTMrET/VeJf5qCeolat0TJptwfr0BZBWV9x1qzh hU4TkbkdAFsvSTFwbQSGuCllhRPDaJO52huYKGsD/uKN5wcyzO0jiJ6xVp+G2HJ4Em7H OebgWatrANWv0QMr0OXMNsGUBmnk07syXcMF3YEBfZO8eieMWv4WF/Ana8UDancUY3A6 h6lw== X-Gm-Message-State: APf1xPCapNcCSVPaOaVyUm3j7Txun1OCVa3G2htR1ysvhbNUfsfJ5ygS 526g3HkksHg6n9tKqDjubiIIxOtA4eliwngVh0RuedNW X-Google-Smtp-Source: AH8x2259bGao50lpDRZq4JgJTV9Hs7YIOWeKxaJMP7CqrRUOsqcZbfp1sy180ED4dwdcx6OjgR1CmlsZNEdyU49QN6c= X-Received: by 10.36.0.23 with SMTP id 23mr3676752ita.53.1518398508286; Sun, 11 Feb 2018 17:21:48 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.17.206 with HTTP; Sun, 11 Feb 2018 17:21:27 -0800 (PST) From: Jason Merrill Date: Sun, 11 Feb 2018 20:21:27 -0500 Message-ID: Subject: C++ PATCH for c++/84036, ICE with variadic lambda capture To: gcc-patches List X-IsSubscribed: yes The old lambda model handled variadic capture by focusing on the FIELD_DECL rather than trying to map between capture proxies. The new model relies more on capture proxies, so it makes sense to use them more for variadic capture as well. So with this patch we treat a variadic capture proxy as a pack, rather than the field. Tested x86_64-pc-linux-gnu, applying to trunk. commit d6e4c6a3af04599f408b04e630b853d5a907beac Author: Jason Merrill Date: Thu Feb 8 16:18:33 2018 -0500 PR c++/84036 - ICE with variadic capture. Handle variadic capture proxies more like non-variadic. * lambda.c (build_capture_proxy): Remove workaround. * pt.c (find_parameter_packs_r): The proxy is a pack. (instantiate_class_template_1): Remove dead lambda code. (extract_fnparm_pack): Don't make_pack_expansion. (extract_locals_r): Don't strip a pack expansion. (tsubst_pack_expansion): Handle proxy packs. Use PACK_EXPANSION_EXTRA_ARGS less. (tsubst_decl) [FIELD_DECL]: Don't register_specialization. (tsubst_copy) [FIELD_DECL]: Don't retrieve*_specialization. [VAR_DECL]: Handle ARGUMENT_PACK_SELECT. (tsubst_expr) [DECL_EXPR]: Handle proxy packs. (tsubst_copy_and_build) [VAR_DECL]: Handle proxy packs normally. diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 2545eae9ce9..6b5bd800741 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -455,19 +455,11 @@ build_capture_proxy (tree member, tree init) STRIP_NOPS (init); } - if (TREE_CODE (init) == COMPONENT_REF) - /* We're capturing a capture of a function parameter pack, and have - lost track of the original variable. It's not important to have - DECL_CAPTURED_VARIABLE in this case, since a function parameter pack - isn't a constant variable, so don't bother trying to set it. */; - else - { - gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL); - while (is_normal_capture_proxy (init)) - init = DECL_CAPTURED_VARIABLE (init); - retrofit_lang_decl (var); - DECL_CAPTURED_VARIABLE (var) = init; - } + gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL); + while (is_normal_capture_proxy (init)) + init = DECL_CAPTURED_VARIABLE (init); + retrofit_lang_decl (var); + DECL_CAPTURED_VARIABLE (var) = init; } if (name == this_identifier) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 281604594ad..b58c60f0dcb 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3561,14 +3561,13 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) /* Look through a lambda capture proxy to the field pack. */ case VAR_DECL: - if (DECL_HAS_VALUE_EXPR_P (t)) - { - tree v = DECL_VALUE_EXPR (t); - cp_walk_tree (&v, - &find_parameter_packs_r, - ppd, ppd->visited); - *walk_subtrees = 0; - } + if (DECL_PACK_P (t)) + { + /* We don't want to walk into the type of a variadic capture proxy, + because we don't want to see the type parameter pack. */ + *walk_subtrees = 0; + parameter_pack_p = true; + } else if (variable_template_specialization_p (t)) { cp_walk_tree (&DECL_TI_ARGS (t), @@ -10838,42 +10837,6 @@ instantiate_class_template_1 (tree type) c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings; } - if (tree expr = CLASSTYPE_LAMBDA_EXPR (type)) - { - tree decl = lambda_function (type); - if (decl) - { - if (cxx_dialect >= cxx17) - CLASSTYPE_LITERAL_P (type) = true; - - if (!DECL_TEMPLATE_INFO (decl) - || DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) != decl) - { - /* Set function_depth to avoid garbage collection. */ - ++function_depth; - instantiate_decl (decl, /*defer_ok=*/false, false); - --function_depth; - } - - /* We need to instantiate the capture list from the template - after we've instantiated the closure members, but before we - consider adding the conversion op. Also keep any captures - that may have been added during instantiation of the op(). */ - tree tmpl_expr = CLASSTYPE_LAMBDA_EXPR (pattern); - tree tmpl_cap - = tsubst_copy_and_build (LAMBDA_EXPR_CAPTURE_LIST (tmpl_expr), - args, tf_warning_or_error, NULL_TREE, - false, false); - - LAMBDA_EXPR_CAPTURE_LIST (expr) - = chainon (tmpl_cap, nreverse (LAMBDA_EXPR_CAPTURE_LIST (expr))); - - maybe_add_lambda_conv_op (type); - } - else - gcc_assert (errorcount); - } - /* Set the file and line number information to whatever is given for the class itself. This puts error messages involving generated implicit functions at a predictable point, and the same point @@ -10970,12 +10933,7 @@ extract_fnparm_pack (tree tmpl_parm, tree *spec_p) parmvec = make_tree_vec (len); spec_parm = *spec_p; for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm)) - { - tree elt = spec_parm; - if (DECL_PACK_P (elt)) - elt = make_pack_expansion (elt); - TREE_VEC_ELT (parmvec, i) = elt; - } + TREE_VEC_ELT (parmvec, i) = spec_parm; /* Build the argument packs. */ SET_ARGUMENT_PACK_ARGS (argpack, parmvec); @@ -11125,6 +11083,7 @@ gen_elem_of_pack_expansion_instantiation (tree pattern, /* Select the Ith argument from the pack. */ if (TREE_CODE (parm) == PARM_DECL + || VAR_P (parm) || TREE_CODE (parm) == FIELD_DECL) { if (index == 0) @@ -11429,8 +11388,7 @@ extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data) /* Pull out the actual PARM_DECL for the partial instantiation. */ tree args = ARGUMENT_PACK_ARGS (spec); gcc_assert (TREE_VEC_LENGTH (args) == 1); - tree arg = TREE_VEC_ELT (args, 0); - spec = PACK_EXPANSION_PATTERN (arg); + spec = TREE_VEC_ELT (args, 0); } *extra = tree_cons (*tp, spec, *extra); } @@ -11551,8 +11509,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, where it isn't expected). */ unsubstituted_fn_pack = true; } - else if (TREE_CODE (parm_pack) == FIELD_DECL) - arg_pack = tsubst_copy (parm_pack, args, complain, in_decl); + else if (is_normal_capture_proxy (parm_pack)) + { + arg_pack = retrieve_local_specialization (parm_pack); + if (argument_pack_element_is_expansion_p (arg_pack, 0)) + unsubstituted_fn_pack = true; + } else { int idx; @@ -11647,15 +11609,14 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, /* We cannot expand this expansion expression, because we don't have all of the argument packs we need. */ - if (use_pack_expansion_extra_args_p (packs, len, (unsubstituted_packs - || unsubstituted_fn_pack))) + if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs)) { /* We got some full packs, but we can't substitute them in until we have values for all the packs. So remember these until then. */ t = make_pack_expansion (pattern, complain); tree extra = args; - if (unsubstituted_fn_pack) + if (local_specializations) if (tree locals = extract_local_specs (pattern)) extra = tree_cons (NULL_TREE, extra, locals); PACK_EXPANSION_EXTRA_ARGS (t) = extra; @@ -11713,6 +11674,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, tree parm = TREE_PURPOSE (pack); if (TREE_CODE (parm) == PARM_DECL + || VAR_P (parm) || TREE_CODE (parm) == FIELD_DECL) register_local_specialization (TREE_TYPE (pack), parm); else @@ -12866,9 +12828,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (PACK_EXPANSION_P (TREE_TYPE (t))) { /* This field is a lambda capture pack. Return a TREE_VEC of - the expanded fields to instantiate_class_template_1 and - store them in the specializations hash table as a - NONTYPE_ARGUMENT_PACK so that tsubst_copy can find them. */ + the expanded fields to instantiate_class_template_1. */ expanded_types = tsubst_pack_expansion (TREE_TYPE (t), args, complain, in_decl); if (TREE_CODE (expanded_types) == TREE_VEC) @@ -12930,12 +12890,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) } if (vec) - { - r = vec; - tree pack = make_node (NONTYPE_ARGUMENT_PACK); - SET_ARGUMENT_PACK_ARGS (pack, vec); - register_specialization (pack, t, args, false, 0); - } + r = vec; } break; @@ -14827,31 +14782,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) return t; case FIELD_DECL: - if (PACK_EXPANSION_P (TREE_TYPE (t))) - { - /* Check for a local specialization set up by - tsubst_pack_expansion. */ - if (tree r = retrieve_local_specialization (t)) - { - if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) - r = ARGUMENT_PACK_SELECT_ARG (r); - return r; - } - - /* When retrieving a capture pack from a generic lambda, remove the - lambda call op's own template argument list from ARGS. Only the - template arguments active for the closure type should be used to - retrieve the pack specialization. */ - if (LAMBDA_FUNCTION_P (current_function_decl) - && (template_class_depth (DECL_CONTEXT (t)) - != TMPL_ARGS_DEPTH (args))) - args = strip_innermost_template_args (args, 1); - - /* Otherwise return the full NONTYPE_ARGUMENT_PACK that - tsubst_decl put in the hash table. */ - return retrieve_specialization (t, args, 0); - } - if (DECL_CONTEXT (t)) { tree ctx; @@ -14935,6 +14865,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (local_specializations) register_local_specialization (r, t); } + if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) + r = ARGUMENT_PACK_SELECT_ARG (r); } else r = t; @@ -16104,20 +16036,24 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, else finish_local_using_decl (decl, scope, name); } - else if (DECL_PACK_P (decl)) - { - /* Don't build up decls for a variadic capture proxy, we'll - instantiate the elements directly as needed. */ - break; - } else if (is_capture_proxy (decl) && !DECL_TEMPLATE_INSTANTIATION (current_function_decl)) { /* We're in tsubst_lambda_expr, we've already inserted a new capture proxy, so look it up and register it. */ - tree inst = lookup_name_real (DECL_NAME (decl), 0, 0, - /*block_p=*/true, 0, LOOKUP_HIDDEN); - gcc_assert (inst != decl && is_capture_proxy (inst)); + tree inst; + if (DECL_PACK_P (decl)) + { + inst = (retrieve_local_specialization + (DECL_CAPTURED_VARIABLE (decl))); + gcc_assert (TREE_CODE (inst) == NONTYPE_ARGUMENT_PACK); + } + else + { + inst = lookup_name_real (DECL_NAME (decl), 0, 0, + /*block_p=*/true, 0, LOOKUP_HIDDEN); + gcc_assert (inst != decl && is_capture_proxy (inst)); + } register_local_specialization (inst, decl); break; } @@ -18265,14 +18201,6 @@ tsubst_copy_and_build (tree t, case VAR_DECL: if (!args) RETURN (t); - else if (DECL_PACK_P (t)) - { - /* We don't build decls for an instantiation of a - variadic capture proxy, we instantiate the elements - when needed. */ - gcc_assert (DECL_HAS_VALUE_EXPR_P (t)); - return RECUR (DECL_VALUE_EXPR (t)); - } /* Fall through */ case PARM_DECL: diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C new file mode 100644 index 00000000000..01ef7c6e220 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C @@ -0,0 +1,21 @@ +// PR c++/84036 +// { dg-do compile { target c++14 } } + +template < typename... T > void sink(T ...){} + +template < typename T > +auto f(T){ + auto l = [](auto ... i){ + [i ...]{ + sink(i...); + [=]{ sink(i ...); }(); + }(); + }; + l(); + l(42); + l(0.1,0.2); +} + +int main(){ + f(0); +}