From patchwork Wed Dec 9 13:26:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1413404 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=R3KaLL3r; dkim-atps=neutral Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CrdBB6rWjz9sWK for ; Thu, 10 Dec 2020 00:26:57 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E9C343857C6D; Wed, 9 Dec 2020 13:26:48 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x82e.google.com (mail-qt1-x82e.google.com [IPv6:2607:f8b0:4864:20::82e]) by sourceware.org (Postfix) with ESMTPS id 469D53858C27 for ; Wed, 9 Dec 2020 13:26:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 469D53858C27 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qt1-x82e.google.com with SMTP id j26so721033qtq.8 for ; Wed, 09 Dec 2020 05:26:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=/guFlRAT/W+V9+RaxHXq+PNwk27q/8p+3fIekETA4Bs=; b=R3KaLL3rjeaKj0G3dq3t4v7XLDoMffwDYw4Fi07Tsncr66+BTcwyMPd+zxqbDbGB3o idzi8IFcAK8eQnYcvUek685k+PGwRpFFFSaRDPqzYhyg9h8MwaL4PyRi9E1YCGyMX9Xx ecZtA4eQAFNhGtvgU3zjebrxcF0kYG7BC1vq92eZEUVOBVZZM/6289xQ5owhTYt583K1 UqSbzgllKLGMgpwnCTRL4hnCTJJ5KcYO6Ov5oPzA2vUnkUx3BXw1To4kzFMKRvVn+WFr OIDNOD9qS3QBLX+LHQiAhZ/AhycpVuALpS+Y1bG7hVY6Is60Ulgn/+esGaK5QxYQFxSr iXxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=/guFlRAT/W+V9+RaxHXq+PNwk27q/8p+3fIekETA4Bs=; b=iu5N8LzETW8t50N+MlU54yb0qLkH1BinrGd4SfY6kTwgLVtG68P997R4AAPBKEFO31 Q2SVUqOKQ4UADETxTVsmQZmp/+tHsNZzl+mEd3VmFiks2TNKo0JEoyyu0yHmwynAADAP DyQVAPDEJdVECFhNkbBO+BqNMFihvNprJg7VDUgk5gIHU5vGj3OpslzVfXRUtc36hNFS glht2u74rEEi6KrpyrMv6+DUJ/5sl/i80PSUBgYrZ+M+ILj+4Dam7gFfRlHFa0s9v3rf gfGinQLX/i7raO6AkvkRhJVwBlKm+SLGtFuwpfdErhOnEds4UZaJx/prBbvZi0bXVmm0 690w== X-Gm-Message-State: AOAM532drjC8+RuQJ098GVmCGzM/pjGKplS0AcYqSrQO+1RzZRDUZt/z Igg0XPi+pnow7s6dD0A4vzM= X-Google-Smtp-Source: ABdhPJyWK7Uz1IgRhnNBOuyDCytGNuMf0qMLv06ppCIUsjOl06cUMtE2Raeldse9HhzSY/KVctM7DA== X-Received: by 2002:a05:622a:d:: with SMTP id x13mr3152578qtw.374.1607520404284; Wed, 09 Dec 2020 05:26:44 -0800 (PST) Received: from ?IPv6:2620:10d:c0a8:1102:f56f:caec:7790:ed9f? ([2620:10d:c091:480::1:54f]) by smtp.googlemail.com with ESMTPSA id u26sm962361qke.57.2020.12.09.05.26.42 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 09 Dec 2020 05:26:43 -0800 (PST) To: GCC Patches From: Nathan Sidwell Subject: c++: Decl module-specific semantic processing Message-ID: <5ce5afef-700e-f0b6-d160-1bc71a1fd957@acm.org> Date: Wed, 9 Dec 2020 08:26:41 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This adds the module-specific logic to the various declaration processing routines in decl.c and semantic.c. I also adjust the rtti type creation, as those are all in the global module, so we need to temporarily clear the module_kind, when they are being created. Finally, I added init and fini module processing with the initialier giving a fatal error if you try and turn it on (so don't do that yet). gcc/cp/ * decl.c (duplicate_decls): Add module-specific redeclaration logic. (cxx_init_decl_processing): Export the global namespace, maybe initialize modules. (start_decl): Reject local-extern in a module, adjust linkage of template var. (xref_tag_1): Add module-specific redeclaration logic. (start_enum): Likewise. (finish_enum_value_list): Export unscoped members of an exported enum. (grokmethod): Implement p1779 linkage of in-class defined functions. * decl2.c (no_linkage_error): Imports are ok. (c_parse_final_cleanups): Call fini_modules. * lex.c (cxx_dup_lang_specific): Clear some module flags in the copy. * module.cc (module_kind): Define. (module_may_redeclare, set_defining_module): Stubs. (init_modules): Error on modules. (fini_modules): Stub. * rtti.c (push_abi_namespace): Save and reset module_kind. (pop_abi_namespace): Restore module kind. (build_dynamic_cast_1, tinfo_base_init): Adjust. * semantics.c (begin_class_definition): Add module-specific logic. (expand_or_defer_fn_1): Keep bodies of more fns when modules_p. pushing to trunk diff --git i/gcc/cp/decl.c w/gcc/cp/decl.c index bb5bb2f1a18..ae93fe1d7f0 100644 --- i/gcc/cp/decl.c +++ w/gcc/cp/decl.c @@ -2008,6 +2008,39 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (!validate_constexpr_redeclaration (olddecl, newdecl)) return error_mark_node; + if (modules_p () + && TREE_CODE (CP_DECL_CONTEXT (olddecl)) == NAMESPACE_DECL + && TREE_CODE (olddecl) != NAMESPACE_DECL + && !hiding) + { + if (DECL_ARTIFICIAL (olddecl)) + { + gcc_checking_assert (!(DECL_LANG_SPECIFIC (olddecl) + && DECL_MODULE_IMPORT_P (olddecl))); + if (!(global_purview_p () || not_module_p ())) + error ("declaration %qD conflicts with builtin", newdecl); + else + DECL_MODULE_EXPORT_P (olddecl) = DECL_MODULE_EXPORT_P (newdecl); + } + else + { + if (!module_may_redeclare (olddecl)) + { + error ("declaration %qD conflicts with import", newdecl); + inform (olddecl_loc, "import declared %q#D here", olddecl); + + return error_mark_node; + } + + if (DECL_MODULE_EXPORT_P (newdecl) + && !DECL_MODULE_EXPORT_P (olddecl)) + { + error ("conflicting exporting declaration %qD", newdecl); + inform (olddecl_loc, "previous declaration %q#D here", olddecl); + } + } + } + /* We have committed to returning OLDDECL at this point. */ /* If new decl is `static' and an `extern' was seen previously, @@ -2218,6 +2251,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } } + DECL_MODULE_IMPORT_P (olddecl) + = DECL_MODULE_IMPORT_P (old_result) + = DECL_MODULE_IMPORT_P (newdecl); + return olddecl; } @@ -2836,6 +2873,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) memcpy ((char *) olddecl + sizeof (struct tree_common), (char *) newdecl + sizeof (struct tree_common), sizeof (struct tree_decl_common) - sizeof (struct tree_common)); + + if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl)) + { + /* Repropagate the module information to the template. */ + tree tmpl = DECL_TI_TEMPLATE (olddecl); + + if (DECL_TEMPLATE_RESULT (tmpl) == olddecl) + { + DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl); + gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl)); + DECL_MODULE_IMPORT_P (tmpl) = false; + } + } + switch (TREE_CODE (newdecl)) { case LABEL_DECL: @@ -4330,7 +4381,8 @@ cxx_init_decl_processing (void) gcc_assert (global_namespace == NULL_TREE); global_namespace = build_lang_decl (NAMESPACE_DECL, global_identifier, void_type_node); - TREE_PUBLIC (global_namespace) = 1; + TREE_PUBLIC (global_namespace) = true; + DECL_MODULE_EXPORT_P (global_namespace) = true; DECL_CONTEXT (global_namespace) = build_translation_unit_decl (get_identifier (main_input_filename)); /* Remember whether we want the empty class passing ABI change warning @@ -4629,6 +4681,9 @@ cxx_init_decl_processing (void) if (! supports_one_only ()) flag_weak = 0; + if (modules_p ()) + init_modules (parse_in); + make_fname_decl = cp_make_fname_decl; start_fname_decls (); @@ -5453,8 +5508,14 @@ start_decl (const cp_declarator *declarator, if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) && current_function_decl) - /* A function-scope decl of some namespace-scope decl. */ - DECL_LOCAL_DECL_P (decl) = true; + { + /* A function-scope decl of some namespace-scope decl. */ + DECL_LOCAL_DECL_P (decl) = true; + if (named_module_purview_p ()) + error_at (declarator->id_loc, + "block-scope extern declaration %q#D not permitted" + " in module purview", decl); + } /* Enter this declaration into the symbol table. Don't push the plain VAR_DECL for a variable template. */ @@ -5470,7 +5531,9 @@ start_decl (const cp_declarator *declarator, if (VAR_P (decl) && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public - && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl)) + && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl) + /* But not templated variables. */ + && !(DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))) { /* This is a const variable with implicit 'static'. Set DECL_THIS_STATIC so we can tell it from variables that are @@ -15143,6 +15206,41 @@ xref_tag_1 (enum tag_types tag_code, tree name, inform (location_of (t), "previous declaration %qD", t); return error_mark_node; } + + if (modules_p () + && how == TAG_how::CURRENT_ONLY) + { + tree decl = TYPE_NAME (t); + if (!module_may_redeclare (decl)) + { + error ("cannot declare %qD in a different module", decl); + inform (DECL_SOURCE_LOCATION (decl), "declared here"); + return error_mark_node; + } + + tree maybe_tmpl = decl; + if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t)) + maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t); + + if (DECL_LANG_SPECIFIC (decl) + && DECL_MODULE_IMPORT_P (decl) + && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL) + { + /* Push it into this TU's symbol slot. */ + gcc_checking_assert (current_namespace == CP_DECL_CONTEXT (decl)); + if (maybe_tmpl != decl) + /* We're in the template parm binding level. + Pushtag has logic to slide under that, but we're + not pushing a *new* type. */ + push_nested_namespace (CP_DECL_CONTEXT (decl)); + + pushdecl (maybe_tmpl); + if (maybe_tmpl != decl) + pop_nested_namespace (CP_DECL_CONTEXT (decl)); + } + + set_instantiating_module (maybe_tmpl); + } } return t; @@ -15487,6 +15585,19 @@ start_enum (tree name, tree enumtype, tree underlying_type, "previous definition here"); underlying_type = NULL_TREE; } + + if (modules_p ()) + { + if (!module_may_redeclare (TYPE_NAME (enumtype))) + { + error ("cannot define %qD in different module", + TYPE_NAME (enumtype)); + inform (DECL_SOURCE_LOCATION (TYPE_NAME (enumtype)), + "declared here"); + enumtype = error_mark_node; + } + set_instantiating_module (TYPE_NAME (enumtype)); + } } if (!enumtype || TREE_CODE (enumtype) != ENUMERAL_TYPE @@ -15747,6 +15858,11 @@ finish_enum_value_list (tree enumtype) else underlying_type = ENUM_UNDERLYING_TYPE (enumtype); + /* If the enum is exported, mark the consts too. */ + bool export_p = (UNSCOPED_ENUM_P (enumtype) + && DECL_MODULE_EXPORT_P (TYPE_STUB_DECL (enumtype)) + && at_namespace_scope_p ()); + /* Convert each of the enumerators to the type of the underlying type of the enumeration. */ for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values)) @@ -15769,6 +15885,8 @@ finish_enum_value_list (tree enumtype) TREE_TYPE (value) = enumtype; } DECL_INITIAL (decl) = value; + if (export_p) + DECL_MODULE_EXPORT_P (decl) = true; } /* Fix up all variant types of this enum type. */ @@ -17366,10 +17484,25 @@ grokmethod (cp_decl_specifier_seq *declspecs, check_template_shadow (fndecl); - if (TREE_PUBLIC (fndecl)) - DECL_COMDAT (fndecl) = 1; - DECL_DECLARED_INLINE_P (fndecl) = 1; - DECL_NO_INLINE_WARNING_P (fndecl) = 1; + /* p1779 ABI-Isolation makes inline not a default for in-class + definitions in named module purview. If the user explicitly + made it inline, grokdeclarator will already have done the right + things. */ + if ((!named_module_purview_p () + || flag_module_implicit_inline + /* Lambda's operator function remains inline. */ + || LAMBDA_TYPE_P (DECL_CONTEXT (fndecl))) + /* If the user explicitly asked for this to be inline, we don't + need to do more, but more importantly we want to warn if we + can't inline it. */ + && !DECL_DECLARED_INLINE_P (fndecl)) + { + if (TREE_PUBLIC (fndecl)) + DECL_COMDAT (fndecl) = 1; + DECL_DECLARED_INLINE_P (fndecl) = 1; + /* It's ok if we can't inline this. */ + DECL_NO_INLINE_WARNING_P (fndecl) = 1; + } /* We process method specializations in finish_struct_1. */ if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl)) diff --git i/gcc/cp/decl2.c w/gcc/cp/decl2.c index eec0c9255c2..c122017c2fa 100644 --- i/gcc/cp/decl2.c +++ w/gcc/cp/decl2.c @@ -4531,6 +4531,10 @@ no_linkage_error (tree decl) /* In C++11 it's ok if the decl is defined. */ return; + if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl)) + /* An imported decl is ok. */ + return; + tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false); if (t == NULL_TREE) /* The type that got us on no_linkage_decls must have gotten a name for @@ -5226,6 +5230,8 @@ c_parse_final_cleanups (void) if (priority_info_map) splay_tree_delete (priority_info_map); + fini_modules (); + /* Generate any missing aliases. */ maybe_apply_pending_pragma_weaks (); diff --git i/gcc/cp/lex.c w/gcc/cp/lex.c index 6053848535e..339ed479a9a 100644 --- i/gcc/cp/lex.c +++ w/gcc/cp/lex.c @@ -1006,6 +1006,12 @@ cxx_dup_lang_specific_decl (tree node) memcpy (ld, DECL_LANG_SPECIFIC (node), size); DECL_LANG_SPECIFIC (node) = ld; + /* Directly clear some flags that do not apply to the copy + (module_purview_p still does). */ + ld->u.base.module_entity_p = false; + ld->u.base.module_import_p = false; + ld->u.base.module_pending_p = false; + if (GATHER_STATISTICS) { tree_node_counts[(int)lang_decl] += 1; diff --git i/gcc/cp/module.cc w/gcc/cp/module.cc index 948ca2a6cab..a961e3bcc92 100644 --- i/gcc/cp/module.cc +++ w/gcc/cp/module.cc @@ -65,6 +65,9 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "langhooks.h" +/* What the current TU is. */ +unsigned module_kind; + module_state * get_module (tree, module_state *, bool) { @@ -99,11 +102,22 @@ get_originating_module (tree, bool) return 0; } +bool +module_may_redeclare (tree) +{ + return true; +} + void set_instantiating_module (tree) { } +void +set_defining_module (tree) +{ +} + void set_originating_module (tree, bool) { @@ -120,3 +134,16 @@ preprocessed_module (cpp_reader *) { } +void +init_modules (cpp_reader *) +{ + /* Do not turn on yet. */ + if (modules_p ()) + fatal_error (input_location, + "Shtopp! What are you doing? This is not ready yet."); +} + +void +fini_modules () +{ +} diff --git i/gcc/cp/rtti.c w/gcc/cp/rtti.c index d6288622246..0be9eff54ad 100644 --- i/gcc/cp/rtti.c +++ w/gcc/cp/rtti.c @@ -143,16 +143,20 @@ static bool typeinfo_in_lib_p (tree); static int doing_runtime = 0; -static void +static unsigned push_abi_namespace (void) { push_nested_namespace (abi_node); push_visibility ("default", 2); + unsigned flags = module_kind; + module_kind = 0; + return flags; } static void -pop_abi_namespace (void) +pop_abi_namespace (unsigned flags) { + module_kind = flags; pop_visibility (2); pop_nested_namespace (abi_node); } @@ -765,7 +769,7 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr, dcast_fn = dynamic_cast_node; if (!dcast_fn) { - push_abi_namespace (); + unsigned flags = push_abi_namespace (); tree tinfo_ptr = xref_tag (class_type, get_identifier ("__class_type_info")); tinfo_ptr = cp_build_qualified_type (tinfo_ptr, TYPE_QUAL_CONST); @@ -780,7 +784,7 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr, NULL_TREE)); dcast_fn = (build_library_fn_ptr (fn_name, fn_type, ECF_LEAF | ECF_PURE | ECF_NOTHROW)); - pop_abi_namespace (); + pop_abi_namespace (flags); dynamic_cast_node = dcast_fn; } result = build_cxx_call (dcast_fn, 4, elems, complain); @@ -954,11 +958,11 @@ tinfo_base_init (tinfo_s *ti, tree target) vtable_ptr = ti->vtable; if (!vtable_ptr) { - push_abi_namespace (); + int flags = push_abi_namespace (); tree real_type = xref_tag (class_type, ti->name); tree real_decl = TYPE_NAME (real_type); DECL_SOURCE_LOCATION (real_decl) = BUILTINS_LOCATION; - pop_abi_namespace (); + pop_abi_namespace (flags); if (!COMPLETE_TYPE_P (real_type)) { diff --git i/gcc/cp/semantics.c w/gcc/cp/semantics.c index d33ef426348..92e32c8e0ad 100644 --- i/gcc/cp/semantics.c +++ w/gcc/cp/semantics.c @@ -3220,6 +3220,19 @@ begin_class_definition (tree t) t = make_class_type (TREE_CODE (t)); pushtag (TYPE_IDENTIFIER (t), t); } + + if (modules_p ()) + { + if (!module_may_redeclare (TYPE_NAME (t))) + { + error ("cannot declare %qD in a different module", TYPE_NAME (t)); + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)), "declared here"); + return error_mark_node; + } + set_instantiating_module (TYPE_NAME (t)); + set_defining_module (TYPE_NAME (t)); + } + maybe_process_partial_specialization (t); pushclass (t); TYPE_BEING_DEFINED (t) = 1; @@ -4506,7 +4519,8 @@ expand_or_defer_fn_1 (tree fn) it out, even though we haven't. */ TREE_ASM_WRITTEN (fn) = 1; /* If this is a constexpr function, keep DECL_SAVED_TREE. */ - if (!DECL_DECLARED_CONSTEXPR_P (fn)) + if (!DECL_DECLARED_CONSTEXPR_P (fn) + && !(modules_p () && DECL_DECLARED_INLINE_P (fn))) DECL_SAVED_TREE (fn) = NULL_TREE; return false; }