From patchwork Thu Dec 15 12:38:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 88145 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp768807qgi; Thu, 15 Dec 2016 04:39:08 -0800 (PST) X-Received: by 10.84.213.23 with SMTP id f23mr2203447pli.59.1481805548192; Thu, 15 Dec 2016 04:39:08 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id 1si2299284pll.154.2016.12.15.04.39.07 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Dec 2016 04:39:08 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-444499-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-444499-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-444499-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=qI+IVgHAO/XIFXC1V1kjznljmN1gc1SH3rworNEP1QnPpB3aww Y7ZKcy2DBmJtm+FUa4TdfEhud+1tRmkIbmXeah44QhdJXsHEYkAodmbnS0IoIzu4 A0Ql1+YE45FNA7zF4KCtGD/0kPpNPyDv6Jl9w0yWvvssa0OXZ2669mY7s= 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:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=CgCZOtOQPRMrjZe5McmrXif3QYE=; b=wIBSjy90q1v11DSX+X4n 4DVdPmRgZCIQhlYHR9Yj1R+NZGhoA+AfD7rNSQZ9cWU5ERUEyuQaiDSUTZWJXVpH ZTnFB22f75JpUARv5bNkYi2DR2GAyPAwAjFgrjX48EwhGalru/yPMxxeRJ9taSNn YXl0OrOGYNMdekSJ6BTuamw= Received: (qmail 123261 invoked by alias); 15 Dec 2016 12:38:57 -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 123234 invoked by uid 89); 15 Dec 2016 12:38:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=Eat, popping, pushes, H*F:U*nathan X-HELO: mail-yb0-f195.google.com Received: from mail-yb0-f195.google.com (HELO mail-yb0-f195.google.com) (209.85.213.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 15 Dec 2016 12:38:44 +0000 Received: by mail-yb0-f195.google.com with SMTP id d59so3590886ybi.2 for ; Thu, 15 Dec 2016 04:38:44 -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:to:cc:from:subject:message-id:date :user-agent:mime-version; bh=ZdtSw38Uda91GiP84Fag1dwtJkJh779Sby17nxHLEx4=; b=kilE48RxenrlBLMGf7Cz2nmd81hOnxIu6FEZaulEJfdhCzFPjwHusHKaC/PTf2fuTS JKZAXBuhMt7CBPbyyqw6QPe8Oth+0MBewJC+uB8MnI96VGlsfSpECqCoQW8jR+WsKWGh SJ4acd87OfREtvdiqF8AyO2Jh2Y0Vfe0M22IycbW5U6UNpunxH+81tTCyL3xwvg3BpWs bHdZPfq1yRBwxy7sQjPPa1C3CaKQudKBS4oXk2LXi6GRzkqYwQNkVn3oKBZxRKhc7TTX dQOVoYY62X5HFKMWgGsiGK31Vo79qtgww0kmbNYLTedG+mjPgs7pkVcQSHinkP8Yrg+u Uuyw== X-Gm-Message-State: AIkVDXI9h3TdZuh8jaLkkuYpSApKOOLrIgXAxr0c+FazJsasUAVj2VL5bMEmJ1OpWwkQ8A== X-Received: by 10.37.44.7 with SMTP id s7mr863761ybs.130.1481805523148; Thu, 15 Dec 2016 04:38:43 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::640]) by smtp.googlemail.com with ESMTPSA id g133sm510934ywe.1.2016.12.15.04.38.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Dec 2016 04:38:42 -0800 (PST) To: Jason Merrill Cc: GCC Patches From: Nathan Sidwell Subject: [PATCH] c++/pr77585 bogus this error with generic lambda Message-ID: Date: Thu, 15 Dec 2016 07:38:41 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 77585 concerns the instantiation of a generic lambda that contains a call to a non-dependent non-static member function. auto lam = [&](auto) { return Share (); }; r += Eat (lam); // instantation of lambda::operator() here During instantiation of the call to Share, maybe_resolve_dummy gets called and uses current_nonlambda_class_type, which peeks up the current_current_class stack. That peeking presupposes we're actually pushing and popping class scopes as we enter them all the way from the global scope. But that doesn't always happen in instantiation. push_nested_class pushes the immediately enclosing scopes, but stops at function scope. So we don't get the class scope of that function pushed. Thus stack peeking fails. This hasn't previously been an instantiation problem, because templates couldn't be defined at local scope. But generic lambdas now have that property (wrt this capture at least). This patch amends instantiate_decl to first push the containing non-lambda class scope before start_preparsed_function does its stack pushing. ok? nathan -- Nathan Sidwell 2016-12-14 Nathan Sidwell PR c++/77585 * pt.c (instantiate_decl): Push to class scope lambda resides within when instantiating a generic lambda function. PR c++/77585 * g++.dg/cpp1y/pr77585.C: New. Index: cp/pt.c =================================================================== --- cp/pt.c (revision 243661) +++ cp/pt.c (working copy) @@ -22483,6 +22483,7 @@ instantiate_decl (tree d, int defer_ok, tree tmpl_parm; tree spec_parm; tree block = NULL_TREE; + tree lambda_ctx = NULL_TREE; /* Save away the current list, in case we are instantiating one template from within the body of another. */ @@ -22496,7 +22497,23 @@ instantiate_decl (tree d, int defer_ok, && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL) block = push_stmt_list (); else - start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED); + { + if (LAMBDA_FUNCTION_P (d)) + { + /* When instantiating a lambda's templated function + operator, we need to push the non-lambda class scope + of the lambda itself so that the nested function + stack is sufficiently correct to deal with this + capture. */ + lambda_ctx = DECL_CONTEXT (d); + do + lambda_ctx = decl_type_context (TYPE_NAME (lambda_ctx)); + while (lambda_ctx && LAMBDA_TYPE_P (lambda_ctx)); + if (lambda_ctx) + push_nested_class (lambda_ctx); + } + start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED); + } /* Some typedefs referenced from within the template code need to be access checked at template instantiation time, i.e now. These @@ -22564,6 +22581,8 @@ instantiate_decl (tree d, int defer_ok, d = finish_function (0); expand_or_defer_fn (d); } + if (lambda_ctx) + pop_nested_class (); if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)) cp_check_omp_declare_reduction (d); Index: testsuite/g++.dg/cpp1y/pr77585.C =================================================================== --- testsuite/g++.dg/cpp1y/pr77585.C (revision 0) +++ testsuite/g++.dg/cpp1y/pr77585.C (working copy) @@ -0,0 +1,41 @@ +// PR c++/77585 +// { dg-do run { target c++14 } } + +// Confusion about this capture when instantiating generic lambda's +// function operator + +template int Eat (F &&f) { return f (1); } + +struct Foo { + int x = 1; + int Share () { return x++; } + int Frob (int); +}; + +int Foo::Frob (int r) +{ + auto lam = [&](auto) { return Share (); }; + r += Eat (lam); + + auto lam0 = [&](auto) { + auto lam1 = [&](auto) { return Share (); }; + return Eat (lam1); }; + r += Eat (lam0); + + return r; +} + +int Frob (int r) +{ + auto lam = [&](auto) { return 1; }; + r += Eat (lam); + return r; +} + + +int main () +{ + Foo f; + + return Frob (f.Frob (0)) == 4 ? 0 : 1; +}