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; }