From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 77714 invoked by alias); 20 Jan 2017 00:32:51 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 76624 invoked by uid 89); 20 Jan 2017 00:32:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-HELO: mail-wm0-f68.google.com Received: from mail-wm0-f68.google.com (HELO mail-wm0-f68.google.com) (74.125.82.68) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 20 Jan 2017 00:32:38 +0000 Received: by mail-wm0-f68.google.com with SMTP id r144so2909976wme.0; Thu, 19 Jan 2017 16:32:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=wPCnowbvcBcXMZew53LeDPtHF2z4hGgxOD8bELVwVMA=; b=r2TZ211uTycGSXIUxUj5FpRZnRJ/IBWiYqgKF+wwuadzgJLdz3kOrsNVlWspHacr8+ HZxZ2hEztpVqZapH1t6yfmW+eyA0A8tRkZTb0LViH1yI6fYjdsj74n53uUTWFCes8BnD c/rYEq1uqJd5hvxkXxSqiXrn6y25JCZ1FYoEd+fAq6RYsvFqBJUQeZsS+pUg13/cyJfh 2emGHrt8pdKLqpWB6sIHglq4nKZCHXKno07JLJwMZSUQtYMk785yKzGkzcJm6gvSDsC5 H5Zpb/s+C9kaoQKXe1Q8iqjYUmXHdaDhSd7PthZQ7b0Cq35NzNmhvM1xAK77XAoLW1LP 5U/g== X-Gm-Message-State: AIkVDXJEDM+s1v5xEZLq8+squaZBmI5thFJpooxAXozuzZC9PKGtW6kxmAhioqBiiduqSA== X-Received: by 10.28.0.73 with SMTP id 70mr1041080wma.109.1484872356193; Thu, 19 Jan 2017 16:32:36 -0800 (PST) Received: from xtorus.lan (munkyhouse.force9.co.uk. [84.92.42.80]) by smtp.gmail.com with ESMTPSA id 186sm1822316wmw.24.2017.01.19.16.32.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 19 Jan 2017 16:32:35 -0800 (PST) From: Adam Butcher To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, nathan@gcc.gnu.org, adam@jessamine.co.uk Subject: [PATCH] Fix PR c++/64382 Date: Fri, 20 Jan 2017 01:06:00 -0000 Message-Id: <20170119040842.20219-1-adam@jessamine.co.uk> X-SW-Source: 2017-01/txt/msg01538.txt.bz2 Hi Jason, I've reopened 64382 and unhooked it from 61636 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64382#c6). This is a rebase of my original patch for 64382 from April 2015 against latest master. My query about caching parsing_default_capturing_generic_lambda_in_template() still applies. It is currently called once for each id-expression that is dependent but its result will be consistent within a particular lambda body. It feels like we should compute the state once when entering a lambda body and refer to the cached state thereafter (resetting/restoring it on descent/return from each lambda we come across). Cheers, Adam PR c++/64382 * cp/parser.c (parsing_default_capturing_generic_lambda_in_template): New function. * cp/cp-tree.h: Declare it. * cp/semantics.c (finish_id_expression): Resolve names within a default capturing generic lambda defined within a template prior to instantiation to allow for captures to be added to the closure type. PR c++/64382 * g++.dg/cpp1y/pr64382.C: New test. --- gcc/cp/cp-tree.h | 1 + gcc/cp/parser.c | 25 +++++++++++++++++++++++++ gcc/cp/semantics.c | 8 +++++--- gcc/testsuite/g++.dg/cpp1y/pr64382.C | 23 +++++++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr64382.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9c4436710dd..77d20d4d3dc 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6110,6 +6110,7 @@ extern bool maybe_clone_body (tree); /* In parser.c */ extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool); extern bool parsing_nsdmi (void); +extern bool parsing_default_capturing_generic_lambda_in_template (void); extern void inject_this_parameter (tree, cp_cv_quals); /* in pt.c */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 29dcfea283f..5cc0ddacc2b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -20450,6 +20450,31 @@ parsing_nsdmi (void) return false; } +/* Return true iff our current scope is a default capturing generic lambda + defined within a template. */ + +bool +parsing_default_capturing_generic_lambda_in_template (void) +{ + if (!processing_template_decl || !current_class_type) + return false; + + tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); + if (!lam || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_NONE) + return false; + + tree callop = lambda_function (lam); + if (!callop) + return false; + + return (DECL_TEMPLATE_INFO (callop) + && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop) + && ((current_nonlambda_class_type () + && CLASSTYPE_TEMPLATE_INFO (current_nonlambda_class_type ())) + || ((current_nonlambda_function () + && DECL_TEMPLATE_INFO (current_nonlambda_function ()))))); +} + /* Parse a late-specified return type, if any. This is not a separate non-terminal, but part of a function declarator, which looks like diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 42024755e4f..3c0bd7e751c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3562,9 +3562,11 @@ finish_id_expression (tree id_expression, ? CP_ID_KIND_UNQUALIFIED_DEPENDENT : CP_ID_KIND_UNQUALIFIED))); - /* If the name was dependent on a template parameter, we will - resolve the name at instantiation time. */ - if (dependent_p) + /* If the name was dependent on a template parameter and we're not in a + default capturing generic lambda within a template, we will resolve the + name at instantiation time. */ + if (dependent_p + && !parsing_default_capturing_generic_lambda_in_template ()) { if (DECL_P (decl) && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl))) diff --git a/gcc/testsuite/g++.dg/cpp1y/pr64382.C b/gcc/testsuite/g++.dg/cpp1y/pr64382.C new file mode 100644 index 00000000000..8f2e931e048 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr64382.C @@ -0,0 +1,23 @@ +// PR c++/64382 +// { dg-do compile { target c++14 } } + +template +struct my_queue +{ + void push(T) + { + } + void ice() + { + auto L = [=](auto &&v) { + push(v); + }; + trav(L); + } + template + void trav(F &&f) + { + f(T()); + } +}; +template struct my_queue; -- 2.11.0