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.133.124]) by sourceware.org (Postfix) with ESMTPS id 86738383236A for ; Wed, 14 Dec 2022 17:48:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 86738383236A Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1671040111; 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: content-transfer-encoding:content-transfer-encoding; bh=H393ajTKssWPocThS4Sa8Hh+lwpMpjXCZZlsrSx7y34=; b=SwlW313E4zcQbTpBKdaaxs6aHd+Y/nkf95HXO9gIoSyyU5c+KADh4LGuyy3yL09Nw/AajF bihR6siawXvxCRanhGnizhQftz09Q0fcUMpVq9ypfI/nXoiDBYlDBsybD1Pjp8SeCynAUt YRg1et25mzHdEz0jClDWEbRPTF3nU28= Received: from mail-vs1-f69.google.com (mail-vs1-f69.google.com [209.85.217.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-648-XL8AoddbODO30u1JJJn9qQ-1; Wed, 14 Dec 2022 12:48:30 -0500 X-MC-Unique: XL8AoddbODO30u1JJJn9qQ-1 Received: by mail-vs1-f69.google.com with SMTP id k30-20020a67ef5e000000b003b139171497so142960vsr.9 for ; Wed, 14 Dec 2022 09:48:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=H393ajTKssWPocThS4Sa8Hh+lwpMpjXCZZlsrSx7y34=; b=sSkFNSAVCp1fHfOqNLQdEcm3TjTm+j6TO1p5VmluD3Bkk+hTuDH0QEVsczjrsumuWJ Xa+Xph7LGDpLFVgPu+BDFYvDsgMbNptRBNqo/SwObdNQGysf62cEt+JyvZa0LYcQ4Mnh AbeUP69oyjuyvLUbcuCIyD2nvu/mfNlEJrY1rq0N96uEeotxwDQ5xhbIsgVzr4nrgnlR LiJb+5X8+2HzWP6CCIlemmzJbgsh9Zkfd3ie0G18Eci2OJOPuqhm9LLCjV6sbfAcWWkh z6OboVboSqn1jWjx59U4fZrNdzayBZ6oOXuVEoMOPFT6Of7sVvAgq1RSXkG21acxSEnE j8QA== X-Gm-Message-State: ANoB5pmdnlyqPmnFOVPJUU9gH0Ag9S2GVkm5hxRFbr5lUMcXFs/XD5fc QvwCppONLnnrQt+bgTT0RQ3z8Yi/ZKLgHzQ2eYEh9pUTaP91UtVOuIx0mw8NEQg2Ng5fHp/OKZq SUVePWAJZVUX2Ir4m13r64W+KKaXTrMChHW8UIp2W4xHzHZ3ML5RJmNoCfZgk4P4GzUY= X-Received: by 2002:a67:efdb:0:b0:3b0:796c:7a37 with SMTP id s27-20020a67efdb000000b003b0796c7a37mr16827953vsp.28.1671040108473; Wed, 14 Dec 2022 09:48:28 -0800 (PST) X-Google-Smtp-Source: AA0mqf568yCTH5coUa6DCi+YDkDyxrcOdEpZNqTPYOLU9V0wVsuIoSIxRrIoT5btnS+isVwEm8g87Q== X-Received: by 2002:a67:efdb:0:b0:3b0:796c:7a37 with SMTP id s27-20020a67efdb000000b003b0796c7a37mr16827917vsp.28.1671040108033; Wed, 14 Dec 2022 09:48:28 -0800 (PST) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id dm20-20020a05620a1d5400b006fca1691425sm10190878qkb.63.2022.12.14.09.48.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Dec 2022 09:48:27 -0800 (PST) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] c++: local alias in typename in lambda [PR105518] Date: Wed, 14 Dec 2022 12:48:25 -0500 Message-Id: <20221214174825.2340493-1-ppalka@redhat.com> X-Mailer: git-send-email 2.39.0.56.g57e2c6ebbe MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP 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: We substitute the qualifying scope of a TYPENAME_TYPE directly using tsubst_aggr_type (so that we can pass entering_scope=true) instead of going through tsubst, which means we don't properly reuse typedefs during this substitution. This ends up causing us to reject the below testcase because we substitute the TYPENAME_TYPE impl::type as if it were written without the typedef impl for A, and thus we expect the non-capturing lambda to capture t. This patch fixes this by making tsubst_aggr_type delegate typedefs to tsubst so that get properly reused, and then adjusting the result appropriately if entering_scope is true. In passing, this refactors tsubst_aggr_type into two functions, one that's intended to be called directly and a more minimal one that's intended to be called only from the RECORD/UNION/ENUMERAL_TYPE cases of tsubst (and contains only the necessary bits for that call site). Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? Patch generated with -w to suppress noisy whitespace changes. PR c++/105518 gcc/cp/ChangeLog: * pt.cc (tsubst_aggr_type): Handle typedefs by delegating to tsubst and adjusting the result if entering_scope. Split out the main part of the function into ... (tsubst_aggr_type_1) ... here. (tsubst): Use tsubst_aggr_type_1 instead of tsubst_aggr_type. Handle TYPE_PTRMEMFUNC_P RECORD_TYPEs here instead of in tsubst_aggr_type_1. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/lambda/lambda-alias1.C: New test. --- gcc/cp/pt.cc | 58 ++++++++++++++----- .../g++.dg/cpp0x/lambda/lambda-alias1.C | 23 ++++++++ 2 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-alias1.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 81b7787fd3d..86862e56410 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -185,6 +185,7 @@ static tree tsubst_template_parms (tree, tree, tsubst_flags_t); static void tsubst_each_template_parm_constraints (tree, tree, tsubst_flags_t); tree most_specialized_partial_spec (tree, tsubst_flags_t); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); +static tree tsubst_aggr_type_1 (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); static bool check_specialization_scope (void); @@ -13845,23 +13846,49 @@ tsubst_aggr_type (tree t, if (t == NULL_TREE) return NULL_TREE; - /* If T is an alias template specialization, we want to substitute that - rather than strip it, especially if it's dependent_alias_template_spec_p. - It should be OK not to handle entering_scope in this case, since - DECL_CONTEXT will never be an alias template specialization. We only get - here with an alias when tsubst calls us for TYPENAME_TYPE. */ - if (alias_template_specialization_p (t, nt_transparent)) - return tsubst (t, args, complain, in_decl); + /* Handle typedefs via tsubst so that they get reused. */ + if (typedef_variant_p (t)) + { + t = tsubst (t, args, complain, in_decl); + if (t == error_mark_node) + return error_mark_node; + + /* The effect of entering_scope is that when substitution yields a + dependent specialization A, lookup_template_class prefers to + return A's primary template type instead of the implicit instantiation. + So when entering_scope, we mirror this behavior by inspecting + TYPE_CANONICAL appropriately, taking advantage of the fact that + lookup_template_class links the two types by setting TYPE_CANONICAL of + the latter to the former. */ + if (entering_scope + && CLASS_TYPE_P (t) + && dependent_type_p (t) + && TYPE_CANONICAL (t) == TREE_TYPE (TYPE_TI_TEMPLATE (t))) + t = TYPE_CANONICAL (t); + return t; + } switch (TREE_CODE (t)) { case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (t)) - return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl); - - /* Fall through. */ case ENUMERAL_TYPE: case UNION_TYPE: + return tsubst_aggr_type_1 (t, args, complain, in_decl, entering_scope); + + default: + return tsubst (t, args, complain, in_decl); + } +} + +/* The part of tsubst_aggr_type that's shared with tsubst. */ + +static tree +tsubst_aggr_type_1 (tree t, + tree args, + tsubst_flags_t complain, + tree in_decl, + int entering_scope) +{ if (TYPE_TEMPLATE_INFO (t) && uses_template_parms (t)) { tree argvec; @@ -13892,10 +13919,6 @@ tsubst_aggr_type (tree t, else /* This is not a template type, so there's nothing to do. */ return t; - - default: - return tsubst (t, args, complain, in_decl); - } } /* Map from a FUNCTION_DECL to a vec of default argument instantiations, @@ -15812,9 +15835,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) switch (code) { case RECORD_TYPE: + if (TYPE_PTRMEMFUNC_P (t)) + return tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, complain, in_decl); + /* Fall through. */ case UNION_TYPE: case ENUMERAL_TYPE: - return tsubst_aggr_type (t, args, complain, in_decl, + return tsubst_aggr_type_1 (t, args, complain, in_decl, /*entering_scope=*/0); case ERROR_MARK: diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-alias1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-alias1.C new file mode 100644 index 00000000000..4ac69935054 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-alias1.C @@ -0,0 +1,23 @@ +// PR c++/105518 +// { dg-do compile { target c++11 } } + +struct integral_constant { + constexpr operator int() const { return 42; } +}; + +template +struct A { + using type = A; + static constexpr int value = N; +}; + +template +void f(T t) { + using impl = A; + [] (int) { + typename impl::type a; // { dg-bogus "'t' is not captured" } + return a.value; + }(0); +} + +template void f(integral_constant); -- 2.39.0.56.g57e2c6ebbe