From patchwork Tue Jan 3 13:57:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 710485 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3ttFrF22g8z9sf9 for ; Wed, 4 Jan 2017 00:57:32 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="tWQaK69E"; dkim-atps=neutral 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=Vg1aep41Nd2ZMFo1eNBhTVe3OvKyUqONDycPe9Cxxn5syBq1i3 vIyFLnOaeSZyWpuRFjYYtwGc3ZabLbbGhU7qDVg02qhjAmPosIX4gf19Fd9kx81i mUJ20Ot2qd8TXo/NsnYlPnbUMtNLutU8wvyFq9CdB9M0D9nN7/KbhRMd0= 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=PUjblw51xR3ZxFQuomTY0tuDGl4=; b=tWQaK69Ef+iGfmvwReS2 eIhnY4qP1rHk6qoLAG4hwZbc68WJdPKbOqgdceidfQXs5nLvaL4e0PwgI277R98Z A1tvDicmq+UtRe+0T/y+wbh5IErwmJnm2SQPs/sFq106C78+KFSNTTr3Ltr7bery sGbT7yAA+XjclOT0iXBn1+Y= Received: (qmail 39942 invoked by alias); 3 Jan 2017 13:57:23 -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 39930 invoked by uid 89); 3 Jan 2017 13:57:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.3 required=5.0 tests=BAYES_20, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=outermost, sk:build_r, 21114, 211, 14 X-HELO: mail-yw0-f195.google.com Received: from mail-yw0-f195.google.com (HELO mail-yw0-f195.google.com) (209.85.161.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 03 Jan 2017 13:57:12 +0000 Received: by mail-yw0-f195.google.com with SMTP id r204so38511531ywb.3 for ; Tue, 03 Jan 2017 05:57:12 -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=qBmlEwP/PeKTkStpOZr80IuFOuqhLECdti6oUqWXv+0=; b=DLSPOyEoNWyReOOoCuVhfbEIfAxYD9rrjhN4CXpX2hPpaTzcEganz5BjLE5DkqGadr Kn+C+pDXGhwFflHgo9MTGnvUr1lHXOcExGlfTiVPBtTp+QEgwfqhLnNvCzZMAzL7ezxu DGMJxjUHEjvqzgHAWGiaJlHVMb6OMc18e3+2hkDPAvVA91MC8I/HvnmjTN9Lm2y3TTbo Ah2ElJbTO1VcGYh671s2BzgMWmwra/LPFr0EGoWc2+F8Wp0xl5LPH6j/MlwTR2b4e7er +CjS1irSqtOEMmt/JZ+Z/Q1hysf+8pMWauKN7il0V5TLj2JiuJuuMQaQ0pddFGvjzmKU MnFA== X-Gm-Message-State: AIkVDXKUEqtc55bUxrw7arwzzCz2k8+bnbWW7eDq4WrJDg9LG97zJSnZizD6VzWg8md99g== X-Received: by 10.129.172.34 with SMTP id k34mr53056238ywh.105.1483451831055; Tue, 03 Jan 2017 05:57:11 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::e:a6d2]) by smtp.googlemail.com with ESMTPSA id u18sm28808091ywf.28.2017.01.03.05.57.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Jan 2017 05:57:10 -0800 (PST) To: Jason Merrill Cc: GCC Patches From: Nathan Sidwell Subject: [PATCH] PR c++/66735 lambda capture by reference Message-ID: <3d7dc3ce-201b-2bde-27aa-63e979df0341@acm.org> Date: Tue, 3 Jan 2017 08:57:09 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 This patch fixes 66735, where we lose cv qualifiers on an explicit lambda capture by reference: [&r = ] () {...} The problem is the partitioning between lambda_capture_field_type and add_capture, where the latter is responsible for adding the referenceness. That leaves auto deduction clueless that it should preserve cv qualifiers. Fixed by moving the referenceness into LCFT and adjusting. I also refactored the error checking in add_capture, as that seemed a little repetitious to me -- both paths check for type completeness. ok? nathan 2017-01-03 Nathan Sidwell cp/ PR c++/66735 * lambda.c (lambda_capture_field_type): Add is_reference parm. (add_capture): Adjust lambda_capture_field_type call, refactor error checking. * pt.c (tsubst): Adjust lambda_capture_field_type call. * cp-tree.h (lambda_capture_field_type): Update prototype. testsuite/ PR c++/66735 * g++.dg/cpp1y/pr66735.C: New. Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 244021) +++ cp/cp-tree.h (working copy) @@ -6528,7 +6528,7 @@ extern tree finish_trait_expr (enum cp extern tree build_lambda_expr (void); extern tree build_lambda_object (tree); extern tree begin_lambda_type (tree); -extern tree lambda_capture_field_type (tree, bool); +extern tree lambda_capture_field_type (tree, bool, bool); extern tree lambda_return_type (tree); extern tree lambda_proxy_type (tree); extern tree lambda_function (tree); Index: cp/lambda.c =================================================================== --- cp/lambda.c (revision 244021) +++ cp/lambda.c (working copy) @@ -211,14 +211,17 @@ lambda_function (tree lambda) } /* Returns the type to use for the FIELD_DECL corresponding to the - capture of EXPR. - The caller should add REFERENCE_TYPE for capture by reference. */ + capture of EXPR. EXPLICIT_INIT_P indicates whether this is a + C++14 init capture, and BY_REFERENCE_P indicates whether we're + capturing by reference. */ tree -lambda_capture_field_type (tree expr, bool explicit_init_p) +lambda_capture_field_type (tree expr, bool explicit_init_p, + bool by_reference_p) { tree type; bool is_this = is_this_parameter (tree_strip_nop_conversions (expr)); + if (!is_this && type_dependent_expression_p (expr)) { type = cxx_make_type (DECLTYPE_TYPE); @@ -229,11 +232,24 @@ lambda_capture_field_type (tree expr, bo } else if (!is_this && explicit_init_p) { - type = make_auto (); - type = do_auto_deduction (type, expr, type); + tree auto_node = make_auto (); + + type = auto_node; + if (by_reference_p) + { + /* Add the reference now, so deduction doesn't lose + outermost CV qualifiers of EXPR. */ + type = build_reference_type (type); + by_reference_p = false; + } + type = do_auto_deduction (type, expr, auto_node); } else type = non_reference (unlowered_expr_type (expr)); + + if (!is_this && by_reference_p) + type = build_reference_type (type); + return type; } @@ -504,9 +520,11 @@ add_capture (tree lambda, tree id, tree } else { - type = lambda_capture_field_type (initializer, explicit_init_p); + type = lambda_capture_field_type (initializer, explicit_init_p, + by_reference_p); if (type == error_mark_node) return error_mark_node; + if (id == this_identifier && !by_reference_p) { gcc_assert (POINTER_TYPE_P (type)); @@ -514,17 +532,19 @@ add_capture (tree lambda, tree id, tree initializer = cp_build_indirect_ref (initializer, RO_NULL, tf_warning_or_error); } - if (id != this_identifier && by_reference_p) + + if (dependent_type_p (type)) + ; + else if (id != this_identifier && by_reference_p) { - type = build_reference_type (type); - if (!dependent_type_p (type) && !lvalue_p (initializer)) + if (!lvalue_p (initializer)) error ("cannot capture %qE by reference", initializer); } else { /* Capture by copy requires a complete type. */ type = complete_type (type); - if (!dependent_type_p (type) && !COMPLETE_TYPE_P (type)) + if (!COMPLETE_TYPE_P (type)) { error ("capture by copy of incomplete type %qT", type); cxx_incomplete_type_inform (type); Index: cp/pt.c =================================================================== --- cp/pt.c (revision 244021) +++ cp/pt.c (working copy) @@ -13988,7 +13988,8 @@ tsubst (tree t, tree args, tsubst_flags_ if (DECLTYPE_FOR_LAMBDA_CAPTURE (t)) type = lambda_capture_field_type (type, - DECLTYPE_FOR_INIT_CAPTURE (t)); + DECLTYPE_FOR_INIT_CAPTURE (t), + /*by_reference_p=*/false); else if (DECLTYPE_FOR_LAMBDA_PROXY (t)) type = lambda_proxy_type (type); else Index: testsuite/g++.dg/cpp1y/pr66735.C =================================================================== --- testsuite/g++.dg/cpp1y/pr66735.C (revision 0) +++ testsuite/g++.dg/cpp1y/pr66735.C (working copy) @@ -0,0 +1,10 @@ +// { dg-do compile { target c++14 } } + +// PR c++/66735, lost constness on reference capture + +int const x = 5; + +void Foo () +{ + auto l = [&rx = x]() {}; +}