From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id D507D3858C2C for ; Fri, 1 Dec 2023 22:42:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D507D3858C2C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D507D3858C2C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701470538; cv=none; b=G08n+syQ+jOhPBykilHjoYFzyiQy00W5mgd8MNdRw4TdaWX7ZGgcz5EFHbabUPBmkYSCse58XHMJmOrmmvH7sqLErAOqNQErnLPmDZVNOwBXGnNUJBCKQ7+fXSBIDijwoynrUWqYLo3GWe2gm+i10EcB/n2PABHh7zlvky792iI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701470538; c=relaxed/simple; bh=h4KjRMsYrvxiRZ2rzihJ8Unon3geDS1o3/0o5TzmDxY=; h=DKIM-Signature:From:Date:To:Subject:Message-ID:MIME-Version; b=Xeaa2cwG4GB+EyZ8pspxndeC30z5ILH2Z7JILnQabsRZioOQrxXiANgv2gZKCTm9/ZDuSMhIHVxkLBRZ8Ji11iOGuH0M8icjSUFdoh0+PHXL0D0znglwF/N587y8ZuQj753FSeZxDy8+RNhuvthjNUHk/Gxd8WTjAAxvHDystTY= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1701470536; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=cXRcX0QJDAroKGSfEBfPBmg4SIUHURBkCuOb6mYetl0=; b=FQk/N5G8lWK3C5/n3xYZKbb28hQJlt5sWw5vl1bjhyJ5BhLbWgRmSbiYtEkmSh2owLv35l l+6EMwgbQkIjejvU6rM+7A7akpIwhjStGg/S0BVvYWZ5IAo07Qs0Val2XmgmTmxP8i/ora vxKAoNc30GlLpw4aH3E5WOcJPfQdMcA= Received: from mail-ot1-f71.google.com (mail-ot1-f71.google.com [209.85.210.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-613-YG_JTiI5Nimw4REGcSfl4A-1; Fri, 01 Dec 2023 17:42:15 -0500 X-MC-Unique: YG_JTiI5Nimw4REGcSfl4A-1 Received: by mail-ot1-f71.google.com with SMTP id 46e09a7af769-6d876166cf8so9770a34.2 for ; Fri, 01 Dec 2023 14:42:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701470534; x=1702075334; h=mime-version:references:message-id:in-reply-to:subject:cc:to:date :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=cXRcX0QJDAroKGSfEBfPBmg4SIUHURBkCuOb6mYetl0=; b=uTHbErWCNMvpAaYCwXt5zSM+h57fkfHB0tcX3nMQ2blRUq0cu5OXEX2v7PEp1OHrbn MnO/UhqM2U7XnQZdOujJOT46bz7F9iaxAxOSa8VgDmbRtASyEBFIU1reMDcbp25fAsUK pLogOkBZ/4pbbGH7weBOkEGdEb49olUlzSgRonH7m6dPOFPTGTzXB52b1opnJmX7DoQy miPnhPKsqrhShoNfPS4Jrj4hUkr0bUNMVZGPHDPynxVwFrojlthxzFNawR+cs2XSvqp2 J3Wk4v4BMzb+57GL1wnfchniLEO7zfZlr+iE/iFBQgU+wNcfcfCGGpJ6KX3LQcL3IzHc y7sw== X-Gm-Message-State: AOJu0Yxoo06e+2k/coQKCRUISwcVkaY2mnKo0TyWlz4tyI0Zc+zYr7Sa XjCwAo69aSDChDQLn/f2SWYN6753nAxCzPF6qjw4MpeWdBrBdj965i2DHRxtdbTJY2Pa+A2KfdI u3VmWeK1RuTcV0cfrtQ== X-Received: by 2002:a05:6830:43a8:b0:6bd:152f:9918 with SMTP id s40-20020a05683043a800b006bd152f9918mr255006otv.14.1701470534600; Fri, 01 Dec 2023 14:42:14 -0800 (PST) X-Google-Smtp-Source: AGHT+IGXAyFSnXqUZR2eCsgMlTga/ywmQ91SKIEnA5q/FNezqfCw0Zh1RLpy7ioniZDrF9foMam3lA== X-Received: by 2002:a05:6830:43a8:b0:6bd:152f:9918 with SMTP id s40-20020a05683043a800b006bd152f9918mr254995otv.14.1701470534297; Fri, 01 Dec 2023 14:42:14 -0800 (PST) Received: from [192.168.1.130] (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id d19-20020a0cdb13000000b0067a5e43fc98sm1009933qvk.137.2023.12.01.14.42.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:42:13 -0800 (PST) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Fri, 1 Dec 2023 17:42:12 -0500 (EST) To: Jason Merrill cc: Patrick Palka , gcc-patches@gcc.gnu.org Subject: Re: [PATCH] c++: decltype of (non-captured variable) [PR83167] In-Reply-To: <16e8d6ea-3bc1-492f-b3b4-83d228d646e4@redhat.com> Message-ID: References: <20231114161044.985367-1-ppalka@redhat.com> <11df54f6-a14e-468e-9559-9cc3eed6e65d@redhat.com> <9a373c23-3f76-3097-7978-4832755b5573@idea> <16e8d6ea-3bc1-492f-b3b4-83d228d646e4@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,RCVD_IN_SORBS_WEB,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, 1 Dec 2023, Jason Merrill wrote: > On 12/1/23 12:32, Patrick Palka wrote: > > On Tue, 14 Nov 2023, Jason Merrill wrote: > > > > > On 11/14/23 11:10, Patrick Palka wrote: > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > > > trunk? > > > > > > > > -- >8 -- > > > > > > > > For decltype((x)) within a lambda where x is not captured, we dubiously > > > > require that the lambda has a capture default, unlike for decltype(x). > > > > This patch fixes this inconsistency; I couldn't find a justification for > > > > it in the standard. > > > > > > The relevant passage seems to be > > > > > > https://eel.is/c++draft/expr.prim#id.unqual-3 > > > > > > "If naming the entity from outside of an unevaluated operand within S > > > would > > > refer to an entity captured by copy in some intervening lambda-expression, > > > then let E be the innermost such lambda-expression. > > > > > > If there is such a lambda-expression and if P is in E's function parameter > > > scope but not its parameter-declaration-clause, then the type of the > > > expression is the type of a class member access expression ([expr.ref]) > > > naming > > > the non-static data member that would be declared for such a capture in > > > the > > > object parameter ([dcl.fct]) of the function call operator of E." > > > > > > In this case I guess there is no such lambda-expression because naming x > > > won't > > > refer to a capture by copy if the lambda doesn't capture anything, so we > > > ignore the lambda. > > > > > > Maybe refer to that in a comment? OK with that change. > > > > > > I'm surprised that it refers specifically to capture by copy, but I guess > > > a > > > capture by reference should have the same decltype as the captured > > > variable? > > > > Ah, seems like it. So maybe we should get rid of the redundant > > by-reference capture-default handling, to more closely mirror the > > standard? > > > > Also now that r14-6026-g73e2bdbf9bed48 made capture_decltype return > > NULL_TREE to mean the capture is dependent, it seems we should just > > inline capture_decltype into finish_decltype_type rather than > > introducing another special return value to mean "fall back to ordinary > > handling". > > > > How does the following look? Bootstrapped and regtested on > > x86_64-pc-linux-gnu. > > > > -- >8 -- > > > > PR c++/83167 > > > > gcc/cp/ChangeLog: > > > > * semantics.cc (capture_decltype): Inline into its only caller ... > > (finish_decltype_type): ... here. Update nearby comment to refer > > to recent standard. Restrict uncaptured variable handling to just > > lambdas with a by-copy capture-default. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp0x/lambda/lambda-decltype4.C: New test. > > --- > > gcc/cp/semantics.cc | 107 +++++++----------- > > .../g++.dg/cpp0x/lambda/lambda-decltype4.C | 15 +++ > > 2 files changed, 55 insertions(+), 67 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-decltype4.C > > > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > > index fbbc18336a0..fb4c3992e34 100644 > > --- a/gcc/cp/semantics.cc > > +++ b/gcc/cp/semantics.cc > > @@ -53,7 +53,6 @@ along with GCC; see the file COPYING3. If not see > > static tree maybe_convert_cond (tree); > > static tree finalize_nrv_r (tree *, int *, void *); > > -static tree capture_decltype (tree); > > /* Used for OpenMP non-static data member privatization. */ > > @@ -11856,21 +11855,48 @@ finish_decltype_type (tree expr, bool > > id_expression_or_member_access_p, > > } > > else > > { > > - /* Within a lambda-expression: > > - > > - Every occurrence of decltype((x)) where x is a possibly > > - parenthesized id-expression that names an entity of > > - automatic storage duration is treated as if x were > > - transformed into an access to a corresponding data member > > - of the closure type that would have been declared if x > > - were a use of the denoted entity. */ > > if (outer_automatic_var_p (STRIP_REFERENCE_REF (expr)) > > && current_function_decl > > && LAMBDA_FUNCTION_P (current_function_decl)) > > { > > - type = capture_decltype (STRIP_REFERENCE_REF (expr)); > > - if (!type) > > - goto dependent; > > + /* [expr.prim.id.unqual]/3: If naming the entity from outside of an > > + unevaluated operand within S would refer to an entity captured by > > + copy in some intervening lambda-expression, then let E be the > > + innermost such lambda-expression. > > + > > + If there is such a lambda-expression and if P is in E's function > > + parameter scope but not its parameter-declaration-clause, then > > the > > + type of the expression is the type of a class member access > > + expression naming the non-static data member that would be > > declared > > + for such a capture in the object parameter of the function call > > + operator of E." */ > > Hmm, looks like this code is only checking the innermost lambda, it needs to > check all containing lambdas for one that would capture it by copy. Unfortunately this seems to be a can of worms, since IIUC we also have to check that there's no non-default-capture lambda in the stack as well, e.g. int main() { int x; [] { [=] { using ty1 = decltype((x)); // refers to local variable despite // innermost by-copy capture-default using ty1 = int&; }; }; [=] { [] { using ty1 = decltype((x)); // same using ty1 = int&; }; }; [=] { [&] { using ty1 = decltype((x)); // refers to hypothetical capture proxy using ty1 = const int&; }; }; [&] { [=] { using ty1 = decltype((x)); // same using ty1 = const int&; }; }; } And we have to refine the logic for whether to perform the HIDDEN_LAMBDA name lookup (which we currently unconditionally do): int main() { int x; [x] { [x] { using ty1 = decltype((x)); // refers to actual capture proxy, // found by HIDDEN_LAMBDA name lookup using ty1 = const int&; }; }; [x] { [] { using ty1 = decltype((x)); // refers to local variable, // HIDDEN_LAMBDA name lookup not performed using ty1 = int&; }; }; } These could probably be fixed locally within finish_decltype_type, but then there's PR86697 which basically extends all of these capture-related issues to 'decltype(f(x))' instead of 'decltype((x))', which suggests a proper fix should probably be in process_outer_var_ref instead of in finish_decltype_type? Perhaps when in an unevaluated context, process_outer_var_ref should still rewrite uses into capture proxies but not actually add them to the closure or something like that? I don't think I have the cycles to work on these issues this stage.. Would the latest patch be OK at least? It seems to be a strict improvement. > > > + tree decl = STRIP_REFERENCE_REF (expr); > > + tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT > > (current_function_decl)); > > + tree cap = lookup_name (DECL_NAME (decl), LOOK_where::BLOCK, > > + LOOK_want::HIDDEN_LAMBDA); > > + > > + if (cap && is_capture_proxy (cap)) > > + type = TREE_TYPE (cap); > > + else if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_COPY) > > + { > > + type = TREE_TYPE (decl); > > + if (TYPE_REF_P (type) > > + && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) > > + type = TREE_TYPE (type); > > + } > > + > > + if (type && !TYPE_REF_P (type)) > > + { > > + tree obtype = TREE_TYPE (DECL_ARGUMENTS > > (current_function_decl)); > > + if (WILDCARD_TYPE_P (non_reference (obtype))) > > + /* We don't know what the eventual obtype quals will be. */ > > + goto dependent; > > + int quals = cp_type_quals (type); > > + if (INDIRECT_TYPE_P (obtype)) > > + quals |= cp_type_quals (TREE_TYPE (obtype)); > > > > Shouldn't we propagate cv-quals of a by-value object parameter as well? > > Ah, I think you're right. > > Jason > >