From patchwork Fri Apr 10 18:08:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1269153 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Es8G5orv; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48zQxm3cF4z9sQx for ; Sat, 11 Apr 2020 04:08:58 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4B88C385BF81; Fri, 10 Apr 2020 18:08:55 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x831.google.com (mail-qt1-x831.google.com [IPv6:2607:f8b0:4864:20::831]) by sourceware.org (Postfix) with ESMTPS id D5025385B835 for ; Fri, 10 Apr 2020 18:08:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D5025385B835 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qt1-x831.google.com with SMTP id w24so2073228qts.11 for ; Fri, 10 Apr 2020 11:08:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=SFBUGLyvTVXUwZSHYJzIOP1wZWMmtTvrVK4ZHvJ9tRg=; b=Es8G5orvUHtKgZ19RF5t1xc4FSEiiijEY4UMDgnk+Rm61bpXU/1phhZ/jgkSmQF3mi GGN4xj5QNejHFXrwtjpzq63wT2zi6JGVyiXHODJSJCn2G/+TJrKmlqyoTReM2syHXl/I A+bHu7aQVr8GXTZMwoC9NuhZ2r2PTsIEXogAoN8U3em45I9S1pGwHw79u56G0t9MD+5M ObsS6poA0sOYoOzTQG6NciFAGvYy579MZK5tgezYTBHcEb7APwZMobtsi3gkNMeRW7JU m+tQmXfmuz2iweSZvw83n5e1PBNmh9gKWrNaHadfI4PAoFuhVllulyQ+cWXEfabten4X qg9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=SFBUGLyvTVXUwZSHYJzIOP1wZWMmtTvrVK4ZHvJ9tRg=; b=T5UKS9DT3hhq0svlU/9gmTlcgkVpDjUa4IYtIRVB8qopL7s0hAn8DCXx+VemISRzrb Z3ReuL3AnYWQLi/JShEvNN6wXlaO0fRZk4Rf+hrq/RXTFawZZw5tkt8alPGxl4973q7E lRf6b05GXnsJoFDyVeCkm67A4Z6NkG55HQWJzPMF7x9dKWqbrrW+aqFIQBkfSYyAgZZ5 5I2T1WB5PE3LrU94mwBjGu1J2yNVwo3H1QdyA1OfNZMrh/2WekJfy80NKSXB1YeirHpa 8QkGYXgSgXh6Kd1O3VLI3UrPVm6oNiJhq3SrxpsxHOBLBs5E29CLEn4vR39ZMbOsuDuC T6cg== X-Gm-Message-State: AGi0PuZ1NFGmPXqeeEr8fVA/xR5T8vYVSKRzBnwDWmPrsogvP6TDhOg3 hUBlaPfkf19SOD0U6AagcJo= X-Google-Smtp-Source: APiQypKC5/wexAIulSn/nJSXzwjnimZwsn+ife+qclTNYvm0srTaPykmAIkd4qKZs52b5UmtFyGBZw== X-Received: by 2002:ac8:646:: with SMTP id e6mr388395qth.191.1586542132068; Fri, 10 Apr 2020 11:08:52 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a8:1102:153f:b550:b1f2:3a4c? ([2620:10d:c091:480::7727]) by smtp.googlemail.com with ESMTPSA id u15sm2140927qte.91.2020.04.10.11.08.50 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 10 Apr 2020 11:08:50 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [PR C++ 94426] Lambda linkage Message-ID: <32e1aca1-2d0a-8973-6620-9df466ca7ad5@acm.org> Date: Fri, 10 Apr 2020 14:08:49 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-20.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" My fix for 94147 was confusing no-linkage with internal linkage, at the language level. That's wrong. (the std is confusing here, because it describes linkage of names (which is wrong), and lambdas have no names) Lambdas with extra-scope, have linkage. However, at the implementation-level that linkage is at least as restricted as the linkage of the extra-scope decl. Further, when instantiating a variable initialized by a lambda, we must determine the visibility of the variable itself, before instantiating its initializer. If the template arguments are internal (or no-linkage), the variable will have internal linkage, regardless of the linkage of the template it is instantiated from. We need to know that before instantiating the lambda, so we can restrict its linkage correctly. I'll commit this in a few days. nathan 2020-04-10 Nathan Sidwell PR c++/94426 = lambdas with internal linkage are different to no-linkage * decl2.c (determine_visibility): A lambda's visibility is affected by its extra scope. * pt.c (instantiate_decl): Determine var's visibility before instantiating its initializer. * tree.c (no_linkage_check): Revert code looking at visibility of lambda's extra scope. gcc/cp/ * g++.dg/cpp0x/lambda/pr94426-[12].C: New. * g++.dg/abi/lambda-vis.C: Drop a warning. * g++.dg/cpp0x/lambda/lambda-mangle.C: Lambda visibility on variable changes. * g++.dg/opt/dump1.C: Drop warnings of no import. diff --git c/gcc/cp/decl2.c w/gcc/cp/decl2.c index 6cf72b432e2..293df990435 100644 --- c/gcc/cp/decl2.c +++ w/gcc/cp/decl2.c @@ -2527,6 +2527,21 @@ determine_visibility (tree decl) else if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) template_decl = decl; + if (TREE_CODE (decl) == TYPE_DECL + && LAMBDA_TYPE_P (TREE_TYPE (decl)) + && CLASSTYPE_LAMBDA_EXPR (TREE_TYPE (decl)) != error_mark_node) + if (tree extra = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl))) + { + /* The lambda's visibility is limited by that of its extra + scope. */ + int vis = 0; + if (TYPE_P (extra)) + vis = type_visibility (extra); + else + vis = expr_visibility (extra); + constrain_visibility (decl, vis, false); + } + /* If DECL is a member of a class, visibility specifiers on the class can influence the visibility of the DECL. */ tree class_type = NULL_TREE; diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c index 050a57b2e2e..0a8ec3198d2 100644 --- c/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -25541,6 +25541,14 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p) c_inhibit_evaluation_warnings = 0; } + if (VAR_P (d)) + { + /* The variable might be a lambda's extra scope, and that + lambda's visibility depends on D's. */ + maybe_commonize_var (d); + determine_visibility (d); + } + /* Mark D as instantiated so that recursive calls to instantiate_decl do not try to instantiate it again. */ DECL_TEMPLATE_INSTANTIATED (d) = 1; diff --git c/gcc/cp/tree.c w/gcc/cp/tree.c index d1192b7e094..1d311b0fe61 100644 --- c/gcc/cp/tree.c +++ w/gcc/cp/tree.c @@ -2780,9 +2780,10 @@ verify_stmt_tree (tree t) cp_walk_tree (&t, verify_stmt_tree_r, &statements, NULL); } -/* Check if the type T depends on a type with no linkage and if so, return - it. If RELAXED_P then do not consider a class type declared within - a vague-linkage function to have no linkage. */ +/* Check if the type T depends on a type with no linkage and if so, + return it. If RELAXED_P then do not consider a class type declared + within a vague-linkage function to have no linkage. Remember: + no-linkage is not the same as internal-linkage*/ tree no_linkage_check (tree t, bool relaxed_p) @@ -2801,17 +2802,6 @@ no_linkage_check (tree t, bool relaxed_p) tree extra = LAMBDA_TYPE_EXTRA_SCOPE (t); if (!extra) return t; - - /* If the mangling scope is internal-linkage or not repeatable - elsewhere, the lambda effectively has no linkage. (Sadly - we're not very careful with the linkages of types.) */ - if (TREE_CODE (extra) == VAR_DECL - && !(TREE_PUBLIC (extra) - && (processing_template_decl - || (DECL_LANG_SPECIFIC (extra) && DECL_USE_TEMPLATE (extra)) - /* DECL_COMDAT is set too late for us to check. */ - || DECL_VAR_DECLARED_INLINE_P (extra)))) - return t; } /* Otherwise there's no point in checking linkage on template functions; we diff --git c/gcc/testsuite/g++.dg/abi/lambda-vis.C w/gcc/testsuite/g++.dg/abi/lambda-vis.C index 89683b2076a..c1033f501a3 100644 --- c/gcc/testsuite/g++.dg/abi/lambda-vis.C +++ w/gcc/testsuite/g++.dg/abi/lambda-vis.C @@ -2,7 +2,7 @@ // { dg-options "-fno-inline" } template int sfoo (T); // { dg-warning "used but never defined" } -template int gfoo (T); // { dg-warning "used but never defined" } +template int gfoo (T); // OK, but not completable template int ifoo (T); // OK template struct Wrapper {}; template Wrapper capture (T &&) {return Wrapper ();} diff --git c/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C w/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C index 7894ef3051e..ef4bad8698b 100644 --- c/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C +++ w/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle.C @@ -54,9 +54,12 @@ void bar() []{}(); } -// lambdas used in non-template, non-class body initializers are internal. +// lambdas used in namespace-scope initializers have the linkage of +// the decl // { dg-final { scan-assembler-not "weak\[^\n\r\]*_ZNKUlv" } } -// { dg-final { scan-assembler-not "weak\[^\n\r\]*variable" } } +// { dg-final { scan-assembler "weak\[^\n\r\]*variableMUlvE_clEv" { target c++14_down } } } +// in c++17 and up, this operator() become constexpr, no not emitted +// { dg-final { scan-assembler-not "weak\[^\n\r\]*variableMUlvE_clEv" { target c++17 } } } int variable = []{return 1;}(); // And a template instantiated with such a lambda is also internal. diff --git c/gcc/testsuite/g++.dg/cpp0x/lambda/pr94426-1.C w/gcc/testsuite/g++.dg/cpp0x/lambda/pr94426-1.C new file mode 100644 index 00000000000..ae7cbf03091 --- /dev/null +++ w/gcc/testsuite/g++.dg/cpp0x/lambda/pr94426-1.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++14 } } +// PR 94426 ICE mangling lambda +// { dg-options {-flto -O2} } + +template using Void = void; + +template bool Init (U) {return true;} +template bool VAR = Init ([] {}); + +template +Void> Foo (T) +{} + +void q () +{ + Foo ([] {}); +} diff --git c/gcc/testsuite/g++.dg/cpp0x/lambda/pr94426-2.C w/gcc/testsuite/g++.dg/cpp0x/lambda/pr94426-2.C new file mode 100644 index 00000000000..3db864c604b --- /dev/null +++ w/gcc/testsuite/g++.dg/cpp0x/lambda/pr94426-2.C @@ -0,0 +1,20 @@ +// { dg-do compile { target c++14 } } +// PR 94426 ICE mangling lambda + +template using Void = void; + +template bool Init (U) {return true;} +template bool VAR = Init ([] {}); + +template +Void> Foo (T) +{} + +void q () +{ + Foo ([] {}); +} + +// The instantiation of VAR becomes local +// { dg-final { scan-assembler {.local _Z3VARIZ1qvEUlvE_E} { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler {.comm _Z3VARIZ1qvEUlvE_E,1,1} { target { i?86-*-* x86_64-*-* } } } } diff --git c/gcc/testsuite/g++.dg/opt/dump1.C w/gcc/testsuite/g++.dg/opt/dump1.C index f813044456c..38ed055d5c6 100644 --- c/gcc/testsuite/g++.dg/opt/dump1.C +++ w/gcc/testsuite/g++.dg/opt/dump1.C @@ -312,7 +312,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) typename __add_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type - get(tuple<_Elements...>& __t) noexcept; // { dg-warning "used but never defined" } + get(tuple<_Elements...>& __t) noexcept; template struct _Index_tuple {}; @@ -387,7 +387,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) }; template typename _Bind_simple_helper<_Callable, _Args...>::__type - __bind_simple(_Callable&& __callable, _Args&&... __args) // { dg-warning "used but never defined" } + __bind_simple(_Callable&& __callable, _Args&&... __args) ; union _Any_data ; @@ -404,7 +404,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) { protected: static _Functor* - _M_get_pointer(const _Any_data& __source) // { dg-warning "used but never defined" } + _M_get_pointer(const _Any_data& __source) ; }; }; @@ -511,7 +511,7 @@ namespace std __attribute__ ((__visibility__ ("default"))) _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); } static pointer - allocate(_Alloc& __a, size_type __n) // { dg-warning "used but never defined" } + allocate(_Alloc& __a, size_type __n) ; template static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)