From patchwork Mon Sep 23 23:43:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988721 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=jU0IjZp1; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKMQ4pt4z1xsN for ; Tue, 24 Sep 2024 09:44:02 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7C6D7385B529 for ; Mon, 23 Sep 2024 23:44:00 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id B8C613858D39; Mon, 23 Sep 2024 23:43:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B8C613858D39 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B8C613858D39 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::62d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135020; cv=none; b=pYtw49UaVjq7L+BcW4BAaEUMHIViSqMVgiw0nPoFFU/Q3rOHErHhyjVPLdSKsX3E54y/IF2Zfbh47Ba1pweu7TcelmRu0ZmyQrtdV3eC3YcPOUA1NjxplzkK4x7wAefTXYgX8TKVI6RpO3XuD5JAzbaTUI8n4HHPbpgeyazYjk0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135020; c=relaxed/simple; bh=V4Bd7LbmvHidmbBWy4HRa2AuhMWPsry0d4hKRwzkvlk=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=KbGV/yjb1gJ5jychOfJFo/+OqTSBovrPd9iJbfrRhTqStzVQfEqbXqELZhJpfxO0rphCSfTl7Op+cI5dQp7oJtRqEdgRF8ooTJnIBc4vggP0i/alUq8qCSJgkupLZmcNJakzcJokquOG77cdaMir8+M6ABr4vNkfoWZwDp+PwPE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-2053f72319fso2983185ad.2; Mon, 23 Sep 2024 16:43:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135017; x=1727739817; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=cl7Tazh8XWGZja6Wb/Fn11GZnV5x8cQzB2/2Aqj50f8=; b=jU0IjZp1IVq6kLzOOA6rROIYHjtrxCI+ZKIHnwoQqBKg5iBHfUc4rezBMEf8J83++x KtSm7ttJg8ouRXeBMjwVKzkoUoZb5HAfuX/KjQW/skZ3YjqVP87ibql+meJd5IEpy7Yg 4AdFnUgzZw0ZJV7pkmJqxsLde9ZLGIgY1topjTyn/xrnMv88iTvbIpybfSO/fhDa7BQc nzo1eHvWGNxfKyYWDk23LPSY75Bogh/u1B/4XDNR9os/34UPLIXx1GZr7rLA80Q6GzxL hwYJrA3DBmJnfflkdl0qClerK9d3c3fMfoX50V4IrIVpSYoWJYNDgmYIdAnK5Jz3DQpf 4Yow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135017; x=1727739817; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=cl7Tazh8XWGZja6Wb/Fn11GZnV5x8cQzB2/2Aqj50f8=; b=dDz7sG2HsymCkg6c53NuddfFzwuC4aTQrrqZrfFO7Ou+RCby9e/CqnsSPvlztws8cR Ei+p+zB6KLvIgc0MoE3r5hSZcXYaBtv/U67E3ayBW6lTs3LJy6mgxi/F130VGW9N8nZ5 GFJVcSILwyCPLqzLZDv4h0374vbESxIohADo1pXaoMxlqG8MuHt6Jg9uWdxKWWWj9qKn 4WrwUzPtZCMPZ4BwVoQI4Jj5IAjoBh8xnR9PuuDraT9oyLrbuXGdbor5go8JxJDddXw2 vC4EyKQAqetF56DZcmUpW9th22q9lZcxZ5IDdoiZyPHjN+PTexwQRptbuIRD7KIz2Byy 6O7A== X-Forwarded-Encrypted: i=1; AJvYcCX47iej/haOu7FmDxUNSt7FKK+jBxyAkWV9sdJDXpftvK9ISxa8l+UIduiXjWyZ+ZslehtP8C0a@gcc.gnu.org X-Gm-Message-State: AOJu0Yx9BT/VP8xvbsHpmRsOpLZr7t3QP9ULGzrFnky4gN0bL0fgbKZG Xx+4c53stWMFFQDg73I9+SDceLMyrKpQ1Z0e/i/luV6wTjNgw411UGBP8A== X-Google-Smtp-Source: AGHT+IEzbljDMq8nxq8OJ7sE9mwJ3V7V7zzfdqqzlGTpiihcFImdLiH4x6ALknbX9kuw2YC00/0THQ== X-Received: by 2002:a17:902:ec8b:b0:205:8820:fe1c with SMTP id d9443c01a7336-208d83dff51mr83107165ad.5.1727135017445; Mon, 23 Sep 2024 16:43:37 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-20af1727c39sm983005ad.119.2024.09.23.16.43.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:43:36 -0700 (PDT) Message-ID: <66f1fd28.170a0220.16c8a7.03b1@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:43:32 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 01/10] libstdc++: Remove unnecessary 'static' from __is_specialization_of References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- This makes the declarations internal linkage, which is an ODR issue, and causes a future modules patch to fail regtest as it now detects attempted uses of TU-local entities in module CMIs. libstdc++-v3/ChangeLog: * include/std/format: Remove unnecessary 'static'. Signed-off-by: Nathaniel Shead --- libstdc++-v3/include/std/format | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index e963d7f79b3..d9014d111b1 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -361,10 +361,9 @@ namespace __format /// @cond undocumented template class _Class> - static constexpr bool __is_specialization_of = false; + constexpr bool __is_specialization_of = false; template class _Class, typename... _Args> - static constexpr bool __is_specialization_of<_Class<_Args...>, _Class> - = true; + constexpr bool __is_specialization_of<_Class<_Args...>, _Class> = true; namespace __format { From patchwork Mon Sep 23 23:43:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988722 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=JFDlTPRS; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKMs3HvPz1xsw for ; Tue, 24 Sep 2024 09:44:25 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8C806385DDCF for ; Mon, 23 Sep 2024 23:44:23 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) by sourceware.org (Postfix) with ESMTPS id 1797C385DC1B for ; Mon, 23 Sep 2024 23:44:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1797C385DC1B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1797C385DC1B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::429 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135043; cv=none; b=wdPmzPlDZm1ugjoVwHgoEIhfZMQvfr8hiJE6oVXzb4Qi1d16xAiofTksC1XUq9ohY/Q2hGjn6s4kKavmTPhAfcRG6Jtqakzw1EtX/AlinrRiPCb9eN25xOpenHlnk8djnoOA8maUNjSv/96tDC97HYM8i4XjZ1D7hIum1OrhoQE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135043; c=relaxed/simple; bh=sLu/38Q3Mw+sOWnu2deFw5BL+30CdDgLM/3djfHN0Yw=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=ZSHd0+Ge7UNN9EzE4NlClRWegZpZWu1T23wSdTJ6mqJthGOSbwnHwoidAqhcIz8/VkMKiIpyX2RS0PI0kW68OnMofL6bIqGV6Knd6nhyqnfKkFraMBICfASX2/waVDg0NEf4eH2UuvOfOGowjRXtfsMXjA5yy5D10PczScnsAsg= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-718e55bca81so607857b3a.2 for ; Mon, 23 Sep 2024 16:44:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135040; x=1727739840; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=rdbwhn2e4KGMo48efTOohHjOEdOlaF9vBNxqHr+rkXI=; b=JFDlTPRSGdXne76B4zjAxYApBzVzGCRCaqAQT4dyPJkGxsdOQPchM+ekWbRmspou6F x0+rdxQ8gl2zWwmyufm4g4lpsSrq/fRoXyc38F4GEXjTffN3R3SDutLoW+iFZR4hAvBZ Ef+I5/17qqexmuRbsVHpcN0kmG913E3JXtU+9Iszj2FiWDZvfEjHi7hBwq6MO5Lx9ry9 dpZ07ecJiR/4AhMvefx0JPBk1LKUTr1rNAxthxv02mwjobd5V5CZunkmYtxHDAmAj123 /OFfmvxvJ1/jQ2SRd6hMMNNlKdfoHbPVvgerjK/De4o/Yxzq8o/lRfVieCnld2mb8y8K jLyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135040; x=1727739840; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=rdbwhn2e4KGMo48efTOohHjOEdOlaF9vBNxqHr+rkXI=; b=PWiKWoKs2Q4LC25eUQ5AH2OI4tl+Uca0fwJVCpgOcOnQYeQ+3Wl+fBeiLnm837FVbR F6j6TsYAC+7C4OsXFXKOPRL8jTl2/pLXuIkt3/GKecXe2KLgcOl4/WAOR0ShSFWKy4cr pScGnPVdli5IBZ1ydmUuk8sonpxGbPbGKG67Rg6NkP8IzFXgo5pvD/h0YLbQoZo3Jut5 hPToC72j4dThfMJMFRIuWBuAZaqTkX2E6GqJ8akJN4vqjh60eSelEk5W5i8McBl/WhlH q+3jcpjEQ5TBTjNnCe8Bkj8p0HGc6wybYooNc7EPGSKFLV8NH0cBxNKfTCrhjsRAdtot dGVw== X-Gm-Message-State: AOJu0Yytk0qRZhFXgazwoPbjuyN3lcBW+1l5Mcu9sL1gB+qPLrNPACXt S0HRRbmWgti3k1HtZ1zkwTVq/sJme7nv0BF5tUSGEyL88Xx2A9vDdiQN8Q== X-Google-Smtp-Source: AGHT+IHOVA6aSTsLxafJ619xE6rFhvdBIIBDnuzhKYXRrKWG6fvOBYFqwwGKmyiPCQcCfrgDaTSEjQ== X-Received: by 2002:a05:6a00:2d02:b0:70d:2289:4c55 with SMTP id d2e1a72fcca58-7199ca343a1mr7688572b3a.5.1727135039811; Mon, 23 Sep 2024 16:43:59 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc8345b4sm151813b3a.29.2024.09.23.16.43.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:43:59 -0700 (PDT) Message-ID: <66f1fd3f.a70a0220.10bbdd.083b@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:43:55 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 02/10] c++: Update decl_linkage for C++11 References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch intends no change in functionality apart from the mangling difference noted; more tests are in patch 4 of this series, which adds a way to actually check what the linkage of decl_linkage provides more directly. Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- Currently modules code uses a variety of ad-hoc methods to attempt to determine whether an entity has internal linkage, which leads to inconsistencies and some correctness issues as different edge cases are neglected. While investigating this I discovered 'decl_linkage', but it doesn't seem to have been updated to account for the C++11 clarification that all entities declared in an anonymous namespace are internal. I'm not convinced that even in C++98 it was intended that e.g. types in anonymous namespaces should be external, but some tests in the testsuite rely on this, so for compatibility I restricted those modifications to C++11 and later. This should have relatively minimal impact as not much seems to actually rely on decl_linkage, but does change the mangling of symbols in anonymous namespaces slightly. Previously, we had namespace { int x; // mangled as '_ZN12_GLOBAL__N_11xE' static int y; // mangled as '_ZN12_GLOBAL__N_1L1yE' } but with this patch the x is now mangled like y (with the extra 'L'). For contrast, Clang currently mangles neither x nor y with the 'L'. Since this only affects internal-linkage entities I don't believe this should break ABI in any observable fashion. gcc/cp/ChangeLog: * name-lookup.cc (do_namespace_alias): Propagate TREE_PUBLIC for namespace aliases. * tree.cc (decl_linkage): Update rules for C++11. gcc/testsuite/ChangeLog: * g++.dg/modules/mod-sym-4.C: Update test to account for non-static internal-linkage variables new mangling. Signed-off-by: Nathaniel Shead --- gcc/cp/name-lookup.cc | 1 + gcc/cp/tree.cc | 92 +++++++++++++++--------- gcc/testsuite/g++.dg/modules/mod-sym-4.C | 4 +- 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index c7a693e02d5..50e169eca43 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -6610,6 +6610,7 @@ do_namespace_alias (tree alias, tree name_space) DECL_NAMESPACE_ALIAS (alias) = name_space; DECL_EXTERNAL (alias) = 1; DECL_CONTEXT (alias) = FROB_CONTEXT (current_scope ()); + TREE_PUBLIC (alias) = TREE_PUBLIC (DECL_CONTEXT (alias)); set_originating_module (alias); pushdecl (alias); diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index f43febed124..28e14295de4 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5840,7 +5840,7 @@ char_type_p (tree type) || same_type_p (type, wchar_type_node)); } -/* Returns the kind of linkage associated with the indicated DECL. Th +/* Returns the kind of linkage associated with the indicated DECL. The value returned is as specified by the language standard; it is independent of implementation details regarding template instantiation, etc. For example, it is possible that a declaration @@ -5857,53 +5857,75 @@ decl_linkage (tree decl) linkage first, and then transform that into a concrete implementation. */ - /* Things that don't have names have no linkage. */ - if (!DECL_NAME (decl)) - return lk_none; + /* An explicit type alias has no linkage. */ + if (TREE_CODE (decl) == TYPE_DECL + && !DECL_IMPLICIT_TYPEDEF_P (decl) + && !DECL_SELF_REFERENCE_P (decl)) + { + /* But this could be a typedef name for linkage purposes, in which + case we're interested in the linkage of the main decl. */ + if (decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)))) + decl = TYPE_MAIN_DECL (TREE_TYPE (decl)); + else + return lk_none; + } - /* Fields have no linkage. */ - if (TREE_CODE (decl) == FIELD_DECL) + /* Namespace-scope entities with no name usually have no linkage. */ + if (NAMESPACE_SCOPE_P (decl) + && (!DECL_NAME (decl) || IDENTIFIER_ANON_P (DECL_NAME (decl)))) + { + if (TREE_CODE (decl) == TYPE_DECL && !TYPE_ANON_P (TREE_TYPE (decl))) + /* This entity has a typedef name for linkage purposes. */; + else if (TREE_CODE (decl) == NAMESPACE_DECL && cxx_dialect >= cxx11) + /* An anonymous namespace has internal linkage since C++11. */ + return lk_internal; + else + return lk_none; + } + + /* Fields and parameters have no linkage. */ + if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == PARM_DECL) return lk_none; - /* Things in local scope do not have linkage. */ + /* Things in block scope do not have linkage. */ if (decl_function_context (decl)) return lk_none; + /* Things in class scope have the linkage of their owning class. */ + if (tree ctype = DECL_CLASS_CONTEXT (decl)) + return decl_linkage (TYPE_NAME (ctype)); + + /* Anonymous namespaces don't provide internal linkage in C++98, + but otherwise consider such declarations to be internal. */ + if (cxx_dialect >= cxx11 && decl_internal_context_p (decl)) + return lk_internal; + + /* Templates don't properly propagate TREE_PUBLIC, consider the + template result instead. Any template that isn't a variable + or function must be external linkage by this point. */ + if (TREE_CODE (decl) == TEMPLATE_DECL) + { + decl = DECL_TEMPLATE_RESULT (decl); + if (!decl || !VAR_OR_FUNCTION_DECL_P (decl)) + return lk_external; + } + /* Things that are TREE_PUBLIC have external linkage. */ if (TREE_PUBLIC (decl)) return lk_external; - /* maybe_thunk_body clears TREE_PUBLIC on the maybe-in-charge 'tor variants, - check one of the "clones" for the real linkage. */ - if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl) - && DECL_CHAIN (decl) - && DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl))) - return decl_linkage (DECL_CHAIN (decl)); - - if (TREE_CODE (decl) == NAMESPACE_DECL) + /* All types have external linkage in C++98, since anonymous namespaces + didn't explicitly confer internal linkage. */ + if (TREE_CODE (decl) == TYPE_DECL && cxx_dialect < cxx11) return lk_external; - /* Linkage of a CONST_DECL depends on the linkage of the enumeration - type. */ - if (TREE_CODE (decl) == CONST_DECL) - return decl_linkage (TYPE_NAME (DECL_CONTEXT (decl))); - - /* Members of the anonymous namespace also have TREE_PUBLIC unset, but - are considered to have external linkage for language purposes, as do - template instantiations on targets without weak symbols. DECLs really - meant to have internal linkage have DECL_THIS_STATIC set. */ - if (TREE_CODE (decl) == TYPE_DECL) + /* Variables or function decls not marked as TREE_PUBLIC might still + be external linkage, such as for template instantiations on targets + without weak symbols, decls referring to internal-linkage entities, + or compiler-generated entities; in such cases, decls really meant to + have internal linkage will have DECL_THIS_STATIC set. */ + if (VAR_OR_FUNCTION_DECL_P (decl) && !DECL_THIS_STATIC (decl)) return lk_external; - if (VAR_OR_FUNCTION_DECL_P (decl)) - { - if (!DECL_THIS_STATIC (decl)) - return lk_external; - - /* Static data members and static member functions from classes - in anonymous namespace also don't have TREE_PUBLIC set. */ - if (DECL_CLASS_CONTEXT (decl)) - return lk_external; - } /* Everything else has internal linkage. */ return lk_internal; diff --git a/gcc/testsuite/g++.dg/modules/mod-sym-4.C b/gcc/testsuite/g++.dg/modules/mod-sym-4.C index fbf54d00171..14fef4fe253 100644 --- a/gcc/testsuite/g++.dg/modules/mod-sym-4.C +++ b/gcc/testsuite/g++.dg/modules/mod-sym-4.C @@ -12,9 +12,9 @@ static void addone () {} static int x = 5; namespace { -// { dg-final { scan-assembler {_ZN12_GLOBAL__N_14frobEv:} } } +// { dg-final { scan-assembler {_ZN12_GLOBAL__N_1L4frobEv:} } } void frob () {} -// { dg-final { scan-assembler {_ZN12_GLOBAL__N_11yE:} } } +// { dg-final { scan-assembler {_ZN12_GLOBAL__N_1L1yE:} } } int y = 2; struct Bill { From patchwork Mon Sep 23 23:44:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988723 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=asUOvvlR; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKNN4hw6z1xsN for ; Tue, 24 Sep 2024 09:44:52 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7CC91385C6CC for ; Mon, 23 Sep 2024 23:44:50 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) by sourceware.org (Postfix) with ESMTPS id 9704F385DDC6 for ; Mon, 23 Sep 2024 23:44:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9704F385DDC6 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9704F385DDC6 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135072; cv=none; b=pqgQFyBmS8hSbLuRlMffZhKSoEfm/JWCG8JM+nuTzJ6bBnVdwF/eW4EkSBjpWW6oG7LZpU/N+2YlU7Q3SkFpmvzKlTsOWI3VxmEh40wLxKEhHoHg1qfCYbL/JUyimpRZOMU2rFR7laicLFHomYKmmU30xE/55LK8HlXFUZbEhj0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135072; c=relaxed/simple; bh=PA/lVxM7PVg9Q86it4XF/EwMhVJ8SQ4badLhbTDB8Gk=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=mW7oZDs5DjcI/x09NMo6uDwMbqca8QX51iXUWAEc4xHQBND17M8GW1/Ems/zdHhxvOzJQH4n0k3a32WozSWYoygYRJmP4HwBFgRXE2QC/IHzkaUYJ6VvLux3hcTtGkO/z9krKts4hMmQrze0PBnOv4YPsmMhmAVPgp1BiLgQ578= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-7db61fd92a1so272231a12.3 for ; Mon, 23 Sep 2024 16:44:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135068; x=1727739868; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=NIkkaSgeaR4YUVFTL+n/eTeJ7lk043CzFmNvKIS4yX8=; b=asUOvvlRZTk6Xkpphd6E7WPa0RU3FI6VinwJLVhdfdH6D+XhoGV4M6k8S5fozcT0cJ c9p4iQeFdTSttvoZR8nF+qeb3wS3zDJLj9piQBNq/ECk86vc5OdaEpF1CwE3sd5eDc0S kt/OUPw2MLXwJTggCjPoHRNE44NJLIudlbvr/1fCkCuNmfyX52cri7wOKTuBjsRovGmd 3xZ8+tfcFNMW0IZ0U+W+0oUUHAOCLqxAqkUptd3fWQ/OLSrV1VwidL4+X2XW1E9wuXwW MEaO3h05tiRUS0tiiq7pf65h+SbLWnViiH1mS332Vxp0x8Jp1xjwQYUgn/VTVf/aoLw/ X/8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135068; x=1727739868; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=NIkkaSgeaR4YUVFTL+n/eTeJ7lk043CzFmNvKIS4yX8=; b=uY6vUUewu+JDDAHiKppnARrFyQuQIZL7qimQja3Ko3UOJj9pgXAKGIDqrrFdTCZWiy ixi+gRQ+jceTzcAAwRO7Exl3M+T9DfMDwmmsRTqpCwYnUqng6SF+yXy/vGi3YVEbMMBn KsFTdqXNLx4hyWMiz4ee6218xZfxp0dEZOaJzr4mSUDTuNjbuMLnLOf/FmDkj0jXzuSE w12O/lbMB/dk9G8qIUyfOdzxoXP/RLu1JzCuozThbkf8CHBO5i0Sb+rHPRebFXBhFnYN Cj/Xong9CxE96KmU/p96N5sQL6/UerqKzD4c3oKKc/vqeia2uc1Rn0/jGym9PS+Bry+R 7Y6w== X-Gm-Message-State: AOJu0YypktfiKGNYqhyLBBvCt3dU7G1XK4unnxhCNYFymtuLfEszVxiY ngAyQpRv78NYWgMHv9FfrijdKXczzY/py54lvpksYPPw9Bfchnjd4oYIog== X-Google-Smtp-Source: AGHT+IEz/d9UMxkcO8pH5WhQjgZpfgZdOS8ePszAgYN5d2/vnwYxkZfzSnRpaX0acCjLrjygHhj2aQ== X-Received: by 2002:a05:6a20:2452:b0:1cf:43e0:d75f with SMTP id adf61e73a8af0-1d30a9f2180mr9708793637.7.1727135068438; Mon, 23 Sep 2024 16:44:28 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7e6b7c74574sm78085a12.73.2024.09.23.16.44.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:44:28 -0700 (PDT) Message-ID: <66f1fd5c.050a0220.7f01c.0345@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:44:24 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 03/10] c++/modules: Use decl_linkage in maybe_record_mergeable_decl References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org I don't currently have any testcases where this changes something, but I felt it to be a valuable cleanup. Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- This avoids any possible inconsistencies (current or future) about whether a declaration is internal or not. gcc/cp/ChangeLog: * name-lookup.cc (maybe_record_mergeable_decl): Use decl_linkage instead of ad-hoc checks. Signed-off-by: Nathaniel Shead --- gcc/cp/name-lookup.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 50e169eca43..c0f89f98d87 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -3725,17 +3725,10 @@ maybe_record_mergeable_decl (tree *slot, tree name, tree decl) if (TREE_CODE (*slot) != BINDING_VECTOR) return; - if (!TREE_PUBLIC (CP_DECL_CONTEXT (decl))) - /* Member of internal namespace. */ + if (decl_linkage (decl) == lk_internal) return; tree not_tmpl = STRIP_TEMPLATE (decl); - if ((TREE_CODE (not_tmpl) == FUNCTION_DECL - || VAR_P (not_tmpl)) - && DECL_THIS_STATIC (not_tmpl)) - /* Internal linkage. */ - return; - bool is_attached = (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_ATTACH_P (not_tmpl)); tree *gslot = get_fixed_binding_slot From patchwork Mon Sep 23 23:44:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988724 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=IXFUCYNT; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKP30WKZz1xsM for ; Tue, 24 Sep 2024 09:45:27 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E0362385DDCF for ; Mon, 23 Sep 2024 23:45:24 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536]) by sourceware.org (Postfix) with ESMTPS id 4EC71385B508 for ; Mon, 23 Sep 2024 23:44:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 4EC71385B508 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 4EC71385B508 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::536 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135097; cv=none; b=s6P8nGDMBrzhL9c5aImwINgr89JxEzw+hJOPjJrUc36WyzLxxIYGnjpA5Yct54I3qVf/I9n8jrCMAHaqbemBUmDnkO6MDX+MRYfdi/Z7hVtjdA8uvQIOxwQMctIHKRnxw5a0J8pSdI0QyAotfVO34TVTUXbHNiClQOdgPqLoivE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135097; c=relaxed/simple; bh=G9CGZyoUxtSHLKec13tXA/BpGNE35E/ipHpKq5wIlFM=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=jhd3nNrx8r6e5th3Z2FgF+PSxWEOTeRIwzdo1qYmHsbnsqsi1wQBydEh9x3oLVHb6Qv8rqYm0xpjaSzI58zQVNcOY/jwoYEVLw0LKOai8vHq9O5a/Qq6wgTgmhwRsSYZeuHjMOEYAx8e6BAryytbH00ySLrMwL21r5Hm3yDOcIU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x536.google.com with SMTP id 41be03b00d2f7-7db488c2a72so409195a12.3 for ; Mon, 23 Sep 2024 16:44:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135093; x=1727739893; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=u+LYgtlsGjkshNtpGr0rH4YrT7MghKEC6KpyRRQZXkg=; b=IXFUCYNTzhOQr2yEgFGJkp3sg1yKr6sGCK6ypiryiJLfVvonorriK21cktKfjcXjxm ztUpRFZVItr7TtN8MQ03vzmUVbe4ptb2eirybVG4OXfIPz4sSDsb0bndb0sEPj4snZSV +8n2Dv2CqIW1cojlDkiP9vZrfBTUC45qQYDTYkDwOtTNvk9yGVDM/zuT7nK/9/yV6hfk UyM3OhoSVeNg3lAe3oFBza+CMWIENW+7P9l/7uOtgvoBLrL3tJ7UVBSW7o7xcMLcdWrW JJ7bbTqRx8f5At57D79R3YlWcMvLv1ABpWnsemDoQ6vlJULU2Weqeg2xVADZ8xm6Rdaa CVgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135093; x=1727739893; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=u+LYgtlsGjkshNtpGr0rH4YrT7MghKEC6KpyRRQZXkg=; b=XlSOa1xQoZOXs/hv+6Ey3QwWweBXvt/VXMRbpaTcChiBELTkMSLIXho/2QAHbq1n8p t0tD2Ms6Vjo3G+rfra6pPVAlm7VsXpvZD8qPNBIg94KzC2OFOPFjDc93R16WDXowX3Vb 5v5zTaNprIEKjf+o9ZUjPsNE2aO4pm8kkxpchirFS/Q+DB7miy2zm0uv+Pb+jcbDLqCk r0+hkVpns3vbttS1ZPPB2K9K2pRXD2jMSvhMyoW4IaFBIBLrCijHSvskMSqP9UYqIwEA rac3dNlon5yav3qfb13VOyiLVqbXSDeBYdWKJ3MLSGqWCWhcH5Lk8e759/tHBKh15GA+ X6VQ== X-Gm-Message-State: AOJu0YzZlWmHksMJ83Q7SLvI0gAJVYuBT82kdNdpAiL3o+By/y98910b DRlh12m24hKDWxHom1wZ9NLgJm7rn/03QpoksJT6czznlra3PhXmTMvg3w== X-Google-Smtp-Source: AGHT+IGrGGwHJS+/QdezbgAMjS70iTd2pRL6XvE8lm6vhhyMlb3EPCdO2SGdUPnZ/WRu9K1MNVUnuA== X-Received: by 2002:a05:6a00:4b4c:b0:70b:705f:dda7 with SMTP id d2e1a72fcca58-7199c9f0bf6mr7906628b3a.4.1727135093042; Mon, 23 Sep 2024 16:44:53 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc9c7459sm146695b3a.204.2024.09.23.16.44.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:44:52 -0700 (PDT) Message-ID: <66f1fd74.a70a0220.265533.05f6@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:44:48 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 04/10] c++/modules: Fix linkage checks for exported using-decls References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- This fixes some inconsistencies with what kinds of linkage various entities are assumed to have. This also fixes handling of exported using-decls binding to GM entities and type aliases to better align with the standard's requirements. gcc/cp/ChangeLog: * name-lookup.cc (check_can_export_using_decl): Handle internal linkage GM entities, and use linkage of entity ultimately referred to by aliases. gcc/testsuite/ChangeLog: * g++.dg/modules/using-10.C: Add tests for no-linkage, fix expected linkage of aliases. * g++.dg/modules/using-12.C: Likewise. * g++.dg/modules/using-27.C: New test. * g++.dg/modules/using-28_a.C: New test. * g++.dg/modules/using-28_b.C: New test. Signed-off-by: Nathaniel Shead Signed-off-by: Nathaniel Shead --- gcc/cp/name-lookup.cc | 55 ++++++++++++---------- gcc/testsuite/g++.dg/modules/using-10.C | 56 ++++++++++++++++++----- gcc/testsuite/g++.dg/modules/using-12.C | 42 +++++++++++++++-- gcc/testsuite/g++.dg/modules/using-27.C | 14 ++++++ gcc/testsuite/g++.dg/modules/using-28_a.C | 12 +++++ gcc/testsuite/g++.dg/modules/using-28_b.C | 8 ++++ 6 files changed, 145 insertions(+), 42 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/using-27.C create mode 100644 gcc/testsuite/g++.dg/modules/using-28_a.C create mode 100644 gcc/testsuite/g++.dg/modules/using-28_b.C diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index c0f89f98d87..cbb2827808f 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -5206,38 +5206,43 @@ pushdecl_outermost_localscope (tree x) static bool check_can_export_using_decl (tree binding) { - tree decl = STRIP_TEMPLATE (binding); - - /* Linkage is determined by the owner of an enumerator. */ - if (TREE_CODE (decl) == CONST_DECL) - decl = TYPE_NAME (DECL_CONTEXT (decl)); - - /* If the using decl is exported, the things it refers - to must also be exported (or not have module attachment). */ - if (!DECL_MODULE_EXPORT_P (decl) - && (DECL_LANG_SPECIFIC (decl) - && DECL_MODULE_ATTACH_P (decl))) + /* We want the linkage of the underlying entity, so strip typedefs. + If the underlying entity is a builtin type then we're OK. */ + tree entity = binding; + if (TREE_CODE (entity) == TYPE_DECL) { - bool internal_p = !TREE_PUBLIC (decl); + entity = TYPE_MAIN_DECL (TREE_TYPE (entity)); + if (!entity) + return true; + } + + linkage_kind linkage = decl_linkage (entity); + tree not_tmpl = STRIP_TEMPLATE (entity); - /* A template in an anonymous namespace doesn't constrain TREE_PUBLIC - until it's instantiated, so double-check its context. */ - if (!internal_p && TREE_CODE (binding) == TEMPLATE_DECL) - internal_p = decl_internal_context_p (decl); + /* Attachment is determined by the owner of an enumerator. */ + if (TREE_CODE (not_tmpl) == CONST_DECL) + not_tmpl = TYPE_NAME (DECL_CONTEXT (not_tmpl)); + /* If the using decl is exported, the things it refers to must + have external linkage. decl_linkage returns lk_external for + module linkage so also check for attachment. */ + if (linkage != lk_external + || (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_ATTACH_P (not_tmpl) + && !DECL_MODULE_EXPORT_P (not_tmpl))) + { auto_diagnostic_group d; error ("exporting %q#D that does not have external linkage", binding); - if (TREE_CODE (decl) == TYPE_DECL && !DECL_IMPLICIT_TYPEDEF_P (decl)) - /* An un-exported explicit type alias has no linkage. */ - inform (DECL_SOURCE_LOCATION (binding), - "%q#D declared here with no linkage", binding); - else if (internal_p) - inform (DECL_SOURCE_LOCATION (binding), - "%q#D declared here with internal linkage", binding); + if (linkage == lk_none) + inform (DECL_SOURCE_LOCATION (entity), + "%q#D declared here with no linkage", entity); + else if (linkage == lk_internal) + inform (DECL_SOURCE_LOCATION (entity), + "%q#D declared here with internal linkage", entity); else - inform (DECL_SOURCE_LOCATION (binding), - "%q#D declared here with module linkage", binding); + inform (DECL_SOURCE_LOCATION (entity), + "%q#D declared here with module linkage", entity); return false; } diff --git a/gcc/testsuite/g++.dg/modules/using-10.C b/gcc/testsuite/g++.dg/modules/using-10.C index d468a36f5d8..6f82b5dd147 100644 --- a/gcc/testsuite/g++.dg/modules/using-10.C +++ b/gcc/testsuite/g++.dg/modules/using-10.C @@ -23,6 +23,13 @@ namespace s { } } +export using s::a1; // { dg-error "does not have external linkage" } +export using s::b1; // { dg-error "does not have external linkage" } +export using s::x1; // { dg-error "does not have external linkage" } +export using s::y1; // { dg-error "does not have external linkage" } +export using s::f1; // { dg-error "does not have external linkage" } +export using s::g1; // { dg-error "does not have external linkage" } + // module linkage namespace m { struct a2 {}; // { dg-message "declared here with module linkage" } @@ -41,13 +48,6 @@ namespace m { void g2(); // { dg-message "declared here with module linkage" } } -export using s::a1; // { dg-error "does not have external linkage" } -export using s::b1; // { dg-error "does not have external linkage" } -export using s::x1; // { dg-error "does not have external linkage" } -export using s::y1; // { dg-error "does not have external linkage" } -export using s::f1; // { dg-error "does not have external linkage" } -export using s::g1; // { dg-error "does not have external linkage" } - export using m::a2; // { dg-error "does not have external linkage" } export using m::b2; // { dg-error "does not have external linkage" } export using m::x2; // { dg-error "does not have external linkage" } @@ -55,15 +55,47 @@ export using m::y2; // { dg-error "does not have external linkage" } export using m::f2; // { dg-error "does not have external linkage" } export using m::g2; // { dg-error "does not have external linkage" } +// no linkage +namespace n { + using a3 = struct { int x; }; // { dg-message "declared here with no linkage" } + + struct {} tmp_s; // { dg-message "declared here with no linkage" } + using b3 = decltype(tmp_s); + + enum {} tmp_e; // { dg-message "declared here with no linkage" } + using c3 = decltype(tmp_e); + + auto foo() { + struct s {}; // { dg-message "declared here with no linkage" } + return s{}; + } + using d3 = decltype(foo()); +} + +export using n::a3; // { dg-error "does not have external linkage" } +export using n::b3; // { dg-error "does not have external linkage" } +export using n::c3; // { dg-error "does not have external linkage" } +export using n::d3; // { dg-error "does not have external linkage" } + +// typedefs namespace t { - using a = int; // { dg-message "declared here with no linkage" } + // aliases have the linkage of the entity they ultimately refer to + using a = int; + typedef a b; + // a template is not an alias template - using b = int; // { dg-message "declared here with no linkage" } + using c = int; // { dg-message "declared here with module linkage" } + + // anonymous type with typedef name for linkage purposes + typedef struct {} d; // { dg-message "declared here with module linkage" } - typedef int c; // { dg-message "declared here with no linkage" } + // non-empty enum gets linkage of enumerator name + enum { X } e; // { dg-message "declared here with module linkage"} } -export using t::a; // { dg-error "does not have external linkage" } -export using t::b; // { dg-error "does not have external linkage" } +export using t::a; +export using t::b; export using t::c; // { dg-error "does not have external linkage" } +export using t::d; // { dg-error "does not have external linkage" } +export using t::e; // { dg-error "does not have external linkage" } diff --git a/gcc/testsuite/g++.dg/modules/using-12.C b/gcc/testsuite/g++.dg/modules/using-12.C index 52ef3c6285d..4fd71696f62 100644 --- a/gcc/testsuite/g++.dg/modules/using-12.C +++ b/gcc/testsuite/g++.dg/modules/using-12.C @@ -57,15 +57,47 @@ namespace m { export using m::g2; // { dg-error "does not have external linkage" } } +// no linkage +namespace n { + using a3 = struct { int x; }; // { dg-message "declared here with no linkage" } + + struct {} tmp_s; // { dg-message "declared here with no linkage" } + using b3 = decltype(tmp_s); + + enum {} tmp_e; // { dg-message "declared here with no linkage" } + using c3 = decltype(tmp_e); + + auto foo() { + struct s {}; // { dg-message "declared here with no linkage" } + return s{}; + } + using d3 = decltype(foo()); + + export using n::a3; // { dg-error "does not have external linkage" } + export using n::b3; // { dg-error "does not have external linkage" } + export using n::c3; // { dg-error "does not have external linkage" } + export using n::d3; // { dg-error "does not have external linkage" } +} + +// typedefs namespace t { - using a = int; // { dg-message "declared here with no linkage" } + // aliases have the linkage of the entity they ultimately refer to + using a = int; + typedef a b; + // a template is not an alias template - using b = int; // { dg-message "declared here with no linkage" } + using c = int; // { dg-message "declared here with module linkage" } + + // anonymous type with typedef name for linkage purposes + typedef struct {} d; // { dg-message "declared here with module linkage" } - typedef int c; // { dg-message "declared here with no linkage" } + // non-empty enum gets linkage of enumerator name + enum { X } e; // { dg-message "declared here with module linkage" } - export using t::a; // { dg-error "does not have external linkage" } - export using t::b; // { dg-error "does not have external linkage" } + export using t::a; + export using t::b; export using t::c; // { dg-error "does not have external linkage" } + export using t::d; // { dg-error "does not have external linkage" } + export using t::e; // { dg-error "does not have external linkage" } } diff --git a/gcc/testsuite/g++.dg/modules/using-27.C b/gcc/testsuite/g++.dg/modules/using-27.C new file mode 100644 index 00000000000..857d7d4a035 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-27.C @@ -0,0 +1,14 @@ +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi !bad } + +module; + +static int x = 123; // { dg-message "declared here with internal linkage" } +static void f() {} // { dg-message "declared here with internal linkage" } +using T = struct {}; // { dg-message "declared here with no linkage" } + +export module bad; + +export using ::x; // { dg-error "does not have external linkage" } +export using ::f; // { dg-error "does not have external linkage" } +export using ::T; // { dg-error "does not have external linkage" } diff --git a/gcc/testsuite/g++.dg/modules/using-28_a.C b/gcc/testsuite/g++.dg/modules/using-28_a.C new file mode 100644 index 00000000000..96bbef57f64 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-28_a.C @@ -0,0 +1,12 @@ +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi M } +// Test that typedef names correctly provide external linkage + +module; +typedef struct { int x; } A; +export module M; + +export typedef struct {} B; + +export using ::A; +export using ::B; diff --git a/gcc/testsuite/g++.dg/modules/using-28_b.C b/gcc/testsuite/g++.dg/modules/using-28_b.C new file mode 100644 index 00000000000..72876b517ca --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-28_b.C @@ -0,0 +1,8 @@ +// { dg-additional-options "-fmodules-ts" } + +import M; + +int main() { + A a { 10 }; + B b; +} From patchwork Mon Sep 23 23:45:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988725 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=j0IQH++K; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKPj6LTzz1xsM for ; Tue, 24 Sep 2024 09:46:01 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AFBE53858414 for ; Mon, 23 Sep 2024 23:45:59 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) by sourceware.org (Postfix) with ESMTPS id 8CF3F3858431 for ; Mon, 23 Sep 2024 23:45:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8CF3F3858431 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8CF3F3858431 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135121; cv=none; b=NO676MF1Wn4eG7BXE8y752VimrCLe8Yx+uiHQx3IGEE0WVrrTUorRUJZIujRr+rc7igCpewxQA7u4W/nP95MVSXN616tzNXQBBJ2KW9nSasH4YrEprQmTxbbM6mQynHjdvpqZ+m65qehOokYhx1MEdLG5mbwK2XADlN8B81z3aE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135121; c=relaxed/simple; bh=4fzKmB7tUn92tlpBeR0WMKla9oTw+hTrnA2wEGV2NvY=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=dzWD9NNNp3nrBn1TwlJ67m3IH3/0ilnOU/7bZV3XCJqAKmhYKB4Uz4J2uEqKwk4PMspoHZAMHGBZmUa56Q3Q0yYi4/zDnBNc6crQWgExvPHCAyeGd6CbeMh+5Mxj69AUqfVnNG32OOkETXGDqMlt00/fvPOJwSY94OgjXU1TxaU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x52e.google.com with SMTP id 41be03b00d2f7-7d50e844d48so393450a12.1 for ; Mon, 23 Sep 2024 16:45:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135118; x=1727739918; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=uvftdMVQ3iSO8/2PFV+8G2pvwZ41CpVb55O2R+ceY80=; b=j0IQH++KZxe1+XToKWe9ULEdIQ4HF8rJaTLPw0TBO47ztPwEuu+vLy6QxNs+FxsO7a 2+xb86SAmKiuYM9RZFE62FveS/mNuZHNG9z2pT3BcYqsLZbbIO+uPq1RbHFWd0rlnAuO 75t6Ob+LBW30vnbOr9fr8tcECdzUIpqs9LuTiPNoySswaIQLw5Q3pe44U9PA0mEKVIAb FBlu1rlCr1TGeDqtfbUXHRS7mvxC+2+bRXSWY+Rlr7uYxYH0fnixe8ZiFTA22BO27ZPD ocSpswwyM13wUSq1XPj5p3NOxwUtmjgkv4LMJfoG00ctJB7HQFsfCjN2SZY9B+zpg6ZF ggzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135118; x=1727739918; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=uvftdMVQ3iSO8/2PFV+8G2pvwZ41CpVb55O2R+ceY80=; b=BbGTyOJghyojQW7ev2M1LiEIdPnE0rkNCgQA9cwkQ+vjiNT3EX7ox4s5us7OmsQQ+O nYm5mfg0Wsvu749tr9FG/DVDv9ItbINNYhOgOeceQUp4/vSRKoQ22mkbhzirAK3sb3C7 3Cf47aWM5w6eOloAh7qJ/lFi3dg465Xx+td3W9cDrz/oPhGYl+D1G12giW53dmq1toQN ieixZR8Gm9WwBQo9QiNFsxJyndnIJro5p8uX8MAtRgxy2YS5oNSpr2MDvSlXmjLM62b+ 4s6cywdHEKu61gIaM8u06R11UFWutI6aOVpZeBKxj/qgntT/UPaEV43B95JXdRfmjC3h 4xLA== X-Gm-Message-State: AOJu0YzkT7IVCZiR7qOT6mhSarf5OrT8/yLVdr+CcurjWsR7Nm30iouY ZpnJShIeyA6XEs95PxCynId/yreyZHtAX6Vs08y69WP+6gOLhuoDOt1WLA== X-Google-Smtp-Source: AGHT+IEpD7fMNbKWPxnH0gD8iBJPLjpGwIxhS/PVQW/sQDgl8xfbhWoCn+ACNBV/h7cmIs7bD6/j7Q== X-Received: by 2002:a17:90b:3a88:b0:2d8:9ce8:f4e0 with SMTP id 98e67ed59e1d1-2e05811e57fmr418802a91.5.1727135118443; Mon, 23 Sep 2024 16:45:18 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e05904a091sm194220a91.52.2024.09.23.16.45.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:45:18 -0700 (PDT) Message-ID: <66f1fd8e.170a0220.2e1c55.07f2@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:45:14 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 05/10] c++/modules: Allow imported references in constant expressions References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- Currently the streaming code uses TREE_CONSTANT to determine whether an entity will have a definition that is interesting to stream out. This is not sufficient, however; we also need to write the definition of references, since although not TREE_CONSTANT they can still be usable in constant expressions. gcc/cp/ChangeLog: * module.cc (has_definition): Also write definition of references initialized with a constant expression. gcc/testsuite/ChangeLog: * g++.dg/modules/cexpr-5_a.C: New test. * g++.dg/modules/cexpr-5_b.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/module.cc | 6 +++++- gcc/testsuite/g++.dg/modules/cexpr-5_a.C | 13 +++++++++++++ gcc/testsuite/g++.dg/modules/cexpr-5_b.C | 9 +++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/modules/cexpr-5_a.C create mode 100644 gcc/testsuite/g++.dg/modules/cexpr-5_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index f5df9e875d3..7589de2348d 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -11829,7 +11829,11 @@ has_definition (tree decl) since there's no TU to emit them in otherwise. */ return true; - if (!TREE_CONSTANT (decl)) + if (!TREE_CONSTANT (decl) + /* A reference is never TREE_CONSTANT, but still stream its + definition if it's usable in constant expressions. */ + && !(TYPE_REF_P (TREE_TYPE (decl)) + && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))) return false; return true; diff --git a/gcc/testsuite/g++.dg/modules/cexpr-5_a.C b/gcc/testsuite/g++.dg/modules/cexpr-5_a.C new file mode 100644 index 00000000000..3a9f00523f6 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/cexpr-5_a.C @@ -0,0 +1,13 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi M } + +export module M; + +int x = 123; +void f() {} + +int& xr = x; +auto& fr = f; + +constexpr int& cxr = xr; +constexpr auto& cfr = fr; diff --git a/gcc/testsuite/g++.dg/modules/cexpr-5_b.C b/gcc/testsuite/g++.dg/modules/cexpr-5_b.C new file mode 100644 index 00000000000..4b1b901104b --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/cexpr-5_b.C @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } + +module M; + +constexpr auto& use_xr = xr; +constexpr auto& use_fr = fr; + +static_assert(&cxr == &use_xr); +static_assert(&cfr == &use_fr); From patchwork Mon Sep 23 23:45:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988727 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=hmYJPxK1; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKR922vmz1xsM for ; Tue, 24 Sep 2024 09:47:17 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2309E385DDED for ; Mon, 23 Sep 2024 23:47:15 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by sourceware.org (Postfix) with ESMTPS id C65893858D26 for ; Mon, 23 Sep 2024 23:45:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C65893858D26 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C65893858D26 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1031 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135148; cv=none; b=v528zWkZWT/m7nbaOL8qLstgXGOiiVjn/PwfiSP8iiW5O12/TY36JQ0XUUBdmuaEngsKElwCxcD06UYB3g1PasDbxODQgkMDFECV7lpOvwKYq7NjvXyZvDxlNUcffBcCjbizBSNXiLQX79+sGd3gvU0q0Jqhe1MFw2o/a21qsTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135148; c=relaxed/simple; bh=75QWj/ICI2tRQpP82eQXfd0uy9hkCijlWUiU7KcFM+Y=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=aD+7/+YTSLCB7aunkHadecggReeFKXrjlKdT5QuYpoTMDaOdhL6HsNEAL2kf+Dar/uRUrAO14s+O5kmDsQzIqm9EAMBLkH3RFwo5jgb9qj2TOUrtJOjkBhlZ8ck+Gcz0wKaKVImAPpiv+KK+fQ00UCN393TvVcvioKZ/vjnsA+s= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x1031.google.com with SMTP id 98e67ed59e1d1-2da516e6940so947026a91.3 for ; Mon, 23 Sep 2024 16:45:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135142; x=1727739942; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=G3ple2NBTvT24Ukd280YXdXHrqR3teDykN4q1kAuHv8=; b=hmYJPxK1hZ1o6uxqxS3YEBwSUQ9w5NRA/o7hr4gEj5SN/bjZIC4TflYES0mjCjctrn En7/QXkRV4HKioROiCEjMnfMhsZP84L6bKvZulWHJZzxyNEE+56S5kVeHKj34saOZoXw I3w+prS44mtz9MuvaSPh8uQv+cVvkDJy2COvkUaMl9BYcRyHFt3vNU9Pl7b7ARIPy6Zb zhxBFKKH3WB3SMXads3gSX5NFAmvsGVpsSVBunD3Gg8euMhCn5kbutVDbRK8kH1EnAzi fcY8ptmVanCHEeIPJmwJg0YFL/a2qu1/B+l2Yu4lIOwLDBxVQbLzU/P5KXYdPlFQMlUV uEjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135142; x=1727739942; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=G3ple2NBTvT24Ukd280YXdXHrqR3teDykN4q1kAuHv8=; b=Dm/GazbWAlKcME7lb29FpAIk8dhELPft5ME7ZBBXbB8z4LsiS1nr+OYtmwHvo8YTuC ZBYS5XUgA+sVJON+66hHCBKFOisRE01KeAA8QounBMU8qKTOORdgCnJK4Ymazc4NAJgC LQXesf4IdCWHoVrlzHp09qxv0uFYTdi9iuXAfi7wHxNGUGwDlbcHL0JbCvewG9tXL1/F PWHLJVnTMFJfxkd9Gl1rUE4IsIWz6AvfCJTdxzjS9lUrZ5jiRJgMk1OtGg843aUlKOvl yYQ5LCizvfIH1T7qIkVmvYeV7g9mAcpgxwOsPz/CqpKid3te8ir4LhlwMyo/b5RzssTD XOQw== X-Gm-Message-State: AOJu0YzXG1SVvEQCso3TrQqqnKE2KiaZKdbs+h4giF3gx8KNZpkLiseW ABiVgLlSTEr0HzTkUS8WwL3RiROHpm05coQgo51RttA/OyGfgPfih/4P/w== X-Google-Smtp-Source: AGHT+IGPSqzQtyq037OFIM8wgsg555AxrVRvbJoGxOp960l7MVMSQEP7ob+FtcxixuzSU+aVcp1VrQ== X-Received: by 2002:a17:90a:ac02:b0:2d8:792e:9b22 with SMTP id 98e67ed59e1d1-2dd7f17e9c9mr6333741a91.0.1727135142229; Mon, 23 Sep 2024 16:45:42 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2dd6ee8402bsm10030027a91.10.2024.09.23.16.45.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:45:41 -0700 (PDT) Message-ID: <66f1fda5.170a0220.11cf4c.6884@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:45:37 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 06/10] c++/modules: Detect exposures of TU-local entities References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org I feel like there should be a way to make use of LAMBDA_TYPE_EXTRA_SCOPE to avoid the need for the new TYPE_DEFINED_IN_INITIALIZER_P flag, perhaps once something like my patch here[1] is accepted (but with further embellishments for concepts, probably), but I wasn't able to work it out. Since currently as far as I'm aware only lambdas can satisfy being a type with no name defined in an 'initializer' this does seem a little overkill but I've applied it to all class types just in case. [1]: https://gcc.gnu.org/pipermail/gcc-patches/2024-September/662393.html Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- Currently, the modules streaming code implements some checks for declarations in the CMI that reference (some kinds of) internal-linkage entities, and errors if so. This patch expands on that support to implement the logic for exposures of TU-local entities as defined in [basic.link] since P1815. This will cause some code that previously errored in modules to start compiling; for instance, template specialisations of internal linkage functions. However, some code that previously appeared valid will with this patch no longer compile, notably some kinds of usages of internal linkage functions included from the GMF. This appears to be related to P2808 and FR-025, however as yet there doesn't appear to be consensus for changing these rules so I've implemented them as-is. This patch leaves a couple of things out. In particular, a couple of the rules for what is a TU-local entity currently seem to me to be redundant; I've left them as FIXMEs to be handled once I can find testcases that aren't adequately supported by the other logic here. Additionally, there are some exceptions for when naming a TU-local entity is not always an exposure; I've left support for this to a follow-up patch for easier review, as it has broader implications for streaming. Finally, this patch makes a couple of small adjustments to the modules streaming logic to prune any leftover TU-local deps (that aren't erroneous exposures). This is required for this patch to ensure that later stages don't get confused by any leftover TU-local entities floating around. gcc/cp/ChangeLog: * cp-tree.h (TYPE_DEPENDENT_P_VALID): Fix whitespace. (TYPE_DEFINED_IN_INITIALIZER_P): New accessor. * module.cc (DB_IS_INTERNAL_BIT): Rename to... (DB_TU_LOCAL_BIT): ...this. (DB_REFS_INTERNAL_BIT): Rename to... (DB_EXPOSURE_BIT): ...this. (depset::hash::is_internal): Rename to... (depset::hash::is_tu_local): ...this. (depset::hash::refs_internal): Rename to... (depset::hash::is_exposure): ...this. (depset::hash::is_tu_local_entity): New function. (depset::hash::has_tu_local_tmpl_arg): New function. (depset::hash::is_tu_local_value): New function. (depset::hash::make_dependency): Check for TU-local entities. (depset::hash::add_dependency): Make current an exposure whenever it references a TU-local entity. (depset::hash::add_binding_entity): Don't create bindings for any TU-local entity. (depset::hash::finalize_dependencies): Rename flags and adjust diagnostic messages to report exposures of TU-local entities. (depset::tarjan::connect): Don't include any TU-local depsets. (depset::hash::connect): Likewise. * parser.h (struct cp_parser::in_initializer_p): New flag. * parser.cc (cp_debug_parser): Print the new flag. (cp_parser_new): Set the new flag to false. (cp_parser_lambda_expression): Mark whether the lambda was defined in an initializer. (cp_parser_initializer): Set the new flag to true while parsing. (cp_parser_class_head): Mark whether the class was defined in an initializer. (cp_parser_concept_definition): Set the new flag to true while parsing. gcc/testsuite/ChangeLog: * g++.dg/modules/block-decl-2.C: Adjust messages. * g++.dg/modules/internal-1.C: Adjust messages, remove XFAILs. * g++.dg/modules/linkage-2.C: Adjust messages, remove XFAILS. * g++.dg/modules/internal-3.C: New test. * g++.dg/modules/internal-4.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/cp-tree.h | 7 +- gcc/cp/module.cc | 388 +++++++++++++++++--- gcc/cp/parser.cc | 16 + gcc/cp/parser.h | 3 + gcc/testsuite/g++.dg/modules/block-decl-2.C | 2 +- gcc/testsuite/g++.dg/modules/internal-1.C | 15 +- gcc/testsuite/g++.dg/modules/internal-3.C | 18 + gcc/testsuite/g++.dg/modules/internal-4.C | 112 ++++++ gcc/testsuite/g++.dg/modules/linkage-2.C | 5 +- 9 files changed, 493 insertions(+), 73 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/internal-3.C create mode 100644 gcc/testsuite/g++.dg/modules/internal-4.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7baa2ccbe1e..99fbd905896 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -534,6 +534,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; AUTO_IS_DECLTYPE (in TEMPLATE_TYPE_PARM) TEMPLATE_TEMPLATE_PARM_SIMPLE_P (in TEMPLATE_TEMPLATE_PARM) 6: TYPE_DEPENDENT_P_VALID + 7: TYPE_DEFINED_IN_INITIALIZER_P Usage of DECL_LANG_FLAG_?: 0: DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL) @@ -2292,7 +2293,11 @@ enum languages { lang_c, lang_cplusplus }; /* True if dependent_type_p has been called for this type, with the result that TYPE_DEPENDENT_P is valid. */ -#define TYPE_DEPENDENT_P_VALID(NODE) TYPE_LANG_FLAG_6(NODE) +#define TYPE_DEPENDENT_P_VALID(NODE) TYPE_LANG_FLAG_6 (NODE) + +/* True if this type was defined in an initializer. Used for determining + whether an entity is TU-local. */ +#define TYPE_DEFINED_IN_INITIALIZER_P(NODE) TYPE_LANG_FLAG_7 (NODE) /* Nonzero if this type is const-qualified. */ #define CP_TYPE_CONST_P(NODE) \ diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 7589de2348d..ff6891ff8d6 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -2330,10 +2330,8 @@ private: DB_KIND_BITS = EK_BITS, DB_DEFN_BIT = DB_KIND_BIT + DB_KIND_BITS, DB_IS_MEMBER_BIT, /* Is an out-of-class member. */ - DB_IS_INTERNAL_BIT, /* It is an (erroneous) - internal-linkage entity. */ - DB_REFS_INTERNAL_BIT, /* Refers to an internal-linkage - entity. */ + DB_TU_LOCAL_BIT, /* It is a TU-local entity. */ + DB_EXPOSURE_BIT, /* Exposes a TU-local entity. */ DB_IMPORTED_BIT, /* An imported entity. */ DB_UNREACHED_BIT, /* A yet-to-be reached entity. */ DB_HIDDEN_BIT, /* A hidden binding. */ @@ -2414,13 +2412,13 @@ public: return get_flag_bit (); } public: - bool is_internal () const + bool is_tu_local () const { - return get_flag_bit (); + return get_flag_bit (); } - bool refs_internal () const + bool is_exposure () const { - return get_flag_bit (); + return get_flag_bit (); } bool is_import () const { @@ -2580,6 +2578,11 @@ public: depset *add_dependency (tree decl, entity_kind); void add_namespace_context (depset *, tree ns); + private: + bool has_tu_local_tmpl_arg (tree decl, tree args, bool explain); + bool is_tu_local_entity (tree decl, bool explain = false); + bool is_tu_local_value (tree decl, tree expr, bool explain = false); + private: static bool add_binding_entity (tree, WMB_Flags, void *); @@ -9528,6 +9531,18 @@ trees_in::tree_node (bool is_use) /* NULL_TREE. */ break; + case tt_tu_local: + { + /* A translation-unit local entity. */ + res = make_node (TU_LOCAL_ENTITY); + int tag = insert (res); + + TU_LOCAL_ENTITY_NAME (res) = tree_node (); + TU_LOCAL_ENTITY_LOCATION (res) = state->read_location (*this); + dump (dumper::TREE) && dump ("Read TU-local entity:%d %N", tag, res); + } + break; + case tt_fixed: /* A fixed ref, find it in the fixed_ref array. */ { @@ -12890,6 +12905,243 @@ depset::hash::find_binding (tree ctx, tree name) return slot ? *slot : NULL; } +/* Returns true if DECL is a TU-local entity, as defined by [basic.link]. + If EXPLAIN is true, emit an informative note about why DECL is TU-local. */ + +bool +depset::hash::is_tu_local_entity (tree decl, bool explain/*=false*/) +{ + gcc_checking_assert (DECL_P (decl)); + + /* An explicit type alias is not an entity, and so is never TU-local. */ + if (TREE_CODE (decl) == TYPE_DECL + && !DECL_IMPLICIT_TYPEDEF_P (decl) + && !DECL_SELF_REFERENCE_P (decl)) + return false; + + location_t loc = DECL_SOURCE_LOCATION (decl); + tree type = TREE_TYPE (decl); + + /* Check specializations first for slightly better explanations. */ + int use_tpl = -1; + tree ti = node_template_info (decl, use_tpl); + if (use_tpl > 0 && TREE_CODE (TI_TEMPLATE (ti)) == TEMPLATE_DECL) + { + /* A specialization of a TU-local template. */ + tree tmpl = TI_TEMPLATE (ti); + if (is_tu_local_entity (tmpl)) + { + if (explain) + { + inform (loc, "%qD is a specialization of TU-local template %qD", + decl, tmpl); + is_tu_local_entity (tmpl, /*explain=*/true); + } + return true; + } + + /* A specialization of a template with any TU-local template argument. */ + if (has_tu_local_tmpl_arg (decl, TI_ARGS (ti), explain)) + return true; + + /* FIXME A specialization of a template whose (possibly instantiated) + declaration is an exposure. This should always be covered by the + above cases?? */ + } + + /* A type, function, variable, or template with internal linkage. */ + linkage_kind kind = decl_linkage (decl); + if (kind == lk_internal) + { + if (explain) + inform (loc, "%qD declared with internal linkage", decl); + return true; + } + + /* Does not have a name with linkage and is declared, or introduced by a + lambda-expression, within the definition of a TU-local entity. */ + if (kind == lk_none) + { + tree ctx = CP_DECL_CONTEXT (decl); + if (LAMBDA_TYPE_P (type)) + if (tree extra = LAMBDA_TYPE_EXTRA_SCOPE (type)) + ctx = extra; + + if (TREE_CODE (ctx) == NAMESPACE_DECL) + { + if (!TREE_PUBLIC (ctx)) + { + if (explain) + inform (loc, "%qD has no linkage and is declared in an " + "anonymous namespace", decl); + return true; + } + } + else if (TYPE_P (ctx)) + { + tree ctx_decl = TYPE_MAIN_DECL (ctx); + if (is_tu_local_entity (ctx_decl)) + { + if (explain) + { + inform (loc, "%qD has no linkage and is declared within " + "TU-local entity %qT", decl, ctx); + is_tu_local_entity (ctx_decl, /*explain=*/true); + } + return true; + } + } + else if (is_tu_local_entity (ctx)) + { + if (explain) + { + inform (loc, "%qD has no linkage and is declared within " + "TU-local entity %qD", decl, ctx); + is_tu_local_entity (ctx, /*explain=*/true); + } + return true; + } + } + + /* A type with no name that is defined outside a class-specifier, function + body, or initializer; or is introduced by a defining-type-specifier that + is used to declare only TU-local entities. + + We consider types with names for linkage purposes as having names, since + these aren't really TU-local, and also consider constraint-expressions + as initializers. */ + if (TREE_CODE (decl) == TYPE_DECL + && TYPE_ANON_P (type) + && !DECL_SELF_REFERENCE_P (decl) + /* An enum with an enumerator name for linkage. */ + && !(UNSCOPED_ENUM_P (type) && TYPE_VALUES (type))) + { + tree main_decl = TYPE_MAIN_DECL (type); + if (!TYPE_DEFINED_IN_INITIALIZER_P (type) + && !DECL_CLASS_SCOPE_P (main_decl) + && !decl_function_context (main_decl)) + { + if (explain) + inform (loc, "%qT has no name and is not defined within a class, " + "function, or initializer", type); + return true; + } + + // FIXME introduced by a defining-type-specifier only declaring TU-local + // entities; does this refer to e.g. 'static struct {} a;"? I can't + // think of any cases where this isn't covered by earlier cases. */ + } + + return false; +} + +/* Helper for is_tu_local_entity. Returns true if one of the ARGS of + DECL is TU-local. Emits an explanation if EXPLAIN is true. */ + +bool +depset::hash::has_tu_local_tmpl_arg (tree decl, tree args, bool explain) +{ + if (!args || TREE_CODE (args) != TREE_VEC) + return false; + + for (tree a : tree_vec_range (args)) + { + if (TREE_CODE (a) == TREE_VEC) + { + if (has_tu_local_tmpl_arg (decl, a, explain)) + return true; + } + else if (!WILDCARD_TYPE_P (a)) + { + if (DECL_P (a) && is_tu_local_entity (a)) + { + if (explain) + { + inform (DECL_SOURCE_LOCATION (decl), + "%qD has TU-local template argument %qD", + decl, a); + is_tu_local_entity (a, /*explain=*/true); + } + return true; + } + + if (TYPE_P (a) && TYPE_NAME (a) && is_tu_local_entity (TYPE_NAME (a))) + { + if (explain) + { + inform (DECL_SOURCE_LOCATION (decl), + "%qD has TU-local template argument %qT", + decl, a); + is_tu_local_entity (TYPE_NAME (a), /*explain=*/true); + } + return true; + } + + if (EXPR_P (a) && is_tu_local_value (decl, a, explain)) + return true; + } + } + + return false; +} + +/* Returns true if EXPR (part of the initializer for DECL) is a TU-local value + or object. Emits an explanation if EXPLAIN is true. */ + +bool +depset::hash::is_tu_local_value (tree decl, tree expr, bool explain) +{ + if (!expr) + return false; + + tree e = expr; + STRIP_ANY_LOCATION_WRAPPER (e); + STRIP_NOPS (e); + if (TREE_CODE (e) == TARGET_EXPR) + e = TARGET_EXPR_INITIAL (e); + if (!e) + return false; + + /* It is, or is a pointer to, a TU-local function or the object associated + with a TU-local variable. */ + tree object = NULL_TREE; + if (TREE_CODE (e) == ADDR_EXPR) + object = TREE_OPERAND (e, 0); + else if (TREE_CODE (e) == PTRMEM_CST) + object = PTRMEM_CST_MEMBER (e); + else if (VAR_OR_FUNCTION_DECL_P (e)) + object = e; + + if (object + && VAR_OR_FUNCTION_DECL_P (object) + && is_tu_local_entity (object)) + { + if (explain) + { + /* We've lost a lot of location information by the time we get here, + so let's just do our best effort. */ + auto loc = cp_expr_loc_or_loc (expr, DECL_SOURCE_LOCATION (decl)); + if (VAR_P (object)) + inform (loc, "%qD refers to TU-local object %qD", decl, object); + else + inform (loc, "%qD refers to TU-local function %qD", decl, object); + is_tu_local_entity (object, true); + } + return true; + } + + /* It is an object of class or array type and any of its subobjects or + any of the objects or functions to which its non-static data members + of reference type refer is TU-local and is usable in constant + expressions. */ + if (TREE_CODE (e) == CONSTRUCTOR && AGGREGATE_TYPE_P (TREE_TYPE (e))) + for (auto& f : CONSTRUCTOR_ELTS (e)) + if (is_tu_local_value (decl, f.value, explain)) + return true; + + return false; +} + /* DECL is a newly discovered dependency. Create the depset, if it doesn't already exist. Add it to the worklist if so. @@ -13014,26 +13266,30 @@ depset::hash::make_dependency (tree decl, entity_kind ek) } } - if (ek == EK_DECL + if (!header_module_p () && !dep->is_import () - && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL - && !(TREE_CODE (decl) == TEMPLATE_DECL - && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))) - { - tree ctx = CP_DECL_CONTEXT (decl); + && is_tu_local_entity (decl)) + /* An internal decl. This is OK in a header unit. */ + dep->set_flag_bit (); - if (!TREE_PUBLIC (ctx)) - /* Member of internal namespace. */ - dep->set_flag_bit (); - else if (VAR_OR_FUNCTION_DECL_P (not_tmpl) - && DECL_THIS_STATIC (not_tmpl)) - { - /* An internal decl. This is ok in a GM entity. */ - if (!(header_module_p () - || !DECL_LANG_SPECIFIC (not_tmpl) - || !DECL_MODULE_PURVIEW_P (not_tmpl))) - dep->set_flag_bit (); - } + if (!header_module_p () + && !dep->is_import () + && VAR_P (decl) + && (TREE_CONSTANT (decl) + || (TYPE_REF_P (TREE_TYPE (decl)) + && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))) + && is_tu_local_value (decl, DECL_INITIAL (decl))) + { + /* A potentially-constant variable initialized to a TU-local + value is not usable in constant expressions within other + translation units. We can achieve this by simply not + streaming the definition in such cases. */ + dep->clear_flag_bit (); + + if (DECL_DECLARED_CONSTEXPR_P (decl)) + /* Also, a constexpr variable initialized to a TU-local + value is an exposure. This is OK in a header unit. */ + dep->set_flag_bit (); } } @@ -13059,8 +13315,8 @@ depset::hash::add_dependency (depset *dep) gcc_checking_assert (current && !is_key_order ()); current->deps.safe_push (dep); - if (dep->is_internal () && !current->is_internal ()) - current->set_flag_bit (); + if (dep->is_tu_local ()) + current->set_flag_bit (); if (current->get_entity_kind () == EK_USING && DECL_IMPLICIT_TYPEDEF_P (dep->get_entity ()) @@ -13168,13 +13424,9 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_) /* Ignore entities not within the module purview. */ return false; - if (VAR_OR_FUNCTION_DECL_P (inner) - && DECL_THIS_STATIC (inner)) - { - if (!header_module_p ()) - /* Ignore internal-linkage entitites. */ - return false; - } + if (!header_module_p () && data->hash->is_tu_local_entity (decl)) + /* Ignore TU-local entitites. */ + return false; if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL) @@ -13873,10 +14125,8 @@ bool depset::hash::finalize_dependencies () { bool ok = true; - depset::hash::iterator end (this->end ()); - for (depset::hash::iterator iter (begin ()); iter != end; ++iter) + for (depset *dep : *this) { - depset *dep = *iter; if (dep->is_binding ()) { /* Keep the containing namespace dep first. */ @@ -13889,23 +14139,41 @@ depset::hash::finalize_dependencies () gcc_qsort (&dep->deps[1], dep->deps.length () - 1, sizeof (dep->deps[1]), binding_cmp); } - else if (dep->refs_internal ()) + else if (dep->is_exposure () && !dep->is_tu_local ()) { - for (unsigned ix = dep->deps.length (); ix--;) + ok = false; + bool explained = false; + tree decl = dep->get_entity (); + + for (depset *rdep : dep->deps) + if (!rdep->is_binding () && rdep->is_tu_local ()) + { + // FIXME:QOI Better location information? We're + // losing, so it doesn't matter about efficiency + tree exposed = rdep->get_entity (); + auto_diagnostic_group d; + error_at (DECL_SOURCE_LOCATION (decl), + "%qD exposes TU-local entity %qD", decl, exposed); + bool informed = is_tu_local_entity (exposed, /*explain=*/true); + gcc_checking_assert (informed); + explained = true; + break; + } + + if (!explained && VAR_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl)) { - depset *rdep = dep->deps[ix]; - if (rdep->is_internal ()) - { - // FIXME:QOI Better location information? We're - // losing, so it doesn't matter about efficiency - tree decl = dep->get_entity (); - error_at (DECL_SOURCE_LOCATION (decl), - "%q#D references internal linkage entity %q#D", - decl, rdep->get_entity ()); - break; - } + auto_diagnostic_group d; + error_at (DECL_SOURCE_LOCATION (decl), + "%qD is declared % and is initialized to " + "a TU-local value", decl); + bool informed = is_tu_local_value (decl, DECL_INITIAL (decl), + /*explain=*/true); + gcc_checking_assert (informed); + explained = true; } - ok = false; + + /* We should have emitted an error above. */ + gcc_checking_assert (explained); } } @@ -13929,7 +14197,9 @@ void depset::tarjan::connect (depset *v) { gcc_checking_assert (v->is_binding () - || !(v->is_unreached () || v->is_import ())); + || !(v->is_tu_local () + || v->is_unreached () + || v->is_import ())); v->cluster = v->section = ++index; stack.safe_push (v); @@ -13939,7 +14209,8 @@ depset::tarjan::connect (depset *v) { depset *dep = v->deps[ix]; - if (dep->is_binding () || !dep->is_import ()) + if (dep->is_binding () + || !(dep->is_import () || dep->is_tu_local ())) { unsigned lwm = dep->cluster; @@ -14142,14 +14413,12 @@ depset::hash::connect () tarjan connector (size ()); vec deps; deps.create (size ()); - iterator end (this->end ()); - for (iterator iter (begin ()); iter != end; ++iter) + for (depset *item : *this) { - depset *item = *iter; - entity_kind kind = item->get_entity_kind (); if (kind == EK_BINDING || !(kind == EK_REDIRECT + || item->is_tu_local () || item->is_unreached () || item->is_import ())) deps.quick_push (item); @@ -18411,7 +18680,8 @@ module_state::write_begin (elf_out *to, cpp_reader *reader, note_defs = note_defs_table_t::create_ggc (1000); #endif - /* Determine Strongy Connected Components. */ + /* Determine Strongy Connected Components. This will also strip any + unnecessary dependencies on imported or TU-local entities. */ vec sccs = table.connect (); vec_alloc (ool, modules->length ()); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 4dd9474cf60..f75d3f53343 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -564,6 +564,8 @@ cp_debug_parser (FILE *file, cp_parser *parser) parser->in_unbraced_export_declaration_p); cp_debug_print_flag (file, "Parsing a declarator", parser->in_declarator_p); + cp_debug_print_flag (file, "Parsing an initializer", + parser->in_initializer_p); cp_debug_print_flag (file, "In template argument list", parser->in_template_argument_list_p); cp_debug_print_flag (file, "Parsing an iteration statement", @@ -4455,6 +4457,9 @@ cp_parser_new (cp_lexer *lexer) /* We are not processing a declarator. */ parser->in_declarator_p = false; + /* We are not processing an initializer. */ + parser->in_initializer_p = false; + /* We are not processing a template-argument-list. */ parser->in_template_argument_list_p = false; @@ -11426,6 +11431,7 @@ cp_parser_lambda_expression (cp_parser* parser) record_lambda_scope (lambda_expr); record_lambda_scope_discriminator (lambda_expr); + TYPE_DEFINED_IN_INITIALIZER_P (type) = parser->in_initializer_p; /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ determine_visibility (TYPE_NAME (type)); @@ -26331,6 +26337,9 @@ cp_parser_initializer (cp_parser *parser, bool *is_direct_init /*=nullptr*/, if (non_constant_p) *non_constant_p = false; + bool saved_in_initializer_p = parser->in_initializer_p; + parser->in_initializer_p = true; + if (token->type == CPP_EQ) { /* Consume the `='. */ @@ -26367,6 +26376,8 @@ cp_parser_initializer (cp_parser *parser, bool *is_direct_init /*=nullptr*/, if (!subexpression_p && check_for_bare_parameter_packs (init)) init = error_mark_node; + parser->in_initializer_p = saved_in_initializer_p; + return init; } @@ -27937,6 +27948,8 @@ cp_parser_class_head (cp_parser* parser, } else if (type == error_mark_node) type = NULL_TREE; + else + TYPE_DEFINED_IN_INITIALIZER_P (type) = parser->in_initializer_p; if (type) { @@ -31367,6 +31380,8 @@ cp_parser_concept_definition (cp_parser *parser) } processing_constraint_expression_sentinel parsing_constraint; + parser->in_initializer_p = true; + tree init = cp_parser_constraint_expression (parser); if (init == error_mark_node) cp_parser_skip_to_end_of_statement (parser); @@ -31375,6 +31390,7 @@ cp_parser_concept_definition (cp_parser *parser) but continue as if it were. */ cp_parser_consume_semicolon_at_end_of_statement (parser); + parser->in_initializer_p = false; return finish_concept_definition (id, init, attrs); } diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 09b356e5e73..ee8c4f9001e 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -323,6 +323,9 @@ struct GTY(()) cp_parser { direct-declarator. */ bool in_declarator_p; + /* TRUE if we are parsing an initializer. */ + bool in_initializer_p; + /* TRUE if we are presently parsing a template-argument-list. */ bool in_template_argument_list_p; diff --git a/gcc/testsuite/g++.dg/modules/block-decl-2.C b/gcc/testsuite/g++.dg/modules/block-decl-2.C index d491a18dfb1..104a98ab052 100644 --- a/gcc/testsuite/g++.dg/modules/block-decl-2.C +++ b/gcc/testsuite/g++.dg/modules/block-decl-2.C @@ -11,7 +11,7 @@ export extern "C++" auto foo() { struct X { // `foo` is not attached to a named module, and as such // `X::f` should be implicitly `inline` here - void f() { // { dg-error "references internal linkage entity" } + void f() { // { dg-error "exposes TU-local entity" } internal(); } }; diff --git a/gcc/testsuite/g++.dg/modules/internal-1.C b/gcc/testsuite/g++.dg/modules/internal-1.C index 9f7299a5fc7..3ed74c9cc42 100644 --- a/gcc/testsuite/g++.dg/modules/internal-1.C +++ b/gcc/testsuite/g++.dg/modules/internal-1.C @@ -3,13 +3,10 @@ export module frob; // { dg-module-cmi !frob } -namespace { -// We shouldn't be complaining about members of internal linkage -// entities -class X // { dg-bogus "internal linkage" "" { xfail *-*-* } } -{ // { dg-bogus "internal linkage" "" { xfail *-*-* } } -}; - +namespace +{ + // We shouldn't be complaining about members of internal linkage entities + class X {}; } static int frob () @@ -17,5 +14,5 @@ static int frob () return 1; } -export int f (int = frob ()); // { dg-error "references internal linkage" } -int goof (X &); // { dg-error "references internal linkage" } +export int f (int = frob ()); // { dg-error "exposes TU-local entity" } +int goof (X &); // { dg-error "exposes TU-local entity" } diff --git a/gcc/testsuite/g++.dg/modules/internal-3.C b/gcc/testsuite/g++.dg/modules/internal-3.C new file mode 100644 index 00000000000..91aae32783f --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-3.C @@ -0,0 +1,18 @@ +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi !M } +// TU-local entities in the GMF can be exposed. + +module; + +static inline void foo() {} + +export module M; + +inline void bar() { // { dg-error "exposes TU-local entity" } + foo(); +} + +// OK +void qux() { + foo(); +} diff --git a/gcc/testsuite/g++.dg/modules/internal-4.C b/gcc/testsuite/g++.dg/modules/internal-4.C new file mode 100644 index 00000000000..0c9a790d379 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-4.C @@ -0,0 +1,112 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi !bad } +// Test for determining various kinds of entities being marked TU-local + +export module bad; + + +// A type, function variable, or template with internal linkage +namespace { + struct internal_t { int m; }; + enum internal_e {}; + void internal_f() {} + int internal_v; + template void internal_x() {} +} + +inline void expose_type() { // { dg-error "exposes TU-local entity" } + internal_t x; +} +inline void expose_func() { // { dg-error "exposes TU-local entity" } + internal_f(); +} +inline void expose_var() { // { dg-error "exposes TU-local entity" } + int* p = &internal_v; +} +inline void expose_tmpl() { // { dg-error "exposes TU-local entity" } + internal_x(); +} + + +// Does not have a name with linkage and is declared, or introduced by +// a lambda-expression, within the definition of a TU-local entity +static auto get_local_ok() { + return 0; +} +static auto get_local_type() { + struct no_linkage {}; + return no_linkage(); +} +static auto get_local_lambda() { + return []{}; +} +using T = decltype(get_local_ok()); // OK +using U = decltype(get_local_type()); // { dg-error "exposes TU-local entity" } +using V = decltype(get_local_lambda()); // { dg-error "exposes TU-local entity" } + +static auto internal_lambda = []{ internal_f(); }; // OK +auto expose_lambda = internal_lambda; // { dg-error "exposes TU-local entity" } + +int not_in_tu_local + = ([]{ internal_f(); }(), // { dg-error "exposes TU-local entity" } + 0); + + +// A type with no name that is defined outside a class-specifier, function +// body, or initializer + +struct {} no_name; // { dg-error "exposes TU-local entity" } +enum {} e; // { dg-error "exposes TU-local entity" } +using not_an_initializer = class {}; // { dg-error "exposes TU-local entity" } + +class in_class_specifier { struct {} x; }; // OK +void in_function_body() { struct {} x; } // OK +auto in_initializer = []{}; // OK + +#if __cplusplus >= 202002L +decltype([]{}) d_lambda; // { dg-error "exposes TU-local entity" "" { target c++20 } } + +template +concept in_constraint_expression = requires { + // Strictly by the standard this is currently ill-formed + // (this is a constraint-expression not an initializer) + // but I don't think that is intended. + []{}; // OK? +}; +#endif + +// (But consider unnamed types with names for linkage purposes as having names) +typedef struct {} no_name_typedef_t; +no_name_typedef_t linkage_name_struct; // OK + +enum { enum_name } linkage_name_enum; // OK + + +// Specialisation of a TU-local template +template static void f(T) {} +template <> void f(int) {} // OK +inline void f_use(int x) { // { dg-error "exposes TU-local entity" } + f(x); +} + + +// Specialisation of a template with any TU-local argument +template void g(T) {} +template <> void g(internal_t) { internal_f(); } // OK +template <> void g(internal_e) { internal_f(); } // OK +template <> void g(decltype(no_name)) { internal_f(); } // OK +template <> void g(decltype(get_local_lambda())) { internal_f(); } // OK + +template struct h {}; +template struct h<&internal_v>; +template <> struct h<&internal_f> { internal_t x; }; // OK +template <> struct h<&internal_t::m> { void foo() { internal_f(); } }; // OK + + +// TODO: I can't come up with testcases for these that aren't already covered +// by one of the above cases: +// +// - A type with no name introduced by a defining-type-specifier that is +// used to declare only TU-local entities +// - A specialisation of a template whose (possibly instantiated) declaration +// is an exposure diff --git a/gcc/testsuite/g++.dg/modules/linkage-2.C b/gcc/testsuite/g++.dg/modules/linkage-2.C index 4b20411572c..97421bfad8e 100644 --- a/gcc/testsuite/g++.dg/modules/linkage-2.C +++ b/gcc/testsuite/g++.dg/modules/linkage-2.C @@ -25,6 +25,5 @@ export void use() { // Additionally, unnamed types have no linkage but are also TU-local, and thus // cannot be exposed in a module interface unit. The non-TU-local entity 's' -// here is an exposure of this type, so this should be an error; we don't yet -// implement this checking however. -struct {} s; // { dg-error "TU-local" "" { xfail *-*-* } } +// here is an exposure of this type. +struct {} s; // { dg-error "exposes TU-local entity" } From patchwork Mon Sep 23 23:46:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988726 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=khVapm03; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKQd3LZQz1xsM for ; Tue, 24 Sep 2024 09:46:49 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4E76E385DC3C for ; Mon, 23 Sep 2024 23:46:47 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by sourceware.org (Postfix) with ESMTPS id 54279385C6C1 for ; Mon, 23 Sep 2024 23:46:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 54279385C6C1 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 54279385C6C1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1029 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135176; cv=none; b=gqnwOJlhAwzC/TyV+A3r8yNCor500JcrX/McsedhsPoTDsS5UtBJRBYtvyl0DE7JEhoELjt99BjvNdKML7JPbrtkEhWNRL65bnkUcuas3SsN0g1knVGdFd7SDakB+d1zo1GTi/p6r4KLLAk6MElGTBZLXVxPHskm5Wf95Fm2pA0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135176; c=relaxed/simple; bh=31Rag8g/GPkKhcjo6A0XE8wVV3O2NIa05Nxpqur5nuE=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=vRjD/B506biQCEDk4d1Pu/pjz3fGIZkHY4yn+UFCWg3D0lrDzPeamdCYEeOsezQNu6GBOARIu4LwhUhAyPKrkQTmys5XwLhFGGZjepXDJ8ddTZgK9Z2RC/2lUb00Uq6qzhC4LmTEWRcPnOzDZV46HUtnMTlIAUaromL9zgV9qgI= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x1029.google.com with SMTP id 98e67ed59e1d1-2d88a8c66b7so624279a91.1 for ; Mon, 23 Sep 2024 16:46:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135169; x=1727739969; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=sJtX3BX5xm2E8GenGzw3dF5eJDxZ3ZdMg7A2lQkTZ9g=; b=khVapm03sN0GfpkhX7Wx8NesWksioXfXvxlxxlEYwv0B4+hA/BAvpD+ksKMyCeQMZq MGD5BJR4SVVkQvDRabIvCtrWbhJKWsMF9ms4YCVMi47UFzy7jm6+Sln4uiuEykp4/B78 90eUIYHUa4Gu7aonYfU+A0fDTFh9IhwV3H3rWVN1qgveG/MD6taGbeSb/XeXjz4P3cUK mwYWwhzVabsIuaEAhJ8oH+n+vkfTUfSkCvKohxXXV/XZT5z7FGtzO/ri+Qxb567sonMU YWwoF1HZmvU2sdSH8oTFAUJaqCvytLbgY+1DZ5XJCq/TRIFhpiha76nX99J7CajEZ8zO lEEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135169; x=1727739969; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=sJtX3BX5xm2E8GenGzw3dF5eJDxZ3ZdMg7A2lQkTZ9g=; b=avbsekyw9YrPgUVJ6pGA5p5Rd9Ewm3VHjOSbPzenjcjnpo8Cm67sbRZ5EtJ1zV3Og7 9WNzPxKcr5FGreDeY+UOYWCGbGM0ptpz++UsXTKZizv0AHfVDaEI14Q9W0tPwbBOcvEo MvjuMh/+TS0xgMsL1MwuLFQ4ocXwK4LBrCxNn+4aM25XB7dYjThbxbtA8gQJEsAqH6aY +iEbVBqxnRS87wVItnuY5dRMPIzMdQ6suI5ydOK/yzO/MSS/j3esDrwNK6A95xNKlfzJ hTUeWzaVoQi3CgOg5uO5CPArtcZHh/x7smN8Tcllwb2KMC7s9BYXVvf0KcVlXg64neRd d58A== X-Gm-Message-State: AOJu0YwWvY5+tc0TlV6OC2Fyv14QpD6hUQrZE1lGjlMufEcEJdLl06dL t+HiQ800VErUfjPw8DOdsOboo+BJ0uRdOrFYt54X3iOXA6JLZlKQePBaUw== X-Google-Smtp-Source: AGHT+IFFvKB22SkgsemqD2C3PTnRSX0R9ZkP+UZVJyQmAX/NtiKC/+pVg4xBKEi7LqvzQBuDPl0KOw== X-Received: by 2002:a17:90b:3444:b0:2d8:8e8a:2b0c with SMTP id 98e67ed59e1d1-2dd7f3e3241mr6417055a91.3.1727135168429; Mon, 23 Sep 2024 16:46:08 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2dd6eec8914sm10021433a91.31.2024.09.23.16.46.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:46:07 -0700 (PDT) Message-ID: <66f1fdbf.170a0220.11f512.6709@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:46:04 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 07/10] c++/modules: Implement ignored TU-local exposures References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_FILL_THIS_FORM_SHORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Currently I just stream DECL_NAME in TU_LOCAL_ENTITYs for use in diagnostics, but this feels perhaps insufficient. Are there any better approached here? Otherwise I don't think it matters too much, as which entity it is will also be hopefully clear from the 'declared here' notes. I've put the new warning in Wextra, but maybe it would be better to just leave it out of any of the normal warning groups since there's currently no good way to work around the warnings it produces? Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- [basic.link] p14 lists a number of circumstances where a declaration naming a TU-local entity is not an exposure, notably the bodies of non-inline templates and friend declarations in classes. This patch ensures that these references do not error when exporting the module. We do need to still error on instantiation from a different module, however, in case this refers to a TU-local entity. As such this patch adds a new tree TU_LOCAL_ENTITY which is used purely as a placeholder to poison any attempted template instantiations that refer to it. This is also streamed for friend decls so that merging (based on the index of an entity into the friend decl list) doesn't break and to prevent complicating the logic; I imagine this shouldn't ever come up though. We also add a new warning, '-Wignored-exposures', to handle the case where someone accidentally refers to a TU-local value from within a non-inline function template. This will compile without errors as-is, but any attempt to instantiate the decl will fail; this warning can be used to ensure that this doesn't happen. Unfortunately the warning has quite some false positives; for instance, a user could deliberately only call explicit instantiations of the decl, or use 'if constexpr' to avoid instantiating the TU-local entity from other TUs, neither of which are currently detected. The main piece that this patch doesn't yet attempt to solve is ADL: as specified, if ADL adds an overload set that includes a translation-unit local entity when instantiating a template, that overload set is now poisoned and counts as an exposure. Unfortunately, we don't currently differentiate between decls that are hidden due to not being exported, or decls that are hidden due to being hidden friends, so this patch instead just keeps the current (wrong) behaviour of non-exported entities not being visible to ADL at all. gcc/c-family/ChangeLog: * c.opt: New warning '-Wignored-exposures'. gcc/cp/ChangeLog: * cp-objcp-common.cc (cp_tree_size): Add TU_LOCAL_ENTITY. * cp-tree.def (TU_LOCAL_ENTITY): New tree code. * cp-tree.h (struct tree_tu_local_entity): New type. (TU_LOCAL_ENTITY_NAME): New accessor. (TU_LOCAL_ENTITY_LOCATION): New accessor. (enum cp_tree_node_structure_enum): Add TS_CP_TU_LOCAL_ENTITY. (union GTY): Add tu_local_entity field. * module.cc (enum tree_tag): New flag DB_IGNORED_EXPOSURE_BIT. (depset::is_ignored_exposure): New accessor. (depset::has_defn): Override for TU-local entities. (depset::hash::ignore_exposure): New field. (depset::hash::hash): Initialize it. (trees_out::tree_tag::tt_tu_local): New flag. (trees_out::writing_local_entities): New field. (trees_out::is_initial_scan): New function. (trees_out::tu_local_count): New counter. (trees_out::trees_out): Initialize writing_local_entities. (dumper::impl::nested_name): Handle TU_LOCAL_ENTITY. (trees_out::instrument): Report TU-local entity counts. (trees_out::decl_value): Early exit for TU-local entities. (trees_in::decl_value): Handle typedefs of TU-local entities. (trees_out::decl_node): Adjust assertion to cope with early exit of TU-local deps. Always write TU-local entities by value. (trees_out::type_node): Handle TU-local types. (trees_out::has_tu_local_dep): New function. (trees_out::find_tu_local_decl): New function. (trees_out::tree_node): Intercept TU-local entities and write placeholder values for them instead of normal streaming. (trees_in::tree_node): Handle TU-local template results. (trees_out::write_function_def): Ignore exposures in non-inline function bodies. (trees_out::write_var_def): Ignore exposures in initializers. (trees_out::write_class_def): Ignore exposures in friend decls. (trees_in::read_class_def): Skip TU-local friends. (trees_out::write_definition): Record whether we're writing a decl which refers to TU-local entities. (depset::hash::add_dependency): Handle ignored exposures. (depset::hash::find_dependencies): Use depset's own is_key_order function rather than delegating via walker. Pass whether the decl has ignored TU-local entities in its definition. (depset::hash::finalize_dependencies): Implement new warning Wignored-exposures. (module_state::intercluster_seed): Don't seed TU-local deps. (module_state::write_cluster): Pass whether the decl has ignored TU-local entities in its definition. * pt.cc (complain_about_tu_local_entity): New function. (expr_contains_tu_local_entity): New function. (function_contains_tu_local_entity): New function. (instantiate_class_template): Skip TU-local friends. (tsubst_decl): Handle typedefs of TU-local entities. (tsubst): Complain about TU-local entities. (dependent_operand_p): Early exit for TU-local entities so we don't attempt to constant-evaluate them. (tsubst_expr): Detect and complain about TU-local entities. gcc/ChangeLog: * doc/invoke.texi: Document -Wignored-exposures. gcc/testsuite/ChangeLog: * g++.dg/modules/internal-5_a.C: New test. * g++.dg/modules/internal-5_b.C: New test. * g++.dg/modules/internal-6.C: New test. * g++.dg/modules/internal-7_a.C: New test. * g++.dg/modules/internal-7_b.C: New test. Signed-off-by: Nathaniel Shead --- gcc/c-family/c.opt | 4 + gcc/cp/cp-objcp-common.cc | 1 + gcc/cp/cp-tree.def | 6 + gcc/cp/cp-tree.h | 21 +- gcc/cp/module.cc | 303 +++++++++++++++++--- gcc/cp/pt.cc | 98 ++++++- gcc/doc/invoke.texi | 19 +- gcc/testsuite/g++.dg/modules/internal-5_a.C | 104 +++++++ gcc/testsuite/g++.dg/modules/internal-5_b.C | 29 ++ gcc/testsuite/g++.dg/modules/internal-6.C | 24 ++ gcc/testsuite/g++.dg/modules/internal-7_a.C | 75 +++++ gcc/testsuite/g++.dg/modules/internal-7_b.C | 21 ++ 12 files changed, 657 insertions(+), 48 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/internal-5_a.C create mode 100644 gcc/testsuite/g++.dg/modules/internal-5_b.C create mode 100644 gcc/testsuite/g++.dg/modules/internal-6.C create mode 100644 gcc/testsuite/g++.dg/modules/internal-7_a.C create mode 100644 gcc/testsuite/g++.dg/modules/internal-7_b.C diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index ec23249c959..8383210503d 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -828,6 +828,10 @@ Wif-not-aligned C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning Warn when the field in a struct is not aligned. +Wignored-exposures +C++ ObjC++ Var(warn_ignored_exposures) Warning EnabledBy(Wextra) +Warn about ignored exposures of TU-local entities in a module. + Wignored-qualifiers C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra) Warn whenever type qualifiers are ignored. diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc index cd379514991..b959533bcb1 100644 --- a/gcc/cp/cp-objcp-common.cc +++ b/gcc/cp/cp-objcp-common.cc @@ -233,6 +233,7 @@ cp_tree_size (enum tree_code code) case ASSERTION_STMT: return sizeof (tree_exp); case PRECONDITION_STMT: return sizeof (tree_exp); case POSTCONDITION_STMT: return sizeof (tree_exp); + case TU_LOCAL_ENTITY: return sizeof (tree_tu_local_entity); default: switch (TREE_CODE_CLASS (code)) { diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 18f75108c7b..7580dc3667d 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -573,6 +573,12 @@ DEFTREECODE (ASSERTION_STMT, "assertion_stmt", tcc_statement, 3) DEFTREECODE (PRECONDITION_STMT, "precondition_stmt", tcc_statement, 3) DEFTREECODE (POSTCONDITION_STMT, "postcondition_stmt", tcc_statement, 4) +/* A reference to a translation-unit local entity. + + This is emitted by modules streaming when writing a TU-local entity that + wasn't an exposure (e.g. in a non-inline function template). */ +DEFTREECODE (TU_LOCAL_ENTITY, "tu_local_entity", tcc_exceptional, 0) + /* Local variables: mode:c diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 99fbd905896..85c1d23c240 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1779,6 +1779,22 @@ check_constraint_info (tree t) it for unscoped enums. */ #define DECL_MODULE_EXPORT_P(NODE) TREE_LANG_FLAG_3 (NODE) +/* Represents a streamed-in translation-unit-local entity. Any use of this + should emit an error. */ +struct GTY(()) tree_tu_local_entity { + struct tree_base base; + tree name; + location_t loc; +}; + +/* The name of a translation-unit local-entity. */ +#define TU_LOCAL_ENTITY_NAME(NODE) \ + (((struct tree_tu_local_entity *)TU_LOCAL_ENTITY_CHECK (NODE))->name) + +/* The source location of the translation-unit-local entity. */ +#define TU_LOCAL_ENTITY_LOCATION(NODE) \ + (((struct tree_tu_local_entity *)TU_LOCAL_ENTITY_CHECK (NODE))->loc) + /* The list of local parameters introduced by this requires-expression, in the form of a chain of PARM_DECLs. */ @@ -1812,7 +1828,8 @@ enum cp_tree_node_structure_enum { TS_CP_LAMBDA_EXPR, TS_CP_TEMPLATE_INFO, TS_CP_CONSTRAINT_INFO, - TS_CP_USERDEF_LITERAL + TS_CP_USERDEF_LITERAL, + TS_CP_TU_LOCAL_ENTITY }; /* The resulting tree type. */ @@ -1843,6 +1860,8 @@ union GTY((desc ("cp_tree_node_structure (&%h)"), constraint_info; struct tree_userdef_literal GTY ((tag ("TS_CP_USERDEF_LITERAL"))) userdef_literal; + struct tree_tu_local_entity GTY ((tag ("TS_CP_TU_LOCAL_ENTITY"))) + tu_local_entity; }; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index ff6891ff8d6..7b1e69cb4c0 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -2332,6 +2332,7 @@ private: DB_IS_MEMBER_BIT, /* Is an out-of-class member. */ DB_TU_LOCAL_BIT, /* It is a TU-local entity. */ DB_EXPOSURE_BIT, /* Exposes a TU-local entity. */ + DB_IGNORED_EXPOSURE_BIT, /* Will stream a TU-local entity. */ DB_IMPORTED_BIT, /* An imported entity. */ DB_UNREACHED_BIT, /* A yet-to-be reached entity. */ DB_HIDDEN_BIT, /* A hidden binding. */ @@ -2401,7 +2402,9 @@ public: public: bool has_defn () const { - return get_flag_bit (); + /* Never consider TU-local entities as having definitions, since + we will never be accessing them from importers anyway. */ + return get_flag_bit () && !is_tu_local (); } public: @@ -2420,6 +2423,10 @@ public: { return get_flag_bit (); } + bool is_ignored_exposure () const + { + return get_flag_bit (); + } bool is_import () const { return get_flag_bit (); @@ -2543,11 +2550,12 @@ public: depset *current; /* Current depset being depended. */ unsigned section; /* When writing out, the section. */ bool reached_unreached; /* We reached an unreached entity. */ + bool ignore_exposure; /* In a context where exposures are ignored. */ public: hash (size_t size, hash *c = NULL) : parent (size), chain (c), current (NULL), section (0), - reached_unreached (false) + reached_unreached (false), ignore_exposure (false) { worklist.create (size); } @@ -2748,6 +2756,7 @@ static GTY((cache)) decl_tree_cache_map *imported_temploid_friends; /* Tree tags. */ enum tree_tag { tt_null, /* NULL_TREE. */ + tt_tu_local, /* A TU-local entity. */ tt_fixed, /* Fixed vector index. */ tt_node, /* By-value node. */ @@ -3032,6 +3041,8 @@ private: depset::hash *dep_hash; /* Dependency table. */ int ref_num; /* Back reference number. */ unsigned section; + bool writing_local_entities; /* Whether we might walk into a TU-local + entity we need to emit placeholders for. */ #if CHECKING_P int importedness; /* Checker that imports not occurring inappropriately. +ve imports ok, @@ -3061,6 +3072,18 @@ public: }; public: + /* The walk is used for three similar purposes: + + 1. The initial scan for dependencies. + 2. Once dependencies have been found, ordering them. + 3. Writing dependencies to file (streaming_p). + + For cases where it matters, these accessers can be used to determine + which state we're in. */ + bool is_initial_scan () const + { + return !streaming_p () && !is_key_order (); + } bool is_key_order () const { return dep_hash->is_key_order (); @@ -3101,6 +3124,10 @@ private: void tree_pair_vec (vec *); void tree_list (tree, bool has_purpose); +private: + bool has_tu_local_dep (tree) const; + tree find_tu_local_decl (tree); + public: /* Mark a node for by-value walking. */ void mark_by_value (tree); @@ -3138,7 +3165,7 @@ public: public: /* Serialize various definitions. */ - void write_definition (tree decl); + void write_definition (tree decl, bool has_tu_local = false); void mark_declaration (tree decl, bool do_defn); private: @@ -3166,6 +3193,7 @@ private: static unsigned tree_val_count; static unsigned decl_val_count; static unsigned back_ref_count; + static unsigned tu_local_count; static unsigned null_count; }; } // anon namespace @@ -3174,12 +3202,14 @@ private: unsigned trees_out::tree_val_count; unsigned trees_out::decl_val_count; unsigned trees_out::back_ref_count; +unsigned trees_out::tu_local_count; unsigned trees_out::null_count; trees_out::trees_out (allocator *mem, module_state *state, depset::hash &deps, unsigned section) :parent (mem), state (state), tree_map (500), - dep_hash (&deps), ref_num (0), section (section) + dep_hash (&deps), ref_num (0), section (section), + writing_local_entities (false) { #if CHECKING_P importedness = 0; @@ -4301,6 +4331,9 @@ dumper::impl::nested_name (tree t) int origin = -1; tree name = NULL_TREE; + if (t && TREE_CODE (t) == TU_LOCAL_ENTITY) + t = TU_LOCAL_ENTITY_NAME (t); + if (t && TREE_CODE (t) == TREE_BINFO) t = BINFO_TYPE (t); @@ -4853,6 +4886,7 @@ trees_out::instrument () dump (" %u decl trees", decl_val_count); dump (" %u other trees", tree_val_count); dump (" %u back references", back_ref_count); + dump (" %u TU-local entities", tu_local_count); dump (" %u null trees", null_count); } } @@ -7809,6 +7843,17 @@ trees_out::decl_value (tree decl, depset *dep) || DECL_ORIGINAL_TYPE (decl) || !TYPE_PTRMEMFUNC_P (TREE_TYPE (decl))); + /* There's no need to walk any of the contents of a known TU-local entity, + since importers should never see any of it regardless. But make sure we + at least note its location so importers can use it for diagnostics. */ + if (dep && dep->is_tu_local ()) + { + gcc_checking_assert (is_initial_scan ()); + insert (decl, WK_value); + state->note_location (DECL_SOURCE_LOCATION (decl)); + return; + } + merge_kind mk = get_merge_kind (decl, dep); bool is_imported_temploid_friend = imported_temploid_friends->get (decl); @@ -8390,14 +8435,17 @@ trees_in::decl_value () /* Frob it to be ready for cloning. */ TREE_TYPE (inner) = DECL_ORIGINAL_TYPE (inner); DECL_ORIGINAL_TYPE (inner) = NULL_TREE; - set_underlying_type (inner); - if (tdef_flags & 2) + if (TREE_CODE (TREE_TYPE (inner)) != TU_LOCAL_ENTITY) { - /* Match instantiate_alias_template's handling. */ - tree type = TREE_TYPE (inner); - TYPE_DEPENDENT_P (type) = true; - TYPE_DEPENDENT_P_VALID (type) = true; - SET_TYPE_STRUCTURAL_EQUALITY (type); + set_underlying_type (inner); + if (tdef_flags & 2) + { + /* Match instantiate_alias_template's handling. */ + tree type = TREE_TYPE (inner); + TYPE_DEPENDENT_P (type) = true; + TYPE_DEPENDENT_P_VALID (type) = true; + SET_TYPE_STRUCTURAL_EQUALITY (type); + } } } @@ -8902,10 +8950,14 @@ trees_out::decl_node (tree decl, walk_kind ref) } tree_node (tpl); - /* Streaming TPL caused us to visit DECL and maybe its type. */ - gcc_checking_assert (TREE_VISITED (decl)); - if (DECL_IMPLICIT_TYPEDEF_P (decl)) - gcc_checking_assert (TREE_VISITED (TREE_TYPE (decl))); + /* Streaming TPL caused us to visit DECL and maybe its type, + if it wasn't TU-local. */ + if (CHECKING_P && !has_tu_local_dep (tpl)) + { + gcc_checking_assert (TREE_VISITED (decl)); + if (DECL_IMPLICIT_TYPEDEF_P (decl)) + gcc_checking_assert (TREE_VISITED (TREE_TYPE (decl))); + } return false; } @@ -8925,10 +8977,10 @@ trees_out::decl_node (tree decl, walk_kind ref) dep = dep_hash->add_dependency (decl, kind); } - if (!dep) + if (!dep || dep->is_tu_local ()) { /* Some internal entity of context. Do by value. */ - decl_value (decl, NULL); + decl_value (decl, dep); return false; } @@ -9084,7 +9136,10 @@ trees_out::type_node (tree type) if (streaming_p ()) dump (dumper::TREE) && dump ("Wrote typedef %C:%N%S", TREE_CODE (name), name, name); - gcc_checking_assert (TREE_VISITED (type)); + + /* We'll have either visited this type or have newly discovered + that it's TU-local; either way we won't need to visit it again. */ + gcc_checking_assert (TREE_VISITED (type) || has_tu_local_dep (name)); return; } @@ -9363,6 +9418,64 @@ trees_in::tree_value () return existing; } +/* Whether DECL has a TU-local dependency in the hash. */ + +bool +trees_out::has_tu_local_dep (tree decl) const +{ + /* Only the contexts of fields or enums remember that they're + TU-local. */ + if (DECL_CONTEXT (decl) + && (TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == CONST_DECL)) + decl = TYPE_NAME (DECL_CONTEXT (decl)); + + depset *dep = dep_hash->find_dependency (decl); + return dep && dep->is_tu_local (); +} + +/* If T depends on a TU-local entity, return that decl. */ + +tree +trees_out::find_tu_local_decl (tree t) +{ + /* We need to have walked all deps first before we can check. */ + gcc_checking_assert (!is_initial_scan ()); + + auto walker = [](tree *tp, int *walk_subtrees, void *data) -> tree + { + auto self = (trees_out *)data; + + tree decl = NULL_TREE; + if (TYPE_P (*tp)) + { + /* A PMF type is a record type, which we otherwise wouldn't walk; + return whether the function type is TU-local. */ + if (TYPE_PTRMEMFUNC_P (*tp)) + { + *walk_subtrees = 0; + return self->find_tu_local_decl (TYPE_PTRMEMFUNC_FN_TYPE (*tp)); + } + else + decl = TYPE_MAIN_DECL (*tp); + } + else if (DECL_P (*tp)) + decl = *tp; + + if (decl) + { + /* We found a DECL, this will tell us whether we're TU-local. */ + *walk_subtrees = 0; + return self->has_tu_local_dep (decl) ? decl : NULL_TREE; + } + return NULL_TREE; + }; + + /* We need to walk without duplicates so that we step into the pointed-to + types of array types. */ + return cp_walk_tree_without_duplicates (&t, walker, this); +} + /* Stream out tree node T. We automatically create local back references, which is essentially a single pass lisp self-referential structure pretty-printer. */ @@ -9375,6 +9488,46 @@ trees_out::tree_node (tree t) if (ref == WK_none) goto done; + /* Find TU-local entities and intercept streaming to instead write a + placeholder value; this way we don't need to expose such decls. + We only need to do this when writing a definition of an entity + that we know is an ignored exposure. */ + if (!is_initial_scan () && writing_local_entities) + { + tree local_decl = NULL_TREE; + if (DECL_P (t) && has_tu_local_dep (t)) + local_decl = t; + /* Consider a type to be TU-local if it refers to any TU-local decl, + no matter how deep. + + This worsens diagnostics slightly, as we often no longer point + directly to the at-fault entity when instantiating. However, this + reduces the module size slightly and means that much less of pt.cc + needs to know about us. */ + else if (TYPE_P (t)) + local_decl = find_tu_local_decl (t); + else if (EXPR_P (t)) + local_decl = find_tu_local_decl (TREE_TYPE (t)); + + if (local_decl) + { + int tag = insert (t, WK_value); + if (streaming_p ()) + { + tu_local_count++; + i (tt_tu_local); + dump (dumper::TREE) + && dump ("Writing TU-local entity:%d %C:%N", + tag, TREE_CODE (t), t); + } + /* TODO: Get a more descriptive name? */ + tree_node (DECL_NAME (local_decl)); + if (state) + state->write_location (*this, DECL_SOURCE_LOCATION (local_decl)); + goto done; + } + } + if (ref != WK_normal) goto skip_normal; @@ -10159,7 +10312,8 @@ trees_in::tree_node (bool is_use) /* A template. */ if (tree tpl = tree_node ()) { - res = DECL_TEMPLATE_RESULT (tpl); + res = (TREE_CODE (tpl) == TU_LOCAL_ENTITY ? + tpl : DECL_TEMPLATE_RESULT (tpl)); dump (dumper::TREE) && dump ("Read template %C:%N", TREE_CODE (res), res); } @@ -11933,8 +12087,18 @@ void trees_out::write_function_def (tree decl) { tree_node (DECL_RESULT (decl)); - tree_node (DECL_INITIAL (decl)); - tree_node (DECL_SAVED_TREE (decl)); + + { + /* The function body for a non-inline function or function template + is ignored for determining exposures. This should only matter + for templates (we don't emit the bodies of non-inline functions + to begin with). */ + auto ovr = make_temp_override (dep_hash->ignore_exposure, + !DECL_DECLARED_INLINE_P (decl)); + tree_node (DECL_INITIAL (decl)); + tree_node (DECL_SAVED_TREE (decl)); + } + tree_node (DECL_FRIEND_CONTEXT (decl)); constexpr_fundef *cexpr = retrieve_constexpr_fundef (decl); @@ -12036,6 +12200,10 @@ trees_in::read_function_def (tree decl, tree maybe_template) void trees_out::write_var_def (tree decl) { + /* The initializer of a variable or variable template is ignored for + determining exposures. */ + auto ovr = make_temp_override (dep_hash->ignore_exposure, VAR_P (decl)); + tree init = DECL_INITIAL (decl); tree_node (init); if (!init) @@ -12223,21 +12391,28 @@ trees_out::write_class_def (tree defn) for (; vtables; vtables = TREE_CHAIN (vtables)) write_definition (vtables); - /* Write the friend classes. */ - tree_list (CLASSTYPE_FRIEND_CLASSES (type), false); + { + /* Friend declarations in class definitions are ignored when + determining exposures. */ + auto ovr = make_temp_override (dep_hash->ignore_exposure, true); - /* Write the friend functions. */ - for (tree friends = DECL_FRIENDLIST (defn); - friends; friends = TREE_CHAIN (friends)) - { - /* Name of these friends. */ - tree_node (TREE_PURPOSE (friends)); - tree_list (TREE_VALUE (friends), false); - } - /* End of friend fns. */ - tree_node (NULL_TREE); + /* Write the friend classes. */ + tree_list (CLASSTYPE_FRIEND_CLASSES (type), false); + + /* Write the friend functions. */ + for (tree friends = DECL_FRIENDLIST (defn); + friends; friends = TREE_CHAIN (friends)) + { + tree_node (FRIEND_NAME (friends)); + tree_list (FRIEND_DECLS (friends), false); + } + /* End of friend fns. */ + tree_node (NULL_TREE); + } - /* Write the decl list. */ + /* Write the decl list. We don't need to ignore exposures of friend + decls here as any such decls should already have been added and + ignored above. */ tree_list (CLASSTYPE_DECL_LIST (type), true); if (TYPE_CONTAINS_VPTR_P (type)) @@ -12590,6 +12765,8 @@ trees_in::read_class_def (tree defn, tree maybe_template) friend_decls; friend_decls = TREE_CHAIN (friend_decls)) { tree f = TREE_VALUE (friend_decls); + if (TREE_CODE (f) == TU_LOCAL_ENTITY) + continue; DECL_BEFRIENDING_CLASSES (f) = tree_cons (NULL_TREE, type, DECL_BEFRIENDING_CLASSES (f)); @@ -12738,8 +12915,11 @@ trees_in::read_enum_def (tree defn, tree maybe_template) /* Write out the body of DECL. See above circularity note. */ void -trees_out::write_definition (tree decl) +trees_out::write_definition (tree decl, bool has_tu_local) { + auto ovr = make_temp_override (writing_local_entities, + writing_local_entities || has_tu_local); + if (streaming_p ()) { assert_definition (decl); @@ -13316,7 +13496,12 @@ depset::hash::add_dependency (depset *dep) current->deps.safe_push (dep); if (dep->is_tu_local ()) - current->set_flag_bit (); + { + if (ignore_exposure) + current->set_flag_bit (); + else + current->set_flag_bit (); + } if (current->get_entity_kind () == EK_USING && DECL_IMPLICIT_TYPEDEF_P (dep->get_entity ()) @@ -13966,7 +14151,7 @@ depset::hash::find_dependencies (module_state *module) { walker.mark_declaration (decl, current->has_defn ()); - if (!walker.is_key_order () + if (!is_key_order () && (item->get_entity_kind () == EK_SPECIALIZATION || item->get_entity_kind () == EK_PARTIAL || (item->get_entity_kind () == EK_DECL @@ -13978,15 +14163,16 @@ depset::hash::find_dependencies (module_state *module) walker.decl_value (decl, current); if (current->has_defn ()) - walker.write_definition (decl); + walker.write_definition (decl, + current->is_ignored_exposure ()); } walker.end (); - if (!walker.is_key_order () + if (!is_key_order () && DECL_CLASS_TEMPLATE_P (decl)) add_deduction_guides (decl); - if (!walker.is_key_order () + if (!is_key_order () && TREE_CODE (decl) == TEMPLATE_DECL && !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)) { @@ -14175,6 +14361,36 @@ depset::hash::finalize_dependencies () /* We should have emitted an error above. */ gcc_checking_assert (explained); } + else if (warn_ignored_exposures && dep->is_ignored_exposure ()) + { + tree decl = dep->get_entity (); + + /* Friend decls in a class body are ignored, but this is harmless: + it should not impact any consumers. */ + if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))) + continue; + + /* We should now only be warning about templates. */ + gcc_checking_assert + (TREE_CODE (decl) == TEMPLATE_DECL + && VAR_OR_FUNCTION_DECL_P (DECL_TEMPLATE_RESULT (decl))); + + /* Ideally we would only warn in cases where there are no explicit + instantiations of the template, but we don't currently track this + in an easy-to-find way. */ + for (depset *rdep : dep->deps) + if (!rdep->is_binding () && rdep->is_tu_local ()) + { + tree exposed = rdep->get_entity (); + auto_diagnostic_group d; + if (warning_at (DECL_SOURCE_LOCATION (decl), + OPT_Wignored_exposures, + "%qD refers to TU-local entity %qD and cannot " + "be instantiated in other TUs", decl, exposed)) + is_tu_local_entity (exposed, /*explain=*/true); + break; + } + } } return ok; @@ -15338,8 +15554,9 @@ enum ct_bind_flags void module_state::intercluster_seed (trees_out &sec, unsigned index_hwm, depset *dep) { - if (dep->is_import () - || dep->cluster < index_hwm) + if (dep->is_tu_local ()) + /* We only stream placeholders for TU-local entities anyway. */; + else if (dep->is_import () || dep->cluster < index_hwm) { tree ent = dep->get_entity (); if (!TREE_VISITED (ent)) @@ -15560,7 +15777,7 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size, sec.u (ct_defn); sec.tree_node (decl); dump () && dump ("Writing definition %N", decl); - sec.write_definition (decl); + sec.write_definition (decl, b->is_ignored_exposure ()); if (!namer->has_defn ()) namer = b; diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 769e7999dac..2d0b65854be 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -9862,6 +9862,71 @@ add_pending_template (tree d) pop_tinst_level (); } +/* Emit a diagnostic about instantiating a reference to TU-local entity E. */ + +static void +complain_about_tu_local_entity (tree e) +{ + auto_diagnostic_group d; + error ("instantiation exposes TU-local entity %qD", + TU_LOCAL_ENTITY_NAME (e)); + inform (TU_LOCAL_ENTITY_LOCATION (e), "declared here"); +} + +/* Checks if T contains a TU-local entity. */ + +static bool +expr_contains_tu_local_entity (tree t) +{ + if (!modules_p ()) + return false; + + auto walker = [](tree *tp, int *walk_subtrees, void *) -> tree + { + if (TREE_CODE (*tp) == TU_LOCAL_ENTITY) + return *tp; + if (!EXPR_P (*tp)) + *walk_subtrees = false; + return NULL_TREE; + }; + return cp_walk_tree (&t, walker, nullptr, nullptr); +} + +/* Errors and returns TRUE if X is a function that contains a TU-local + entity in its overload set. */ + +static bool +function_contains_tu_local_entity (tree x) +{ + if (!modules_p ()) + return false; + + if (!x || x == error_mark_node) + return false; + + if (TREE_CODE (x) == OFFSET_REF + || TREE_CODE (x) == COMPONENT_REF) + x = TREE_OPERAND (x, 1); + x = MAYBE_BASELINK_FUNCTIONS (x); + if (TREE_CODE (x) == TEMPLATE_ID_EXPR) + x = TREE_OPERAND (x, 0); + + if (OVL_P (x)) + for (tree ovl : lkp_range (x)) + if (TREE_CODE (ovl) == TU_LOCAL_ENTITY) + { + x = ovl; + break; + } + + if (TREE_CODE (x) == TU_LOCAL_ENTITY) + { + complain_about_tu_local_entity (x); + return true; + } + + return false; +} /* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS and ARGLIST. Valid choices for FNS are given in the cp-tree.def @@ -12727,8 +12792,10 @@ instantiate_class_template (tree type) } else { - if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t) - || DECL_TEMPLATE_TEMPLATE_PARM_P (t)) + if (TREE_CODE (t) == TU_LOCAL_ENTITY) + /* Ignore. */; + else if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t) + || DECL_TEMPLATE_TEMPLATE_PARM_P (t)) { /* Build new CLASSTYPE_FRIEND_CLASSES. */ @@ -15506,7 +15573,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, RETURN (error_mark_node); if (TREE_CODE (t) == TYPE_DECL - && t == TYPE_MAIN_DECL (TREE_TYPE (t))) + && (TREE_CODE (TREE_TYPE (t)) == TU_LOCAL_ENTITY + || t == TYPE_MAIN_DECL (TREE_TYPE (t)))) { /* If this is the canonical decl, we don't have to mess with instantiations, and often we can't (for @@ -16234,6 +16302,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) || TREE_CODE (t) == TRANSLATION_UNIT_DECL) return t; + /* Any instantiation of a template containing a TU-local entity is an + exposure, so always issue a hard error irrespective of complain. */ + if (TREE_CODE (t) == TU_LOCAL_ENTITY) + { + complain_about_tu_local_entity (t); + return error_mark_node; + } + tsubst_flags_t tst_ok_flag = (complain & tf_tst_ok); complain &= ~tf_tst_ok; @@ -18470,6 +18546,12 @@ dependent_operand_p (tree t) { while (TREE_CODE (t) == IMPLICIT_CONV_EXPR) t = TREE_OPERAND (t, 0); + + /* If we contain a TU_LOCAL_ENTITY assume we're non-dependent; we'll error + later when instantiating. */ + if (expr_contains_tu_local_entity (t)) + return false; + ++processing_template_decl; bool r = (potential_constant_expression (t) ? value_dependent_expression_p (t) @@ -20202,6 +20284,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) else object = NULL_TREE; + if (function_contains_tu_local_entity (templ)) + RETURN (error_mark_node); + tree tid = lookup_template_function (templ, targs); protected_set_expr_location (tid, EXPR_LOCATION (t)); @@ -20894,6 +20979,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) qualified_p = true; } + if (function_contains_tu_local_entity (function)) + RETURN (error_mark_node); + nargs = call_expr_nargs (t); releasing_vec call_args; tsubst_call_args (t, args, complain, in_decl, call_args); @@ -21915,6 +22003,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) RETURN (op); } + case TU_LOCAL_ENTITY: + complain_about_tu_local_entity (t); + RETURN (error_mark_node); + default: /* Handle Objective-C++ constructs, if appropriate. */ if (tree subst = objcp_tsubst_expr (t, args, complain, in_decl)) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a6cd5111d47..10a407a2e24 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -258,7 +258,7 @@ in the following sections. -Weffc++ -Wno-elaborated-enum-base -Wno-exceptions -Wextra-semi -Wno-global-module -Wno-inaccessible-base -Wno-inherited-variadic-ctor -Wno-init-list-lifetime --Winvalid-constexpr -Winvalid-imported-macros +-Wignored-exposures -Winvalid-constexpr -Winvalid-imported-macros -Wno-invalid-offsetof -Wno-literal-suffix -Wmismatched-new-delete -Wmismatched-tags -Wmultiple-inheritance -Wnamespaces -Wnarrowing @@ -4076,6 +4076,23 @@ the variable declaration statement. @end itemize +@opindex Wignored-exposures +@opindex Wno-ignored-exposures +@item -Wignored-exposures +Warn when a template body hides an exposure of a translation-unit-local +entity. In most cases, referring to a translation-unit-local entity +(such as an internal linkage declaration) within an entity that is +emitted into a module's CMI is an error. However, within the +initializer of a variable, or in the body of a non-inline function, +this error is suppressed. + +This can cause variable or function templates to accidentally become +unusable if they reference such an entity, because other translation +units that import the template will never be able to instantiate it. +This warning attempts to detect cases where this might occur. + +This warning is enabled by @option{-Wextra}. + @opindex Winvalid-constexpr @opindex Wno-invalid-constexpr @item -Winvalid-constexpr diff --git a/gcc/testsuite/g++.dg/modules/internal-5_a.C b/gcc/testsuite/g++.dg/modules/internal-5_a.C new file mode 100644 index 00000000000..a36fcb0d834 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-5_a.C @@ -0,0 +1,104 @@ +// { dg-additional-options "-fmodules-ts -Wignored-exposures" } +// { dg-module-cmi M } +// Ignore exposures in these cases + +export module M; + +namespace { + inline namespace ns { + struct internal_t {}; + template struct internal_tmpl_t {}; + + int internal_x; + void internal_ovl(int&) {} + void internal_ovl(internal_t) {} + + template void internal_tmpl() {} + } +} +export struct ok_inst_tag {}; + + +// The function body for a non-inline function or function template +export void function() { + internal_t i {}; + internal_tmpl_t ii {}; + internal_ovl(internal_x); + internal_tmpl(); +} + +export template void function_tmpl() { // { dg-warning "refers to TU-local entity" } + internal_t i {}; + internal_tmpl_t ii {}; + internal_ovl(internal_x); + internal_tmpl(); +} +template void function_tmpl(); + + +// The initializer for a variable or variable template +export int var + = (internal_t{}, internal_tmpl_t{}, + internal_ovl(internal_x), internal_tmpl(), 0); + +export template int var_tmpl // { dg-warning "refers to TU-local entity" } + = (internal_t{}, internal_tmpl_t{}, + internal_ovl(internal_x), internal_tmpl(), 0); + +template int var_tmpl // { dg-warning "refers to TU-local entity" } + = (internal_t{}, internal_tmpl_t{}, + internal_ovl(internal_x), internal_tmpl(), 0); + +template int var_tmpl; +template int var_tmpl; + +export int& constant_ref = internal_x; +static_assert (&constant_ref == &internal_x); + + +// Friend declarations in a class definition +export struct klass { // { dg-bogus "TU-local" } + friend ns::internal_t; + friend ns::internal_tmpl_t; + friend void ns::internal_ovl(int&); + friend void ns::internal_ovl(internal_t); + friend void ns::internal_tmpl(); + + template friend struct ns::internal_tmpl_t; + template friend void ns::internal_tmpl(); +}; + +export template +class klass_tmpl { // { dg-bogus "TU-local" } + friend ns::internal_t; + friend ns::internal_tmpl_t; + friend void ns::internal_ovl(int&); + friend void ns::internal_ovl(internal_t); + friend void ns::internal_tmpl(); + + template friend struct ns::internal_tmpl_t; + template friend void ns::internal_tmpl(); +}; + +template class klass_tmpl { // { dg-bogus "TU-local" } + friend ns::internal_t; + friend ns::internal_tmpl_t; + friend void ns::internal_ovl(int&); + friend void ns::internal_ovl(internal_t); + friend void ns::internal_tmpl(); + + template friend struct ns::internal_tmpl_t; + template friend void ns::internal_tmpl(); +}; + + +// Any reference to a non-volatile const object or reference with internal or +// no linkage initialized with a constant expression that is not an ODR-use +static const int value = 123; +static const int& ref = value; +static const internal_t internal {}; +export inline void no_odr_use() { + int x = value; + int y = ref; + int z = (internal, 0); +} diff --git a/gcc/testsuite/g++.dg/modules/internal-5_b.C b/gcc/testsuite/g++.dg/modules/internal-5_b.C new file mode 100644 index 00000000000..ecf78861fb7 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-5_b.C @@ -0,0 +1,29 @@ +// { dg-additional-options "-fmodules-ts" } + +import M; + +int main() { + // These are all OK + function(); + int a = var; + klass k; + klass_tmpl kt; + klass_tmpl ktp; + no_odr_use(); + + function_tmpl(); + int b = var_tmpl; + int c = var_tmpl; + + // But don't ignore exposures in these cases + function_tmpl(); // { dg-message "required from here" } + int x = var_tmpl; // { dg-message "required from here" } + int y = var_tmpl; // { dg-message "required from here" } + + // And decls initialized to a TU-local value are not constant here + // Unfortunately the error does not currently point to this decl + constexpr int& r = constant_ref; + // { dg-error "is not a constant expression" "" { target *-*-* } 0 } +} + +// { dg-error "instantiation exposes TU-local entity" "" { target *-*-* } 0 } diff --git a/gcc/testsuite/g++.dg/modules/internal-6.C b/gcc/testsuite/g++.dg/modules/internal-6.C new file mode 100644 index 00000000000..0f138781ad5 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-6.C @@ -0,0 +1,24 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi !M } +// Exposures (or not) of TU-local values + +export module M; + +static void f() {} +auto& fr = f; // OK +constexpr auto& fr2 = fr; // { dg-error "initialized to a TU-local value" } +static constexpr auto fp2 = fr; // OK + +struct S { void (&ref)(); } s{ f }; // OK, value is TU-local +constexpr extern struct W { S& s; } wrap{ s }; // OK, value is not TU-local +constexpr S s2{ f }; // { dg-error "initialized to a TU-local value" } + +constexpr int a = 123; +static constexpr int b = 456; +struct X { + union { + const int* p[2]; + }; +}; +constexpr X x { &a }; // OK +constexpr X y { &a, &b }; // { dg-error "initialized to a TU-local value" } diff --git a/gcc/testsuite/g++.dg/modules/internal-7_a.C b/gcc/testsuite/g++.dg/modules/internal-7_a.C new file mode 100644 index 00000000000..47b7f2eb54e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-7_a.C @@ -0,0 +1,75 @@ +// { dg-additional-options "-fmodules-ts -Wignored-exposures" } +// Test streaming and instantiations of various kinds of exposures + +export module M; + +namespace { + int x; + constexpr int y = 1; + + struct S { int m; void d(); }; + enum class E { e }; + + template int f(T t) { return (int)t; } +} + +template void g() {} + +template +int expose_1() { // { dg-warning "TU-local" } + return x; +} + +template +void expose_2() { // { dg-warning "TU-local" } + T t = &y; +} + +template +bool expose_3() { // { dg-warning "TU-local" } + return !(T{} * (x + 5) > 123); +} + +template +bool expose_4() { // { dg-warning "TU-local" } + return __is_same(S, T); +} + +template +void expose_5() { // { dg-warning "TU-local" } + static_assert(T{} == (int)E::e); +} + +template +void expose_6() { // { dg-warning "TU-local" } + f(T{}); +} + +template +void expose_7() { // { dg-warning "TU-local" } + g<&y>(); +} + +template +void expose_8() { // { dg-warning "TU-local" } + decltype(T{} .* &S::m)* (*x)[5][10]; +}; + +template +bool expose_9() { // { dg-warning "TU-local" } + return noexcept((T{} .* &S::d)()); +} + +template +void expose_10() { // { dg-warning "TU-local" } + using U = decltype(f()); +} + +template +void expose_11() { // { dg-warning "TU-local" } + static thread_local E r; +} + +template +int expose_var // { dg-warning "TU-local" } + = f(sizeof(T)); diff --git a/gcc/testsuite/g++.dg/modules/internal-7_b.C b/gcc/testsuite/g++.dg/modules/internal-7_b.C new file mode 100644 index 00000000000..2a11e449d6e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-7_b.C @@ -0,0 +1,21 @@ +// { dg-additional-options "-fmodules-ts" } + +module M; + +void inst() { + expose_1(); // { dg-message "required from here" } + expose_2(); // { dg-message "required from here" } + expose_3(); // { dg-message "required from here" } + expose_4(); // { dg-message "required from here" } + expose_5(); // { dg-message "required from here" } + expose_6(); // { dg-message "required from here" } + expose_7(); // { dg-message "required from here" } + expose_8(); // { dg-message "required from here" } + expose_9(); // { dg-message "required from here" } + expose_10(); // { dg-message "required from here" } + expose_11(); // { dg-message "required from here" } + + expose_var; // { dg-message "required from here" } +} + +// { dg-error "instantiation exposes TU-local entity" "" { target *-*-* } 0 } From patchwork Mon Sep 23 23:46:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988730 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=AGx/Xa1o; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKSs4tfQz1xsM for ; Tue, 24 Sep 2024 09:48:45 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DD6DB385C6E1 for ; Mon, 23 Sep 2024 23:48:43 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by sourceware.org (Postfix) with ESMTPS id 824AE385C6C8 for ; Mon, 23 Sep 2024 23:46:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 824AE385C6C8 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 824AE385C6C8 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1032 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135192; cv=none; b=TMrk6wUfMQghA+q65sUMRj+LGol1unDPIaGKUVk9kMdP3/jMnD3RObL8PWLIgzUIfmOD2KiwtIvR2X3dYRwSyRUQfmhtxUS5IO2RaLCWdb7s+sW3NYrjBay7VbtkMCLFFhQPrsnQo1ltmHsYMqqYHbjg2RAYDSe7B3hL+K+tLfE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135192; c=relaxed/simple; bh=38EvmMvPNDj08URfZ/BKePaPxqrPDQCop9EIUh9RXWY=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=PdFp+XPJVIMAOCTTTuDDv0qT4SLik5PVwF9718t2IZHGOtuZqj5GaPOq6N3Kf91BwiRUdaYYiC848gLIR/cZkNZqZOxSF8MrbdvBjvbC0yFvZuqiMcAYdVHs+B6tkPknmjIx/resMpts46FSszzIP+0EYJTp+ZfDiZ+Sz7CPL9M= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-2deec99c780so396648a91.2 for ; Mon, 23 Sep 2024 16:46:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135188; x=1727739988; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=g/juaRIfiaa1NK8SjkG5pAGqS0pOAQvZj9aGL9qqdI4=; b=AGx/Xa1oeavA4x6HFSWgJgorDNP/wTkVv80RVbpoEByf12tZ1JTosJeNXFR1S+mhW1 fwH/WU7LOLW+uZaAlAvqJlfbkuDGKLm7Iw5Z7ZA02d45lLKJPF+J/BOIM5CYDjGpu4sC PHlLxbzUAwWUJ9C28FhmqHI34v1D9/+93X8K7u/xBAKrhEj7cNry74TB5ctaL96y3DMP 67YkyrL7BBRoYRqsR2JE4dryVdvnkcwlDqzuYXz/k1d9SqVqVamwXn2kbv/FcgoBrrxd wYY4YxKRTU1kMfW5V0mS7BQjy2Zo60zSt+mzKopsfpWWHos5vacmtvMilg/vHFKiOTp5 uuqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135188; x=1727739988; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=g/juaRIfiaa1NK8SjkG5pAGqS0pOAQvZj9aGL9qqdI4=; b=C3MSzYyN0G/WQM9/pot/0SykanI4EHec6XwoalI4JYyYhFBS3f403HO3JrB2jRRZKn wTH7kemOV0NyyeAvjV70/eLE3dpVJfN0sVdcgL+78wSSvK84iCDthdtclxZVg3V9PvYZ P2X7MZVGfgteCYvvk3lnumbuVlO7NqViC0s44VQTFHjCVqWGstZJ2P1stgv6gYDQj8AB a6MOriMZRvSi28+1asLR8orxpTqlezW/mr38dlFPxtNct3m1Je3LLAhiMIPjMi9xu6zN Q1Vvv/LRzCUOGPrgTCXgb3XYmc1vnfNa7lwNozCHaE0NOsScig5QSoJyEWUrP3XraOi8 MnNA== X-Gm-Message-State: AOJu0YzwJOEF8xmzUMbT13/ZsZMQN5v/rPZkRBX1lxYGG1Kh0Y4Ssxk+ oegqgZqi+Ci5kGdB347lk6Hh45C5RzR0P++Wt/HpUCb1PE6BKEv0m7X+GA== X-Google-Smtp-Source: AGHT+IF1iWpow6Ml3oM1e49KTq3exLAvDA0Q2D0NogBqrQ2eYv6rQpsv69WPA0FNouu/TmJn+JpARw== X-Received: by 2002:a17:902:ecd1:b0:207:1367:c46d with SMTP id d9443c01a7336-208d8442833mr81948145ad.12.1727135188401; Mon, 23 Sep 2024 16:46:28 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7e6b7c320eesm109141a12.13.2024.09.23.16.46.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:46:27 -0700 (PDT) Message-ID: <66f1fdd3.630a0220.308aca.0457@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:46:24 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 08/10] c++/modules: Support anonymous namespaces in header units References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- A header unit may contain anonymous namespaces, and those declarations are exported (as with any declaration in a header unit). This patch ensures that such declarations are correctly handled. The change to 'make_namespace_finish' is required so that if an anonymous namespace is first seen by an import it is correctly handled within 'add_imported_namespace'. I don't see any particular reason why handling of anonymous namespaces here had to be handled separately outside that function since these are the only two callers. gcc/cp/ChangeLog: * module.cc (depset::hash::add_binding_entity): Also walk anonymous namespaces. (module_state::write_namespaces): Adjust assertion. * name-lookup.cc (push_namespace): Move anon using-directive handling to... (make_namespace_finish): ...here. gcc/testsuite/ChangeLog: * g++.dg/modules/internal-8_a.H: New test. * g++.dg/modules/internal-8_b.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/module.cc | 7 +++-- gcc/cp/name-lookup.cc | 8 +++--- gcc/testsuite/g++.dg/modules/internal-8_a.H | 28 ++++++++++++++++++++ gcc/testsuite/g++.dg/modules/internal-8_b.C | 29 +++++++++++++++++++++ 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/internal-8_a.H create mode 100644 gcc/testsuite/g++.dg/modules/internal-8_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 7b1e69cb4c0..f114c2ec980 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -13717,15 +13717,15 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_) return (flags & WMB_Using ? flags & WMB_Export : DECL_MODULE_EXPORT_P (decl)); } - else if (DECL_NAME (decl) && !data->met_namespace) + else if (!data->met_namespace) { /* Namespace, walk exactly once. */ - gcc_checking_assert (TREE_PUBLIC (decl)); data->met_namespace = true; if (data->hash->add_namespace_entities (decl, data->partitions)) { /* It contains an exported thing, so it is exported. */ gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl)); + gcc_checking_assert (TREE_PUBLIC (decl) || header_module_p ()); DECL_MODULE_EXPORT_P (decl) = true; } @@ -16120,8 +16120,7 @@ module_state::write_namespaces (elf_out *to, vec spaces, tree ns = b->get_entity (); gcc_checking_assert (TREE_CODE (ns) == NAMESPACE_DECL); - /* P1815 may have something to say about this. */ - gcc_checking_assert (TREE_PUBLIC (ns)); + gcc_checking_assert (TREE_PUBLIC (ns) || header_module_p ()); unsigned flags = 0; if (TREE_PUBLIC (ns)) diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index cbb2827808f..5f0b056f272 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -9094,6 +9094,9 @@ make_namespace_finish (tree ns, tree *slot, bool from_import = false) if (DECL_NAMESPACE_INLINE_P (ns) || !DECL_NAME (ns)) emit_debug_info_using_namespace (ctx, ns, true); + + if (!DECL_NAMESPACE_INLINE_P (ns) && !DECL_NAME (ns)) + add_using_namespace (NAMESPACE_LEVEL (ctx)->using_directives, ns); } /* Push into the scope of the NAME namespace. If NAME is NULL_TREE, @@ -9230,11 +9233,6 @@ push_namespace (tree name, bool make_inline) gcc_checking_assert (slot); } make_namespace_finish (ns, slot); - - /* Add the anon using-directive here, we don't do it in - make_namespace_finish. */ - if (!DECL_NAMESPACE_INLINE_P (ns) && !name) - add_using_namespace (current_binding_level->using_directives, ns); } } diff --git a/gcc/testsuite/g++.dg/modules/internal-8_a.H b/gcc/testsuite/g++.dg/modules/internal-8_a.H new file mode 100644 index 00000000000..57fe60bb3c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-8_a.H @@ -0,0 +1,28 @@ +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +static int x = 123; +static void f() {} +template static void t() {} + +namespace { + int y = 456; + void g() {}; + template void u() {} + + namespace ns { int in_ns = 456; } + + struct A {}; + template struct B {}; + + enum E { X }; + enum class F { Y }; + + template using U = int; + +#if __cplusplus >= 202002L + template concept C = true; +#endif +} + +namespace ns2 = ns; diff --git a/gcc/testsuite/g++.dg/modules/internal-8_b.C b/gcc/testsuite/g++.dg/modules/internal-8_b.C new file mode 100644 index 00000000000..a2d74a87473 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-8_b.C @@ -0,0 +1,29 @@ +// { dg-additional-options "-fmodules-ts" } + +import "internal-8_a.H"; + +int main() { + auto x2 = x; + f(); + t(); + + auto y2 = y; + g(); + u(); + + int val1 = ns::in_ns; + + A a; + B b; + + E e = X; + F f = F::Y; + + U temp; + +#if __cplusplus >= 202002L + static_assert(C); +#endif + + int val2 = ns2::in_ns; +} From patchwork Mon Sep 23 23:46:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988728 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=MTD20Qr5; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKRJ48sNz1xsM for ; Tue, 24 Sep 2024 09:47:24 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6F16F385DDF2 for ; Mon, 23 Sep 2024 23:47:22 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by sourceware.org (Postfix) with ESMTPS id A91DC385DDC2 for ; Mon, 23 Sep 2024 23:46:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A91DC385DDC2 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A91DC385DDC2 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::430 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135221; cv=none; b=O9MHfiP4jE69AGui8vq89iZstWN0FoSwfuVqegHo4J2HWKw5zeBbUoGoORJJ9gI3SUSdRKGTAs3rDr1GWAlL844qxu1Dzaj1od/l2rapq9MBcxwnHtyntuRZtecbC//zfVZDIsf0A9SdugqpBZi02WbgqjN9kdwrWgi58pPN8TI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135221; c=relaxed/simple; bh=YXbeKK5p/l/F51O2ilkJrZx3f0fC/pKXpw0qsnt0bng=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=WGTJzwDMKrwCjSpts+5/L0FyxeUlZ1Co+C4D2ZSu2+1Vd+nk1xxasn/S5avx4m62HtuMFyFOmJw3CbzdcUiXQ6DsO8k+L5A65T/v4ILWDLje22nXYTB2oVazJ0s4W/qbqpEAsfuktBdFZWTUq+2F17aMfI4Pg7+6l5FCuSb2jN0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-717839f9eb6so792871b3a.3 for ; Mon, 23 Sep 2024 16:46:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135214; x=1727740014; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=KMv5UVMijK7/CeWqCH979vIvK5JRnoQR+9T1MLcYtZo=; b=MTD20Qr5vnzw98s46TCoOhTN7QeBuxF54bTGivUDAm2f/Kg2L+m4CSsiY1L5I3RUEx aBRm/EY0xcWHHRiFdypLYD3DlO4g+stQD1IKnExz1Pvd1Cwo8XcwMiJQiA7fB3HClx7M FpEKtZlWfmqSZyQzHKf8ToVZB9gJ1BzxaASA+tHGD2zRkGv6qFZ62DUP88Qb9/tFzAk7 l0wTvS2rXMgqszEGw9d7UvKi2tLsAt6iGjKEhiI3dMY6qZ/7eztAtsV1oFPUmPYPMmvl jbCoCWt6Lb9hSo1aNMATVGX0f6XnIlKJwA+n0plt+b44xgVTp5nn84FwHtwmDgRuAZs1 3ExA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135214; x=1727740014; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=KMv5UVMijK7/CeWqCH979vIvK5JRnoQR+9T1MLcYtZo=; b=ArFD8yLX3y+EFCdDoEvcaR3WP/YwZaRWryLTqT+RdCUFnZCLgYaxpoSu2JzbZWObYd o6tCIWrwsN7OSB6VvFs8FnP0rJDfclDHxsGii6SgSvgccE2hK1ziqQ/hEN6uyoY9yi8X QmT1PryNp2uWQn/YNJHD7PfUVJT0SfSvT1RiMUz873C0WBv3FtgTqerkIcR+k4nivdOV wSD2Nyz6gKT9+I2iKeXpaI2uVhtw6qZPR6BHHLNujyRDgjRm/xv5lwq9QGM2YSoeI1pr NVNHDC97roW5JYFIoyYvlIieJxsueqQsIgW7nDFvkUWdNpdNQ9Dguy/exPuPOFtwy78H ApYw== X-Gm-Message-State: AOJu0Yy/RSmOZdeeXYAjm4I2WBjlEUuSIG7S7B4nZL+WlobGqoX8daiF ioWg1R/KlWfr/92W1rZ5CsPsWS/o09Cj0/jdt3C3xhhjP/IOe+FiAG1LKA== X-Google-Smtp-Source: AGHT+IFI2P7wpKG0QyYKBnElXKTI0OZHQlGenG07kXn1MYBfpupD4hXInvp9ejCw/SaanazWdpWdAQ== X-Received: by 2002:a17:90b:1dc6:b0:2dd:5137:a9da with SMTP id 98e67ed59e1d1-2e058148b06mr413436a91.6.1727135214247; Mon, 23 Sep 2024 16:46:54 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2dd6ee9f43dsm10105985a91.24.2024.09.23.16.46.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:46:53 -0700 (PDT) Message-ID: <66f1fded.170a0220.1649dc.7196@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:46:50 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 09/10] c++/modules: Check linkage for exported declarations References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- By [module.interface] p3, if an exported declaration is not within a header unit, it shall not declare a name with internal linkage. Unfortunately we cannot just do this within set_originating_module, since at the locations its called the linkage for declarations are not always fully determined yet. We could move the calls but this causes the checking assertion to fail as the originating module declaration may have moved, and in general for some kinds of declarations it's not always obvious where it should be moved to. This patch instead introduces a new function to check that the linkage of a declaration within a module is correct, to be called for all declarations once their linkage is fully determined. As a drive-by fix this patch also improves the source location of namespace aliases to point at the identifier rather than the terminating semicolon. gcc/cp/ChangeLog: * cp-tree.h (check_module_decl_linkage): Declare. * decl2.cc (finish_static_data_member_decl): Check linkage. * module.cc (set_originating_module): Adjust comment. (check_module_decl_linkage): New function. * name-lookup.cc (do_namespace_alias): Build alias with specified location, check linkage. (pushtag): Check linkage. (push_namespace): Slightly clarify error message. * name-lookup.h (do_namespace_alias): Add location parameter. * parser.cc (cp_parser_namespace_alias_definition): Pass identifier location to do_namespace_alias. (cp_parser_alias_declaration): Check linkage. (cp_parser_init_declarator): Check linkage. (cp_parser_function_definition_after_declarator): Check linkage. (cp_parser_save_member_function_body): Check linkage. * pt.cc (finish_concept_definition): Mark as public, check linkage. libcc1/ChangeLog: * libcp1plugin.cc (plugin_add_namespace_alias): Call do_namespace_alias with input_location. gcc/testsuite/ChangeLog: * g++.dg/modules/export-3.C: Adjust error message. * g++.dg/modules/export-6.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/cp-tree.h | 1 + gcc/cp/decl2.cc | 1 + gcc/cp/module.cc | 29 +++++++++++++++++--- gcc/cp/name-lookup.cc | 15 ++++++++--- gcc/cp/name-lookup.h | 2 +- gcc/cp/parser.cc | 9 ++++++- gcc/cp/pt.cc | 2 ++ gcc/testsuite/g++.dg/modules/export-3.C | 2 +- gcc/testsuite/g++.dg/modules/export-6.C | 35 +++++++++++++++++++++++++ libcc1/libcp1plugin.cc | 2 +- 10 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/export-6.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 85c1d23c240..05731a66df3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7454,6 +7454,7 @@ extern void set_originating_module (tree, bool friend_p = false); extern tree get_originating_module_decl (tree) ATTRIBUTE_PURE; extern int get_originating_module (tree, bool for_mangle = false) ATTRIBUTE_PURE; extern unsigned get_importing_module (tree, bool = false) ATTRIBUTE_PURE; +extern void check_module_decl_linkage (tree); /* Where current instance of the decl got declared/defined/instantiated. */ extern void set_instantiating_module (tree); diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 0279372488c..97ce4473b1c 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -1019,6 +1019,7 @@ finish_static_data_member_decl (tree decl, } cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags); + check_module_decl_linkage (decl); } /* DECLARATOR and DECLSPECS correspond to a class member. The other diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index f114c2ec980..d7e6fe2c54f 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -19920,11 +19920,34 @@ set_originating_module (tree decl, bool friend_p ATTRIBUTE_UNUSED) DECL_MODULE_ATTACH_P (decl) = true; } - if (!module_exporting_p ()) + /* It is illegal to export a declaration with internal linkage. However, at + the point this function is called we don't always know yet whether this + declaration has internal linkage; instead we defer this check for callers + to do once visibility has been determined. */ + if (module_exporting_p ()) + DECL_MODULE_EXPORT_P (decl) = true; +} + +/* Checks whether DECL within a module unit has valid linkage for its kind. + Must be called after visibility for DECL has been finalised. */ + +void +check_module_decl_linkage (tree decl) +{ + if (!module_has_cmi_p ()) return; - // FIXME: Check ill-formed linkage - DECL_MODULE_EXPORT_P (decl) = true; + /* An internal-linkage declaration cannot be generally be exported. + But it's OK to export any declaration from a header unit, including + internal linkage declarations. */ + if (!header_module_p () + && DECL_MODULE_EXPORT_P (decl) + && decl_linkage (decl) == lk_internal) + { + error_at (DECL_SOURCE_LOCATION (decl), + "exporting declaration %qD with internal linkage", decl); + DECL_MODULE_EXPORT_P (decl) = false; + } } /* DECL is keyed to CTX for odr purposes. */ diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 5f0b056f272..050539a1603 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -6594,7 +6594,7 @@ pop_decl_namespace (void) /* Process a namespace-alias declaration. */ void -do_namespace_alias (tree alias, tree name_space) +do_namespace_alias (location_t loc, tree alias, tree name_space) { if (name_space == error_mark_node) return; @@ -6604,12 +6604,13 @@ do_namespace_alias (tree alias, tree name_space) name_space = ORIGINAL_NAMESPACE (name_space); /* Build the alias. */ - alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node); + alias = build_lang_decl_loc (loc, NAMESPACE_DECL, alias, void_type_node); DECL_NAMESPACE_ALIAS (alias) = name_space; DECL_EXTERNAL (alias) = 1; DECL_CONTEXT (alias) = FROB_CONTEXT (current_scope ()); TREE_PUBLIC (alias) = TREE_PUBLIC (DECL_CONTEXT (alias)); set_originating_module (alias); + check_module_decl_linkage (alias); pushdecl (alias); @@ -8542,6 +8543,7 @@ pushtag (tree name, tree type, TAG_how how) /* Set type visibility now if this is a forward declaration. */ TREE_PUBLIC (decl) = 1; determine_visibility (decl); + check_module_decl_linkage (decl); return type; } @@ -9245,8 +9247,13 @@ push_namespace (tree name, bool make_inline) if (TREE_PUBLIC (ns)) DECL_MODULE_EXPORT_P (ns) = true; else if (!header_module_p ()) - error_at (input_location, - "exporting namespace with internal linkage"); + { + if (name) + error_at (input_location, + "exporting namespace %qD with internal linkage", ns); + else + error_at (input_location, "exporting anonymous namespace"); + } } if (module_purview_p ()) DECL_MODULE_PURVIEW_P (ns) = true; diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index f39f5309150..26b3b1ffc62 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -444,7 +444,7 @@ extern tree cp_namespace_decls (tree); extern void set_decl_namespace (tree, tree, bool); extern void push_decl_namespace (tree); extern void pop_decl_namespace (void); -extern void do_namespace_alias (tree, tree); +extern void do_namespace_alias (location_t, tree, tree); extern tree do_class_using_decl (tree, tree); extern tree lookup_arg_dependent (tree, tree, vec *); extern tree search_anon_aggr (tree, tree, bool = false); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index f75d3f53343..b1adf12a9b5 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -22354,6 +22354,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser) /* Look for the `namespace' keyword. */ cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE); /* Look for the identifier. */ + location_t id_location = cp_lexer_peek_token (parser->lexer)->location; identifier = cp_parser_identifier (parser); if (identifier == error_mark_node) return; @@ -22377,7 +22378,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser) cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); /* Register the alias in the symbol table. */ - do_namespace_alias (identifier, namespace_specifier); + do_namespace_alias (id_location, identifier, namespace_specifier); } /* Parse a qualified-namespace-specifier. @@ -22826,6 +22827,8 @@ cp_parser_alias_declaration (cp_parser* parser) check_member_template (decl); } + check_module_decl_linkage (decl); + return decl; } @@ -23883,6 +23886,7 @@ cp_parser_init_declarator (cp_parser* parser, `explicit' constructor cannot be used. */ ((is_direct_init || !is_initialized) ? LOOKUP_NORMAL : LOOKUP_IMPLICIT)); + check_module_decl_linkage (decl); } else if ((cxx_dialect != cxx98) && friend_p && decl && TREE_CODE (decl) == FUNCTION_DECL) @@ -33124,6 +33128,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, /* Finish the function. */ fn = finish_function (inline_p); + check_module_decl_linkage (fn); if (modules_p () && !inline_p @@ -33778,6 +33783,8 @@ cp_parser_save_member_function_body (cp_parser* parser, /* Add FN to the queue of functions to be parsed later. */ vec_safe_push (unparsed_funs_with_definitions, fn); + check_module_decl_linkage (fn); + return fn; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 2d0b65854be..5cea47eab3e 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -29680,11 +29680,13 @@ finish_concept_definition (cp_expr id, tree init, tree attrs) tree decl = build_lang_decl_loc (loc, CONCEPT_DECL, *id, boolean_type_node); DECL_CONTEXT (decl) = current_scope (); DECL_INITIAL (decl) = init; + TREE_PUBLIC (decl) = true; if (attrs) cplus_decl_attributes (&decl, attrs, 0); set_originating_module (decl, false); + check_module_decl_linkage (decl); /* Push the enclosing template. */ return push_template_decl (decl); diff --git a/gcc/testsuite/g++.dg/modules/export-3.C b/gcc/testsuite/g++.dg/modules/export-3.C index 6af314b9519..cdb8e9c0841 100644 --- a/gcc/testsuite/g++.dg/modules/export-3.C +++ b/gcc/testsuite/g++.dg/modules/export-3.C @@ -25,4 +25,4 @@ namespace { export namespace ns {} // { dg-error "internal linkage" } } -export namespace {} // { dg-error "internal linkage" } +export namespace {} // { dg-error "exporting anonymous namespace" } diff --git a/gcc/testsuite/g++.dg/modules/export-6.C b/gcc/testsuite/g++.dg/modules/export-6.C new file mode 100644 index 00000000000..a2cc86a7b8e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/export-6.C @@ -0,0 +1,35 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi !bad } + +export module bad; + +export static int x = 123; // { dg-error "internal linkage" } +export static void f(); // { dg-error "internal linkage" } +export static void g() {} // { dg-error "internal linkage" } +export template static void t(); // { dg-error "internal linkage" } +export template static void u() {} // { dg-error "internal linkage" } + +namespace { + export int y = 456; // { dg-error "internal linkage" } + export void h(); // { dg-error "internal linkage" } + export void i() {} // { dg-error "internal linkage" } + export template void v(); // { dg-error "internal linkage" } + export template void w() {} // { dg-error "internal linkage" } + + export namespace ns {} // { dg-error "internal linkage" } + + export struct A {}; // { dg-error "internal linkage" } + export template struct B {}; // { dg-error "internal linkage" } + + export enum E {}; // { dg-error "internal linkage" } + export enum class F {}; // { dg-error "internal linkage" } + + export template using U = int; // { dg-error "internal linkage" } + +#if __cplusplus >= 202002L + export template concept C = true; // { dg-error "internal linkage" "" { target c++20 } } +#endif +} + +export namespace {} // { dg-error "exporting anonymous namespace" } +export namespace ns2 = ns; // { dg-error "internal linkage" } diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index da68c5d0ac1..97877ad9138 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -799,7 +799,7 @@ plugin_add_namespace_alias (cc1_plugin::connection *, tree name = get_identifier (id); tree target = convert_in (target_in); - do_namespace_alias (name, target); + do_namespace_alias (input_location, name, target); return 1; } From patchwork Mon Sep 23 23:47:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1988729 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=IDnlgf3l; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCKRw0qv9z1xsM for ; Tue, 24 Sep 2024 09:47:56 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D66F7385DDD8 for ; Mon, 23 Sep 2024 23:47:53 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) by sourceware.org (Postfix) with ESMTPS id 9BF28385DDF5 for ; Mon, 23 Sep 2024 23:47:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9BF28385DDF5 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9BF28385DDF5 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135245; cv=none; b=J/oxgGmiUbWbb2A7UgurW49TRBw9i9yuNkXGuF53NX2puqUwbrtsXh8mCyvxnB21135XjVZuIT3d/v1ImNGHmGdi7zWz/wiKGD2tTw6DGJZYkpZ5XJFPox92r2YbSsvOVXhOlkKmBgP3sQr+gtQ7vvppnCun/aP/tG8Z4zWu124= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727135245; c=relaxed/simple; bh=n/GHyMn6fL2mWrQnZstoBAbwcB6pujjwKOxnrLtuamg=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=k29pGdsgNTotmTSpH+z6f3NponnlH7uEsgyxoahlFftriKoEdY/EgYnn19ajO7AXgi++5iVYCy3XTnAe45xk0TOvFYf6myjNgaNtxdkqcvYYVs/FogVhVQmgIJefEAl68tigz+Hyd0mIzapQjgEY45LpzTrPFv+46x1rVOoB9+I= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-7dafb321dbcso326642a12.1 for ; Mon, 23 Sep 2024 16:47:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727135241; x=1727740041; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=J7FlxQ+rPwOUTL4sJocddWDvjdrLuO4u73fJMwOKJIw=; b=IDnlgf3l0EHAuONALI10DTYuyBfIGdyFSI91thwERxF62wwOVVlP7FHJWvwIu5GjQU yWFFfE4II9pPh9Qq1V6qZGVcxhB64ysTyS7Tt64lqKl/MYs6tt2zk3g033pUoIvoD5OP QQqJx7fiE4h0HcpPqZKdK7rX3q04bQxaZDB6NnHkBsk77PNIY5bJtZqLViSXo0vZ/x3I cpi8IyaGL2c/x4nYTfnbbqRnLS6kcyxdbtywne9k7JHLgnFMq+HjdPDvR72C7djhxH9l 8hsMFP89I/d9O0vq8VHcwmxuqEeAUOpBKL8tDcK1LSUAQFMd1pm0qCFKxeR6e/t1I23J NY+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727135242; x=1727740042; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=J7FlxQ+rPwOUTL4sJocddWDvjdrLuO4u73fJMwOKJIw=; b=HJmK6bP4/jNy+qPUwD8hVhsKKH3TtzXXPbVzM+mOqTLd4CBSF4ycFWWEHZ8UQQUjp8 WrDWF8HbLXPUaD20bXq+rmpAX84U0oI+WY4bC315CZjfMf8P6iDFSGMTGlmNjreMvamf S9Pm4tbel4/Y0pUTL/x37PPQmjlNu8whDCAf2fwAAr+quF1kWgnXGolKjpy4aXNZhE3o +zw0t0IoZOiSFrQjHVW2+1l+KeQ7miU/SidPiNkHZLWIzgc8cSD4zUGW9w16yjpiy64N 1x8lzHKyqUJZ9MZgnywnY/ckdRFZeIwMTq2Tfug+woWsgB8lGetPehCL5idHL39S4mCX 0wIQ== X-Gm-Message-State: AOJu0Yy0hmMV37GCvve1dM5lfWKTkS4OJxdn+hHwU7tOaxiQyyA/Ca8Q Jufh3ZSKjOP/TReHahbpyq3p9ouBw1oXhz9Eo64LvWWltYF5hj+ZxndkTg== X-Google-Smtp-Source: AGHT+IFprL48BOlPp/7ZJpRtq1vJsczvdv+M7EzTRCEkNQgSAhqXvJw1KWiCe2cgZm9c6zcxnop/rQ== X-Received: by 2002:a05:6a21:7891:b0:1cf:37d4:c50b with SMTP id adf61e73a8af0-1d30a94d354mr10042436637.4.1727135241480; Mon, 23 Sep 2024 16:47:21 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc847938sm155554b3a.86.2024.09.23.16.47.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 16:47:21 -0700 (PDT) Message-ID: <66f1fe09.050a0220.363eeb.069b@mx.google.com> X-Google-Original-Message-ID: Date: Tue, 24 Sep 2024 09:47:17 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 10/10] c++/modules: Validate external linkage definitions in header units [PR116401] References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 -- [module.import] p6 says "A header unit shall not contain a definition of a non-inline function or variable whose name has external linkage." This patch implements this requirement, and cleans up some issues in the testsuite where this was already violated. To handle deduction guides we mark them as inline, since although we give them a definition for implementation by the standard they have no definition, and so should not error in this case. One remaining question is the behaviour of code like: struct S { static const int x = 123; }; 'S::x' is not 'inline' here, but this is legal code as long as there is exactly one definition elsewhere if 'x' is ever odr-used, as specified by [class.static.data] p4. However, since it's not 'inline' then the exemption for [module.import] does not apply, and so it appears uses of this in header units should error. Unfortunately the standard library headers do this, and there doesn't appear to be an easy C++98-compatible way to adjust this. Additionally I'm not entirely certain that this wasn't an oversight; as such this patch reduces this specific case to merely a pedwarn. PR c++/116401 gcc/cp/ChangeLog: * decl.cc (grokfndecl): Mark deduction guides as 'inline'. * module.cc (check_module_decl_linkage): Implement checks for non-inline external linkage definitions in headers. gcc/testsuite/ChangeLog: * g++.dg/modules/macro-4_c.H: Add missing 'inline'. * g++.dg/modules/pr106761.h: Likewise. * g++.dg/modules/pr98843_b.H: Likewise. * g++.dg/modules/pr99468.H: Likewise. * g++.dg/modules/pragma-1_a.H: Likewise. * g++.dg/modules/tpl-ary-1.h: Likewise. * g++.dg/modules/hdr-2.H: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/decl.cc | 1 + gcc/cp/module.cc | 33 +++++ gcc/testsuite/g++.dg/modules/hdr-2.H | 164 ++++++++++++++++++++++ gcc/testsuite/g++.dg/modules/macro-4_c.H | 2 +- gcc/testsuite/g++.dg/modules/pr106761.h | 2 +- gcc/testsuite/g++.dg/modules/pr98843_b.H | 2 +- gcc/testsuite/g++.dg/modules/pr99468.H | 2 +- gcc/testsuite/g++.dg/modules/pragma-1_a.H | 2 +- gcc/testsuite/g++.dg/modules/tpl-ary-1.h | 2 +- 9 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/hdr-2.H diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 2190ede745b..0203bbb682b 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -10818,6 +10818,7 @@ grokfndecl (tree ctype, have one: the restriction that you can't repeat a deduction guide makes them more like a definition anyway. */ DECL_INITIAL (decl) = void_node; + DECL_DECLARED_INLINE_P (decl) = true; break; default: break; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index d7e6fe2c54f..143eb676ce9 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -19937,6 +19937,39 @@ check_module_decl_linkage (tree decl) if (!module_has_cmi_p ()) return; + /* A header unit shall not contain a definition of a non-inline function + or variable (not template) whose name has external linkage. */ + if (header_module_p () + && !processing_template_decl + && ((TREE_CODE (decl) == FUNCTION_DECL + && !DECL_DECLARED_INLINE_P (decl) + && DECL_INITIAL (decl)) + || (TREE_CODE (decl) == VAR_DECL + && !DECL_INLINE_VAR_P (decl) + && DECL_INITIALIZED_P (decl))) + && !(DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INSTANTIATION (decl)) + && decl_linkage (decl) == lk_external) + { + /* Strictly speaking, + + struct S { static const int x = 123; }; + + is not valid in a header unit as currently specified. But this is + done within the standard library, and there doesn't seem to be a + C++98-compatible alternative, so we support this with a pedwarn. */ + if (VAR_P (decl) + && DECL_CLASS_SCOPE_P (decl) + && DECL_INITIALIZED_IN_CLASS_P (decl)) + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic, + "external linkage definition of %qD in header module must " + "be declared %", decl); + else + error_at (DECL_SOURCE_LOCATION (decl), + "external linkage definition of %qD in header module must " + "be declared %", decl); + } + /* An internal-linkage declaration cannot be generally be exported. But it's OK to export any declaration from a header unit, including internal linkage declarations. */ diff --git a/gcc/testsuite/g++.dg/modules/hdr-2.H b/gcc/testsuite/g++.dg/modules/hdr-2.H new file mode 100644 index 00000000000..bb3d7d70123 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/hdr-2.H @@ -0,0 +1,164 @@ +// { dg-additional-options "-fmodule-header -Wno-error=pedantic" } +// { dg-module-cmi !{} } +// external linkage variables or functions in header units must +// not have non-inline definitions + +int x_err; // { dg-error "inline" } +int y_err = 123; // { dg-error "inline" } +void f_err() {} // { dg-error "inline" } + +struct Err { + Err(); + void m(); + static void s(); + static int x; + static int y; +}; +Err::Err() = default; // { dg-error "inline" } +void Err::m() {} // { dg-error "inline" } +void Err::s() {} // { dg-error "inline" } +int Err::x; // { dg-error "inline" } +int Err::y = 123; // { dg-error "inline" } + +// Strictly speaking erroneous, but we support anyway with pedwarn: +struct Ped { + enum E { V }; + static const int x = 123; // { dg-warning "inline" } + static const E e = V; // { dg-warning "inline" } +}; + +// No definition, OK +extern int y_decl; +void f_decl(); + +template struct DeductionGuide {}; +DeductionGuide() -> DeductionGuide; + +// Inline decls are OK +inline int x_inl; +inline int y_inl = 123; +inline void f_inl() {} +constexpr void g_inl() {} +void h_inl() = delete; + +struct Inl { + void m() {} + static void s() {} + static inline int x; + static inline int y = 123; +}; + +// Internal linkage decls are OK +static int x_internal; +static int y_internal = 123; +static void f_internal() {} + +namespace { + struct Internal { + void m(); + static void s(); + static int x; + static int y; + }; + void Internal::m() {} + void Internal::s() {} + int Internal::x; + int Internal::y = 123; +} + +// Function-scope entities are OK +inline void f_static() { + static int x_static; + static int y_static = 123; + thread_local int x_thread_local; + thread_local int y_thread_local = 123; + + x_static = y_static; + x_thread_local = y_thread_local; +} + +// Templates (not functions or variables) are OK +template int x_tpl; +template int y_tpl = 123; +template void f_tpl() {} + +struct Template_Body { + template void m(); + template static void s(); + template static int x; + template static int y; +}; +template void Template_Body::m() {} +template void Template_Body::s() {} +template int Template_Body::x; +template int Template_Body::y = 123; + +template struct Template_Type { + void m(); + static void s(); + static int x; + static int y; +}; +template void Template_Type::m() {} +template void Template_Type::s() {} +template int Template_Type::x; +template int Template_Type::y = 123; + +// Implicit instantiations are OK +inline void instantiate_tmpls() { + x_tpl = y_tpl; + f_tpl(); + + Template_Body{}.m(); + Template_Body::s(); + Template_Body::x = Template_Body::y; + + using TT = Template_Type; + TT{}.m(); + TT::s(); + TT::x = TT::y; +} + +// Explicit instantiations are also OK (extern or otherwise) +template int x_tpl; +template int y_tpl; +template void f_tpl(); + +template void Template_Body::m(); +template void Template_Body::s(); +template int Template_Body::x; +template int Template_Body::y; + +template void Template_Type::m(); +template void Template_Type::s(); +template int Template_Type::x; +template int Template_Type::y; + +extern template int x_tpl; +extern template int y_tpl; +extern template void f_tpl(); + +extern template void Template_Body::m(); +extern template void Template_Body::s(); +extern template int Template_Body::x; +extern template int Template_Body::y; + +extern template void Template_Type::m(); +extern template void Template_Type::s(); +extern template int Template_Type::x; +extern template int Template_Type::y; + +// But explicit specialisations are not (though note [temp.expl.spec] p13) +template <> int x_tpl; // { dg-error "inline" } +template <> int y_tpl = 123; // { dg-error "inline" } +template <> void f_tpl() {} // { dg-error "inline" } + +template <> void Template_Body::m() {} // { dg-error "inline" } +template <> void Template_Body::s() {} // { dg-error "inline" } +template <> int Template_Body::x; // { dg-bogus "inline" "not a definition" } +template <> int Template_Body::y = 123; // { dg-error "inline" } + +template <> void Template_Type::m() {} // { dg-error "inline" } +template <> void Template_Type::s() {} // { dg-error "inline" } +template <> int Template_Type::x; // { dg-bogus "inline" "not a definition" } +template <> int Template_Type::y = 123; // { dg-error "inline" } diff --git a/gcc/testsuite/g++.dg/modules/macro-4_c.H b/gcc/testsuite/g++.dg/modules/macro-4_c.H index ec2bed91ccd..5692e8e41d2 100644 --- a/gcc/testsuite/g++.dg/modules/macro-4_c.H +++ b/gcc/testsuite/g++.dg/modules/macro-4_c.H @@ -6,7 +6,7 @@ #undef FIVE // no effect import "macro-4_a.H"; -int a; +inline int a; #undef THREE #undef FOUR #define FOUR 4c diff --git a/gcc/testsuite/g++.dg/modules/pr106761.h b/gcc/testsuite/g++.dg/modules/pr106761.h index 9f22a22a45d..5c13fc0f118 100644 --- a/gcc/testsuite/g++.dg/modules/pr106761.h +++ b/gcc/testsuite/g++.dg/modules/pr106761.h @@ -19,4 +19,4 @@ struct tuple { = typename _TupleConstraints::template __constructible; }; -tuple t; +inline tuple t; diff --git a/gcc/testsuite/g++.dg/modules/pr98843_b.H b/gcc/testsuite/g++.dg/modules/pr98843_b.H index d6734bd382d..af504a840c7 100644 --- a/gcc/testsuite/g++.dg/modules/pr98843_b.H +++ b/gcc/testsuite/g++.dg/modules/pr98843_b.H @@ -6,7 +6,7 @@ template int Fn () return I; } -template<> int Fn<1> () +template<> inline int Fn<1> () { return 0; } diff --git a/gcc/testsuite/g++.dg/modules/pr99468.H b/gcc/testsuite/g++.dg/modules/pr99468.H index d7da3a83e1c..df63c613b2c 100644 --- a/gcc/testsuite/g++.dg/modules/pr99468.H +++ b/gcc/testsuite/g++.dg/modules/pr99468.H @@ -3,4 +3,4 @@ module M; // { dg-error "module-declaration not permitted" } -int i; +inline int i; diff --git a/gcc/testsuite/g++.dg/modules/pragma-1_a.H b/gcc/testsuite/g++.dg/modules/pragma-1_a.H index 6eb0a5900a7..a69be2fd05e 100644 --- a/gcc/testsuite/g++.dg/modules/pragma-1_a.H +++ b/gcc/testsuite/g++.dg/modules/pragma-1_a.H @@ -1,4 +1,4 @@ // { dg-additional-options -fmodule-header } // { dg-module-cmi {} } -int i; +inline int i; diff --git a/gcc/testsuite/g++.dg/modules/tpl-ary-1.h b/gcc/testsuite/g++.dg/modules/tpl-ary-1.h index 2f745afba36..2f9a8106412 100644 --- a/gcc/testsuite/g++.dg/modules/tpl-ary-1.h +++ b/gcc/testsuite/g++.dg/modules/tpl-ary-1.h @@ -1,5 +1,5 @@ -int ary[4]; +inline int ary[4]; extern int unb[]; typedef int z[0]; From patchwork Wed Sep 25 00:54:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 1989106 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=ZkX2zy7v; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XCyvM067pz1xsM for ; Wed, 25 Sep 2024 10:55:26 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 640CB3858D26 for ; Wed, 25 Sep 2024 00:55:24 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by sourceware.org (Postfix) with ESMTPS id D22883858D26 for ; Wed, 25 Sep 2024 00:55:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D22883858D26 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D22883858D26 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::52b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727225704; cv=none; b=fNTtAc3Q0M40gCQXrnxKMbsTXbcGRt2W+Cn43aMxRJw3IZUcGw6rfxARG/PIJGEAjjG1JwQk7ZtFvnPnC0I1di+bIbbVX3E311V/NHmvKIvRyIT0hr/1Z+uo/5+eCrU1AN6Tq4NWHssJ5RH3FSMtEyG5BHBpqI8UKVElF8oIjR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1727225704; c=relaxed/simple; bh=xhK2/g/jgKHPfikSsFo0qYuUOpkPyjZ98VcHkwwlkL0=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=ebTGTcPWw2prsQ3evWliyluw8iKHOo8d42zvmjg6o3CXoK9YDGatQOOlhfTCqlcUh07BV5M78oVbgcb/M6nY29NlEeMRfnU2ZwrVlSls9aO9wp0kfKZ44st44roQ9RhbodO0USWwPp9G339p8R3O5tiJL8tUhUE9CnZfVprleLI= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x52b.google.com with SMTP id 41be03b00d2f7-7e6bac92bf6so138150a12.3 for ; Tue, 24 Sep 2024 17:55:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727225701; x=1727830501; darn=gcc.gnu.org; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:from:to:cc:subject:date:message-id:reply-to; bh=KVsuJ67CcOWRrtYC0g5KKkcC6Zs2Vq3JzfTTlseRARM=; b=ZkX2zy7vXKuLD58R17p5P7LDTNBr17ImtUJuoZKPB0BW5Ypn39h/aWiO5AHAoGeDvX Bs3wsVP+aHnU7dTL7QBrZFbCsIF4+ZLsFSAl7jGCkYJtDcAg76R25+zRT2TQjzTSL2JS HK7NR9GcxpkA553qYX/Lnv5psnftvfs3W8bjkFBo6BzC29wZhAfr97YH9voyqF2prShI fNFymvbT8wG1K36fp2QG/bLumY7gtDDmC61eM4XPrbOOpV/ViEan+tXM/tBQ4H+BrXnc F+w9U0csGc9uNpbUB8bJVN8KsjVsLT7AVNhIgeYFMYIMLd/G7rI+ptSFv1Y76AC8F+Zf cong== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727225701; x=1727830501; h=in-reply-to:content-disposition:mime-version:references:subject:cc :to:from:date:message-id:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=KVsuJ67CcOWRrtYC0g5KKkcC6Zs2Vq3JzfTTlseRARM=; b=uSr+yiLz06qWFIsD7Slo9jYTUHi5peQwiyEikE5aR7qDwtgYQt9WDTNv4aC0HJNLMr carzDoky2lEjRlKOcxMpoFSHceCsSRNpz59PT5AglFXVsGBIlEqno1eQCu4WgG8cjDQK gRmNR4KW4lgO4vYA7lSH9GTBze+g/el8h3nD5bRygI1SRzeen1lx7LmLVyk9DsIEjCRK NL+8w0EQs3FjKanPhkHkcU/LG3rbBA13lgqJ0wrniuXlAZHqf3wn3jra6+9bQRwr6BUZ Dqjvo8hYal6Xa2ubOhWBVl4lLjUgMAFldbGyn0Mc1l+Pqa9zIZUUKMYFJ0E2T7MAi8WO 372A== X-Gm-Message-State: AOJu0YwT8nHgGfsS0/ldBhQx+vjnS4UqOLBoMN0PH1F2okLjbwwMSTSu 3A9qzVIBSg9+8QlsulQGgSPeiLLLllckPfF/DgFKpvZoJQm8VvnzJVIp8Q== X-Google-Smtp-Source: AGHT+IEXN3SAgDqrITQ707+I1Awzf4ScUe82lpVsKvZpAzTSKkFakgkvRzXQoqNRTDRRlkmQQDr/kA== X-Received: by 2002:a05:6a00:1254:b0:704:173c:5111 with SMTP id d2e1a72fcca58-71b0ac41274mr662625b3a.3.1727225700548; Tue, 24 Sep 2024 17:55:00 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc85bbbasm1768688b3a.95.2024.09.24.17.54.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 17:55:00 -0700 (PDT) Message-ID: <66f35f64.050a0220.1a363a.7c51@mx.google.com> X-Google-Original-Message-ID: Date: Wed, 25 Sep 2024 10:54:56 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Nathan Sidwell Subject: [PATCH 11/10] c++/modules: Treat weakrefs as not TU-local [PR115126] References: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <66f1fce5.170a0220.150b6f.03f5@mx.google.com> X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This follows up on some more test failures reported by Linaro on aarch64. The testcase also depends on the libgcc/libstdc++ patch here: https://gcc.gnu.org/pipermail/gcc-patches/2024-September/663749.html To avoid an intermediary state where aarch64 regtests fail I could include the module.cc changes in patch 6 of this series. Let me know if you'd like me to send through a full updated v2 patch series instead of having all these 'extra' patches fixing issues on other platforms... Bootstrapped and regtested on x86_64-pc-linux and aarch64-unknown-linux-gnu, OK for trunk? -- >8 -- On some targets the gthreads support code uses weakref aliases on entities marked 'static'. By the C++ standard these have internal linkage, but we really shouldn't consider these as TU-local. This provides enough of the puzzle to pass the testcase in the PR on at least x86_64-linux and aarch64-linux; we'll see what happens on other targets. PR c++/115126 gcc/cp/ChangeLog: * module.cc (depset::hash::is_tu_local_entity): Don't treat weak entities as TU-local. gcc/testsuite/ChangeLog: * g++.dg/modules/xtreme-header-8.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/module.cc | 5 +++++ gcc/testsuite/g++.dg/modules/xtreme-header-8.C | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 gcc/testsuite/g++.dg/modules/xtreme-header-8.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index d54f1c88366..3e9b63c1e56 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -13135,6 +13135,11 @@ depset::hash::is_tu_local_entity (tree decl, bool explain/*=false*/) linkage_kind kind = decl_linkage (decl); if (kind == lk_internal) { + /* But don't consider weak entities as TU-local. */ + tree inner = STRIP_TEMPLATE (decl); + if (VAR_OR_FUNCTION_DECL_P (inner) && DECL_WEAK (inner)) + return false; + if (explain) inform (loc, "%qD declared with internal linkage", decl); return true; diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-8.C b/gcc/testsuite/g++.dg/modules/xtreme-header-8.C new file mode 100644 index 00000000000..9da4e01cc68 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/xtreme-header-8.C @@ -0,0 +1,8 @@ +// PR c++/115126 +// { dg-additional-options "-fmodules-ts -Wignored-exposures" } +// { dg-module-cmi xstd } + +export module xstd; +extern "C++" { + #include "xtreme-header.h" +}