From patchwork Fri Jan 12 19:11:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 860153 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-471040-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="jfBl/yHC"; 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 3zJC6W6XVfz9sBd for ; Sat, 13 Jan 2018 06:12:02 +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:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=LHgZNMvvNxuu4yiTw1TskOwXGe67CqQKFAA73bYG/nU/X4SyfQ iiIcGsmZhmSIn4zKBTyvWZ7S16YnYDmTCaoCXMOsNvxlL+3RzIkh8obBOjoUfwgn tjDWVs+hBHcu6dES0avRc3Ui3d1GasE5oMQqx5Z9+R9OCVT9lTJdyG7U8= 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=8DsMofgVNfUU0pjP2ba18TFodsM=; b=jfBl/yHCmRnNgUNEIzkl UwdwJMkpqBBtWXWq06/z+CWkS7uIuq7OPomkZ++TS3a/w0uaF0pobmyikGwfKMLU 0q+vGNFtF86d8DNHmbLjSG8behDQRc3TRbqkGpQaG73591jWHgI4By03GRGaMg69 s6a4GNMBeOUNUW1xFewECH8= Received: (qmail 82719 invoked by alias); 12 Jan 2018 19:11:55 -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 79880 invoked by uid 89); 12 Jan 2018 19:11:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=KIND X-HELO: mail-yb0-f180.google.com Received: from mail-yb0-f180.google.com (HELO mail-yb0-f180.google.com) (209.85.213.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 12 Jan 2018 19:11:52 +0000 Received: by mail-yb0-f180.google.com with SMTP id a82so3137437ybg.1 for ; Fri, 12 Jan 2018 11:11:52 -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:content-language; bh=8WhjXqlnK8eAwP1tgWsgZWi71pYVscFtCSux+ILO8Sc=; b=SLTOhiZuR3GRodJuhjqmi4W5xKhGOBejdTELw8YljUmNt0QKqzrV+coHrTuUNbKbVY ff7j+SEDloZzc4/hsP7XFld3+01WaDilm67xdTwpCh6mVaV3LXPaVB8W44U9NvRJAnQb uIdp/3b3ln4i2wvGRrZZzJSgXwZI/GJwmD/FXa3FayfN5PMlNFpukCf78NLA6fZ1Rcbo c+gbGfAWnMRsNkyYS6YPpqWw7fYVjkVgK3qlzkesRVAMzivpt9niEEc73+5DJRHobhL1 4v6KVyYGvQpwPb57unKyS44Zv4l4cHE9L+2rJyknADnHbeZAw0XnbTfkTO1WXH8FhGN2 biqQ== X-Gm-Message-State: AKwxyte8Xt0q5L9HnYRojxhxoL8kXinS0fZqx6JE9pVnJwbc1NXWoD3X 01gC5p1PI8OKkb6Dl55z80Q= X-Google-Smtp-Source: ACJfBosC/6ey6fhiITrePPLKUkOTtswLaI3gB+1sNWkMy8KXFihDU9d547nfNfYsy0trwVdDw4Q/cg== X-Received: by 10.37.162.205 with SMTP id c13mr8682332ybn.136.1515784310599; Fri, 12 Jan 2018 11:11:50 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:7500:e7fb:4a6f:2254? ([2620:10d:c091:200::2:3141]) by smtp.googlemail.com with ESMTPSA id j71sm2757425ywg.38.2018.01.12.11.11.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 12 Jan 2018 11:11:49 -0800 (PST) To: Jason Merrill Cc: GCC Patches From: Nathan Sidwell Subject: [PR c++/83160] local ref to capture Message-ID: <4cde21ec-f32a-203c-c4b6-756e35f03738@acm.org> Date: Fri, 12 Jan 2018 14:11:47 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2 MIME-Version: 1.0 Jason, this fixes 83160, where we complain about not having an lvalue in things like: void foo () { const int a = 0; [&a] () { const int &b = a; // here }; } The problem is that we in convert_like_real we have ref_bind->identity conversions, and the identity conversion calls 'mark_rvalue_use'. For a regular rvalue use of a 'const int' VAR_DECL, we return the VAR_DECL -- not collapse it to the initialized value. However, for captures, there is code to look through the capture when rvalue_p is true. We end up looking through the lambda capture, through the captured 'a' and to its initializer. oops. Calling mark_lvalue_use instead is also wrong, because the identity conv may of course be being applied to an rvalue, and we end up giving an equally wrong error in the opposite case. Dealing with ck_identity this way sees wrong -- context determines whether this is an rvalue or lvalue use. I think the solution is for the identity conv to know whether it's going to be the subject of a direct reference binding and call mark_lvalue_use in tha case. There's 2 issues with that: 1) mark_lvalue_use isn't quite right because we want to specify reject_builtin to the inner mark_use call. (I didn't try changing mark_lvalue_use to pass true, I suspected it'd break actual calls of builtins). Fixed by making mark_use externally reachable, and passing in an appropriate 'rvalue_p' parm directly. I think your recent patch to select between the two marking fns may be neater using this entry point? 2) I modify direct_reference_binding to look at the incoming conv, and if it is ck_identity set that conv's rvaluedness_matches_p flag. Then deply that flag to determine the arg in #1. 'rvaluedness_matches_p' seemed the least worst existing flag to press into service here. WDYT? nathan 2018-01-12 Nathan Sidwell PR c++/83160 * cp-tree.h (mark_use): Declare. * expr.c (mark_use): Make extern. * call.c (direct_reference_binding): Set inner conv's rvaluedness_matches_p, if it is an identity. (convert_like_real): Mark lvalue or rvalue use for identity as rvaledness_matches_p demands. PR c++/83160 * g++.dg/cpp0x/pr83160.C: New. Index: cp/call.c =================================================================== --- cp/call.c (revision 256593) +++ cp/call.c (working copy) @@ -102,7 +102,8 @@ struct conversion { being bound to an lvalue expression or an rvalue reference is being bound to an rvalue expression. If KIND is ck_rvalue, true when we are treating an lvalue as an rvalue (12.8p33). If - KIND is ck_base, always false. */ + KIND is ck_base, always false. If ck_identity, we will be + binding a reference directly. */ BOOL_BITFIELD rvaluedness_matches_p: 1; BOOL_BITFIELD check_narrowing: 1; /* The type of the expression resulting from the conversion. */ @@ -1501,6 +1502,10 @@ direct_reference_binding (tree type, con That way, convert_like knows not to generate a temporary. */ conv->need_temporary_p = false; } + else if (conv->kind == ck_identity) + /* Mark the identity conv as to not decay to rvalue. */ + conv->rvaluedness_matches_p = true; + return build_conv (ck_ref_bind, type, conv); } @@ -6800,7 +6805,9 @@ convert_like_real (conversion *convs, tr else gcc_unreachable (); } - expr = mark_rvalue_use (expr); + expr = mark_use (expr, /*rvalue_p=*/!convs->rvaluedness_matches_p, + /*read_p=*/true, UNKNOWN_LOCATION, + /*reject_builtin=*/true); if (type_unknown_p (expr)) expr = instantiate_type (totype, expr, complain); Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 256593) +++ cp/cp-tree.h (working copy) @@ -6328,6 +6328,9 @@ extern tree create_try_catch_expr /* in expr.c */ extern tree cplus_expand_constant (tree); +extern tree mark_use (tree expr, bool rvalue_p, bool read_p, + location_t = UNKNOWN_LOCATION, + bool reject_builtin = true); extern tree mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, bool reject_builtin = true); Index: cp/expr.c =================================================================== --- cp/expr.c (revision 256593) +++ cp/expr.c (working copy) @@ -89,7 +89,7 @@ cplus_expand_constant (tree cst) /* We've seen an actual use of EXPR. Possibly replace an outer variable reference inside with its constant value or a lambda capture. */ -static tree +tree mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc /* = UNKNOWN_LOCATION */, bool reject_builtin /* = true */) Index: testsuite/g++.dg/cpp0x/pr83160.C =================================================================== --- testsuite/g++.dg/cpp0x/pr83160.C (revision 0) +++ testsuite/g++.dg/cpp0x/pr83160.C (working copy) @@ -0,0 +1,33 @@ +// { dg-do run { target c++11 } } +// PR c++/83160 failed to capture as lvalue + +int main () +{ + const int a = 0; + + if (![&a] (const int *p) + { + const int &b = a; + // We should bind to the outer a + return &b == p; + } (&a)) + return 1; + + if (![&] (const int *p) + { + const int &b = a; + // We should bind to the outer a + return &b == p; + } (&a)) + return 2; + + if ([=] (const int *p) + { + const int &b = a; + // We should bind to the captured instance + return &b == p; + }(&a)) + return 3; + + return 0; +}