From patchwork Tue Feb 13 14:21:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 872868 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-473157-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="wQiZ1qWR"; 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 3zgl8f5nXCz9t5w for ; Wed, 14 Feb 2018 01:21:37 +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=KtTOrIyYJ/UFhzFSTClZJUP74HpnR8drQpJmIwMrkNvmZm akWHcZ2xfVkzhR+2YRw7VwRC1n2yf22Dh70GqDXLf42sK7YjOtAt/M2OXtAdv03i I7JyUf+eaRcmHREsBLo5R61QtSkH5Z+RO68no5MyQk37G2t3UUzF0UxYIDBmo= 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=bxVdvPCX/wf92DYh0UFS6NfLp28=; b=wQiZ1qWRNQX7uJAwxlXm yiikQOGibp7d7ts7WC+fxxA/lz6m1oIXvLDwa9wNMkqNPF6X12zyYeHMvRSAV+nc poNTEEdsWlKmV4NZMFaYlrlJysVF+zv0TInx3cxkfNQpVFY6kCHm+rJTNy1WFpYV Lt25S2YtPOIRVJgNo6wztfE= Received: (qmail 22377 invoked by alias); 13 Feb 2018 14:21:30 -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 22362 invoked by uid 89); 13 Feb 2018 14:21:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.4 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=HX-Received:10.107.56.135 X-HELO: mail-io0-f172.google.com Received: from mail-io0-f172.google.com (HELO mail-io0-f172.google.com) (209.85.223.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 13 Feb 2018 14:21:28 +0000 Received: by mail-io0-f172.google.com with SMTP id 72so21439491iom.10 for ; Tue, 13 Feb 2018 06:21:28 -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=ejKA/20VzSSl4CwJhsmnSdwIvj6JkmA5lfuh4dDt7yA=; b=ukZhh/OwKqPj/DJYXtPp0zYxjopfe+DumA8pW8xMQb+Nxq42Oe7LkCJ8/aI73f4DUa f2Jbt9RrhF6ePyrYfVyQwXZoXbR9wQWYy5Mp9Hkavq6FwA5UrIRSDL2PuqY+frs1W7o5 /3Vhkmuj2ZPrq7v8fGY5RYPREjQjdDYXaOkLaaDziiyClbuDJciXUsSesV0KtcPjN3zr vW9tS/iph2lXHt3xi+ntj7dRVHyrSpgnsCtuqWtGU1Y2EsvevYRhp1jqGKt0zFqv+soU egwntRNY4Gtfmeiv7y3GNGV8QzyyWvidEmydsNDuwOZH2rXs5SLkhyHP8m/wq+bkNb0o la4g== X-Gm-Message-State: APf1xPDd4yKlH+Cpu3Q77ZIaJXxWyulDCzq/ei+uobJYwtVKWJEm9GG0 wvCENTAwTaJcAQbbx4zcyvn7KyUNziQgwbBDyoc3i/EAB7o= X-Google-Smtp-Source: AH8x226OGOLGtxFUIFMF4obC9My95GAn4Sbq9P37pItHr93FA87TAWkG23bP2F6UXu9r0hA+Hz7NqXFPa6KcG4LdVI4= X-Received: by 10.107.56.135 with SMTP id f129mr1465067ioa.208.1518531686320; Tue, 13 Feb 2018 06:21:26 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.17.206 with HTTP; Tue, 13 Feb 2018 06:21:05 -0800 (PST) From: Jason Merrill Date: Tue, 13 Feb 2018 09:21:05 -0500 Message-ID: Subject: C++ PATCH for more variadic capture issues To: gcc-patches List X-IsSubscribed: yes This patch fixes two issues: 1) We were failing to capture a parameter pack used by a pack expansion which needs to use PACK_EXPANSION_EXTRA_ARGS, because in that case we defer actual substitution until we have all the arguments we need. But by that time we're inside an instantiation of the lambda op(), and it's too late to capture anything. So we need to force lambda capture while we're packing up the arguments we'll need for that later substitution. 2) While looking at that, I noticed that although we recently started to support implicit capture within a pack expansion, we didn't support explicit capture. Tested x86_64-pc-linux-gnu, applying to trunk. After this patch, the Boost.Hana testsuite also passes again. commit 6383f88febfbe13aef71a9da2f678ecae344d1f2 Author: Jason Merrill Date: Mon Feb 12 10:26:53 2018 -0500 Fix more variadic capture issues. * pt.c (find_parameter_packs_r): Also look at explicit captures. (check_for_bare_parameter_packs): Check current_class_type for lambda context. (extract_locals_r): Handle seeing a full instantiation of a pack. (tsubst_pack_expansion): Likewise. Force lambda capture. * parser.c (cp_parser_lambda_introducer): Don't check_for_bare_parameter_packs. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9a05e4fc812..81c6f0128e6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -10412,8 +10412,6 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) cp_lexer_consume_token (parser->lexer); capture_init_expr = make_pack_expansion (capture_init_expr); } - else - check_for_bare_parameter_packs (capture_init_expr); } if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a83b7073d20..02d448e99b6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3587,7 +3587,6 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) } break; - /* Look through a lambda capture proxy to the field pack. */ case VAR_DECL: if (DECL_PACK_P (t)) { @@ -3707,6 +3706,12 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) case LAMBDA_EXPR: { + /* Look at explicit captures. */ + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); + cap; cap = TREE_CHAIN (cap)) + cp_walk_tree (&TREE_VALUE (cap), &find_parameter_packs_r, ppd, + ppd->visited); + /* Since we defer implicit capture, look in the body as well. */ tree fn = lambda_function (t); cp_walk_tree (&DECL_SAVED_TREE (fn), &find_parameter_packs_r, ppd, ppd->visited); @@ -3907,7 +3912,7 @@ check_for_bare_parameter_packs (tree t) return false; /* A lambda might use a parameter pack from the containing context. */ - if (current_function_decl && LAMBDA_FUNCTION_P (current_function_decl)) + if (current_class_type && LAMBDA_TYPE_P (current_class_type)) return false; if (TREE_CODE (t) == TYPE_DECL) @@ -11410,30 +11415,72 @@ tsubst_binary_right_fold (tree t, tree args, tsubst_flags_t complain, /* Walk through the pattern of a pack expansion, adding everything in local_specializations to a list. */ +struct el_data +{ + tree extra; + tsubst_flags_t complain; +}; static tree -extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data) +extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data_) { - tree *extra = reinterpret_cast(data); + el_data &data = *reinterpret_cast(data_); + tree *extra = &data.extra; + tsubst_flags_t complain = data.complain; if (tree spec = retrieve_local_specialization (*tp)) { if (TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK) { - /* Pull out the actual PARM_DECL for the partial instantiation. */ + /* Maybe pull out the PARM_DECL for a 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); + if (TREE_VEC_LENGTH (args) == 1) + { + tree elt = TREE_VEC_ELT (args, 0); + if (PACK_EXPANSION_P (elt)) + elt = PACK_EXPANSION_PATTERN (elt); + if (DECL_PACK_P (elt)) + spec = elt; + } + if (TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK) + { + /* Handle lambda capture here, since we aren't doing any + substitution now, and so tsubst_copy won't call + process_outer_var_ref. */ + tree args = ARGUMENT_PACK_ARGS (spec); + int len = TREE_VEC_LENGTH (args); + for (int i = 0; i < len; ++i) + { + tree arg = TREE_VEC_ELT (args, i); + tree carg = arg; + if (outer_automatic_var_p (arg)) + carg = process_outer_var_ref (arg, complain); + if (carg != arg) + { + /* Make a new NONTYPE_ARGUMENT_PACK of the capture + proxies. */ + if (i == 0) + { + spec = copy_node (spec); + args = copy_node (args); + SET_ARGUMENT_PACK_ARGS (spec, args); + register_local_specialization (spec, *tp); + } + TREE_VEC_ELT (args, i) = carg; + } + } + } } + if (outer_automatic_var_p (spec)) + spec = process_outer_var_ref (spec, complain); *extra = tree_cons (*tp, spec, *extra); } return NULL_TREE; } static tree -extract_local_specs (tree pattern) +extract_local_specs (tree pattern, tsubst_flags_t complain) { - tree extra = NULL_TREE; - cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &extra); - return extra; + el_data data = { NULL_TREE, complain }; + cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &data); + return data.extra; } /* Substitute ARGS into T, which is an pack expansion @@ -11468,8 +11515,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, extract_local_specs; map from the general template to our local context. */ tree gen = TREE_PURPOSE (elt); - tree partial = TREE_VALUE (elt); - tree inst = retrieve_local_specialization (partial); + tree inst = TREE_VALUE (elt); + if (DECL_PACK_P (inst)) + inst = retrieve_local_specialization (inst); + /* else inst is already a full instantiation of the pack. */ register_local_specialization (inst, gen); } gcc_assert (!TREE_PURPOSE (extra)); @@ -11651,7 +11700,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, t = make_pack_expansion (pattern, complain); tree extra = args; if (local_specializations) - if (tree locals = extract_local_specs (pattern)) + if (tree locals = extract_local_specs (pattern, complain)) extra = tree_cons (NULL_TREE, extra, locals); PACK_EXPANSION_EXTRA_ARGS (t) = extra; return t; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C index 5196a18b5f1..97f64cd761a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C @@ -11,6 +11,7 @@ template void print_all(const T&... t) { accept_all([&]()->int { print(t); return 0; }...); + accept_all([&t]()->int { print(t); return 0; }...); } int main() diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C new file mode 100644 index 00000000000..811332040fa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C @@ -0,0 +1,16 @@ +// { dg-do compile { target c++14 } } + +template < typename... T > void sink(T ...){} + +template < typename... T > +auto f(T... t){ + [=](auto ... j){ + sink((t + j)...); + }(t...); +} + +int main(){ + f(0); + f(); + f(0.1,0.2); +}