From patchwork Tue Nov 3 21:16:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1393433 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=WtnLTBXZ; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CQjKJ5J53z9sVk for ; Wed, 4 Nov 2020 08:17:08 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5C9FB3987506; Tue, 3 Nov 2020 21:17:06 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qv1-xf30.google.com (mail-qv1-xf30.google.com [IPv6:2607:f8b0:4864:20::f30]) by sourceware.org (Postfix) with ESMTPS id 36C8C39874F5 for ; Tue, 3 Nov 2020 21:17:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 36C8C39874F5 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-qv1-xf30.google.com with SMTP id ed14so5105981qvb.4 for ; Tue, 03 Nov 2020 13:17:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:subject:to:references:message-id:date:user-agent :mime-version:in-reply-to:content-language; bh=+6ryLV8U3lC3E/Ad53uJB89ZOzwmPVm/GDaxFsVvpOA=; b=WtnLTBXZMLwpF+K5l80ikQwD35zEjDsHrWK2EjjTVvg2v3IGbwL7mBc0I8dzkoJfU8 Cw0WwT/VA0jC+DyaBVnNZk96VFj7zYjM+xIAJZu7i9U007LwyjKnzSJraGVHE7Uscg15 b2LumQwAbA522sk1Cs6BJfPc3RVKbeEHAhPbXgX3l5zP4mMJIU7doqqm+cTTeb9X5/i7 QJxipeuTjmPYpCVnFpPD7VguKcFb3EW5e/dxEvxF/4sUP4WX7zzW5wzQ5D5LA3BXckcN x7u51sHcc6niAbO8rRxNSDCZoxzIuTZQFqX6MzitcNjyW0WNJUCyv8wFNnrFLINL7e/U q/cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:subject:to:references:message-id :date:user-agent:mime-version:in-reply-to:content-language; bh=+6ryLV8U3lC3E/Ad53uJB89ZOzwmPVm/GDaxFsVvpOA=; b=ljVz2FbWlTkA3UKiGnifpqQpEFhGUvZn30IsgxVEEr3+32p2gqBjTt5b3hhY8DubkO dQVx16J9Aad3dz+54nl5clSwqpIyuz+bwbp16GeSsYmS8mmZTZPlW+HATtA45/5MD6hn Tw7gbokN9nY20ohowN0/6uOr82Fw7Z5MEv89OE5erJ1Er0i1yIxnVN7oiwrCFXQWnJxI 8yHzJZ8/6IWBgdJt5/f0qpU99vhZV9PMtAWdiqKDq2MjjsoidkN/7SxKlPsPZq3kmRpb U+etKscHpBC1TiqqWb0LhfS+KiDGmns5BLCQLTAcAV3AsgUDhMq2omIOctcjo+/SK9zq GvUQ== X-Gm-Message-State: AOAM531JGcP4Epc29mQt2tVmBF0tqW/Bg1c6FgXonldgDGW6OMFEUxyq s5qBObWDbJtV4GB+2n9zWxV862frbWfyXQ== X-Google-Smtp-Source: ABdhPJw8bujj61JBWkyFC2gSnUZh8CtXh/+VEhZd6Zl9nwhNgl27PjsILdY3/fAxqy0KRx/ZIK3gSA== X-Received: by 2002:ad4:4142:: with SMTP id z2mr29632563qvp.20.1604438219493; Tue, 03 Nov 2020 13:16:59 -0800 (PST) Received: from ?IPv6:2620:10d:c0a8:1102:e5ef:7eb4:1609:98bb? ([2620:10d:c091:480::1:bc2d]) by smtp.googlemail.com with ESMTPSA id 19sm10938464qkj.69.2020.11.03.13.16.57 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 03 Nov 2020 13:16:58 -0800 (PST) From: Nathan Sidwell Subject: [22/32] miscelaneous c++ bits To: GCC Patches , Jason Merrill , Richard Biener References: <7fc9e868-3db9-4972-ed67-6ff249f549c3@acm.org> <0bdf00a8-d8ad-9e97-134d-6668c0e8c86b@acm.org> <85996243-86cf-88b4-5b3b-451eaf3a0df6@acm.org> <4d14b230-3263-9a13-3159-c4853f282761@acm.org> <688bd28f-5998-0def-8c40-03b817832d63@acm.org> <89819c10-e86d-9b01-5673-5223a525a135@acm.org> <35879e15-d74a-c664-4d44-15f4b3783d77@acm.org> <9ae23c4c-67a5-a267-c939-5a96e9488612@acm.org> <6666545b-0583-4812-4745-d51994465818@acm.org> <1ab99df5-3997-0895-c979-f8529f476df7@acm.org> <97e9477b-7173-b7f9-a884-616b972c57ba@acm.org> <01f091a5-cd8b-60b6-9552-2318ecd07025@acm.org> <5c533ebe-440d-188e-5bdb-38c14898852c@acm.org> Message-ID: <10c2ff88-0c67-8557-6c06-bf822f675c59@acm.org> Date: Tue, 3 Nov 2020 16:16:57 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: <5c533ebe-440d-188e-5bdb-38c14898852c@acm.org> Content-Language: en-US X-Spam-Status: No, score=-11.3 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 is probably the messiest diff. It's the remaining diff of cp-tree.h. 1) a new tree type MODULE_VECTOR. This is a sparse array used for name lookup. A namespace symbol table entry may contain one of these, which holds the bindings for each loaded module. If a module doesn't bind that name, there'll be no slot for it. The current TU always uses slot 0. The Global Module uses slot 1, and in a named-module partitions share slot 2. Slots 1 & 2 are used for duplicate declaration matching. I steal more flags from lang-decl-base. Firstly, the selector is reduced from 16 to 3 bits. We add a bunch of module-related flags module_purview_p -- the declaration is owned by a module module_import_p -- the declaration is from an import module_entity_p -- the declaration is in the imported entity hash & array module_pending_specializations_p - in a template we know there are specializations we've not loaded module_pending_members_p - in a class we know there are members to be loaded attached_decls_p -- this decl is in the attached-decls hash, and therefore has attached decls (to do with mangling lambdas initializing namespace-scope maybe-template variables) It sprinkles set_originating_module and set_instantiating_module around a few places. The originating module of a decl is the module that declared the decl. The instantiating module is the module that caused code to be emitted for it. Often these two modules are the same, but for templates they can of course be different. diff --git c/gcc/cp/cp-tree.def w/gcc/cp/cp-tree.def index a188576013b..ba02cdc2748 100644 --- c/gcc/cp/cp-tree.def +++ w/gcc/cp/cp-tree.def @@ -233,6 +233,9 @@ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", tcc_expression, 2) /* One of a set of overloaded functions. */ DEFTREECODE (OVERLOAD, "overload", tcc_exceptional, 0) +/* A vector of module overloads. */ +DEFTREECODE (MODULE_VECTOR, "module_vector", tcc_exceptional, 0) + /* A pseudo-destructor, of the form "OBJECT.~DESTRUCTOR" or "OBJECT.SCOPE::~DESTRUCTOR. The first operand is the OBJECT. The second operand (if non-NULL) is the SCOPE. The third operand is diff --git c/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h index fdb8ee57f0b..e8e4d0af2d8 100644 --- c/gcc/cp/cp-tree.h +++ w/gcc/cp/cp-tree.h @@ -475,20 +484,22 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE) CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR) + DECL_MODULE_EXPORT_P (in _DECL) OVL_NESTED_P (in OVERLOAD) LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR) Reserved for DECL_MODULE_EXPORT (in DECL_) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). - DECL_TINFO_P (in VAR_DECL) + DECL_TINFO_P (in VAR_DECL, TYPE_DECL) FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) OVL_LOOKUP_P (in OVERLOAD) - LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, NAMESPACE_DECL) + LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, NAMESPACE_DECL) 5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR) + OVL_EXPORT_P (in OVL_USING_P OVERLOAD) 6: TYPE_MARKED_P (in _TYPE) DECL_NONTRIVIALLY_INITIALIZED_P (in VAR_DECL) RANGE_FOR_IVDEP (in RANGE_FOR_STMT) @@ -530,6 +541,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; DECL_ANON_UNION_VAR_P (in a VAR_DECL) DECL_SELF_REFERENCE_P (in a TYPE_DECL) DECL_INVALID_OVERRIDER_P (in a FUNCTION_DECL) + DECL_UNINSTANIATED_TEMPLATE_FRIEND_P (in TEMPLATE_DECL) 5: DECL_INTERFACE_KNOWN. 6: DECL_THIS_STATIC (in VAR_DECL, FUNCTION_DECL or PARM_DECL) DECL_FIELD_IS_BASE (in FIELD_DECL) @@ -744,7 +756,8 @@ typedef struct ptrmem_cst * ptrmem_cst_t; /* Lookup walker marking. */ #define LOOKUP_SEEN_P(NODE) TREE_VISITED(NODE) #define LOOKUP_FOUND_P(NODE) \ - TREE_LANG_FLAG_4 (TREE_CHECK3(NODE,RECORD_TYPE,UNION_TYPE,NAMESPACE_DECL)) + TREE_LANG_FLAG_4 (TREE_CHECK4(NODE,RECORD_TYPE,UNION_TYPE,ENUMERAL_TYPE, \ + NAMESPACE_DECL)) /* These two accessors should only be used by OVL manipulators. Other users should use iterators and convenience functions. */ @@ -763,6 +776,8 @@ typedef struct ptrmem_cst * ptrmem_cst_t; #define OVL_NESTED_P(NODE) TREE_LANG_FLAG_3 (OVERLOAD_CHECK (NODE)) /* If set, this overload was constructed during lookup. */ #define OVL_LOOKUP_P(NODE) TREE_LANG_FLAG_4 (OVERLOAD_CHECK (NODE)) +/* If set, this OVL_USING_P overload is exported. */ +#define OVL_EXPORT_P(NODE) TREE_LANG_FLAG_5 (OVERLOAD_CHECK (NODE)) /* The first decl of an overload. */ #define OVL_FIRST(NODE) ovl_first (NODE) @@ -822,6 +837,11 @@ class ovl_iterator { return fn; } + tree get_using () const + { + gcc_checking_assert (using_p ()); + return ovl; + } public: /* Whether this overload was introduced by a using decl. */ @@ -830,10 +850,21 @@ class ovl_iterator { return (TREE_CODE (ovl) == USING_DECL || (TREE_CODE (ovl) == OVERLOAD && OVL_USING_P (ovl))); } + /* Whether this using is being exported. */ + bool exporting_p () const + { + return OVL_EXPORT_P (get_using ()); + } + bool hidden_p () const { return TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl); } + void set_dedup () + { + if (TREE_CODE (ovl) == OVERLOAD) + OVL_DEDUP_P (ovl) = true; + } public: tree remove_node (tree head) @@ -924,6 +955,84 @@ struct named_decl_hash : ggc_remove { static void mark_deleted (value_type) { gcc_unreachable (); } }; +/* Bindings for modules are held in a sparse array. There is always a + current TU slot, others are allocated as needed. By construction + of the importing mechanism we only ever need to append to the + array. Rather than have straight index/slot tuples, we bunch them + up for greater packing. + + The cluster representation packs well on a 64-bit system. */ + +#define MODULE_VECTOR_SLOTS_PER_CLUSTER 2 +struct mc_index { + unsigned short base; + unsigned short span; +}; + +struct GTY(()) module_cluster +{ + mc_index GTY((skip)) indices[MODULE_VECTOR_SLOTS_PER_CLUSTER]; + mc_slot slots[MODULE_VECTOR_SLOTS_PER_CLUSTER]; +}; + +/* These two fields overlay lang flags. So don't use those. */ +#define MODULE_VECTOR_ALLOC_CLUSTERS(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.u.dependence_info.clique) +#define MODULE_VECTOR_NUM_CLUSTERS(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.u.dependence_info.base) +#define MODULE_VECTOR_CLUSTER_BASE(NODE) \ + (((tree_module_vec *)MODULE_VECTOR_CHECK (NODE))->vec) +#define MODULE_VECTOR_CLUSTER_LAST(NODE) \ + (&MODULE_VECTOR_CLUSTER (NODE, MODULE_VECTOR_NUM_CLUSTERS (NODE) - 1)) +#define MODULE_VECTOR_CLUSTER(NODE,IX) \ + (((tree_module_vec *)MODULE_VECTOR_CHECK (NODE))->vec[IX]) + +struct GTY(()) tree_module_vec { + struct tree_base base; + tree name; + module_cluster GTY((length ("%h.base.u.dependence_info.base"))) vec[1]; +}; + +/* The name of a module vector. */ +#define MODULE_VECTOR_NAME(NODE) \ + (((tree_module_vec *)MODULE_VECTOR_CHECK (NODE))->name) + +/* tree_module_vec does uses base.u.dependence_info.base field for + length. It does not have lang_flag etc available! */ + +/* These two flags note if a module-vector contains deduplicated + bindings (i.e. multiple declarations in different imports). */ +/* This binding contains duplicate references to a global module + entity. */ +#define MODULE_VECTOR_GLOBAL_DUPS_P(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.static_flag) +/* This binding contains duplicate references to a partioned module + entity. */ +#define MODULE_VECTOR_PARTITION_DUPS_P(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.volatile_flag) + +/* These two flags indicate the provenence of the bindings on this + particular vector slot. We can of course determine this from slot + number, but that's a relatively expensive lookup. This avoids + that when iterating. */ +/* This slot is part of the global module (a header unit). */ +#define MODULE_BINDING_GLOBAL_P(NODE) \ + (OVERLOAD_CHECK (NODE)->base.static_flag) +/* This slot is part of the current module (a partition or primary). */ +#define MODULE_BINDING_PARTITION_P(NODE) \ + (OVERLOAD_CHECK (NODE)->base.volatile_flag) + +/* There are specializations of a template keyed to this binding. */ +#define MODULE_VECTOR_PENDING_SPECIALIZATIONS_P(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.public_flag) +/* The key is in a header unit (not a named module partition or + primary). */ +#define MODULE_VECTOR_PENDING_IS_HEADER_P(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.protected_flag) +/* The key is in a named module (primary or partition). */ +#define MODULE_VECTOR_PENDING_IS_PARTITION_P(NODE) \ + (MODULE_VECTOR_CHECK (NODE)->base.private_flag) + /* Simplified unique_ptr clone to release a tree vec on exit. */ class releasing_vec @@ -1623,6 +1732,48 @@ check_constraint_info (tree t) #define CONSTRAINED_PARM_PROTOTYPE(NODE) \ DECL_INITIAL (TYPE_DECL_CHECK (NODE)) +/* Module defines. */ +// Too many _DECLS: FUNCTION,VAR,TYPE,TEMPLATE,CONCEPT or NAMESPACE +#define DECL_MODULE_CHECK(NODE) (NODE) + +/* In the purview of a module (including header unit). */ +#define DECL_MODULE_PURVIEW_P(N) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (N))->u.base.module_purview_p) + +/* True if the live version of the decl was imported. */ +#define DECL_MODULE_IMPORT_P(NODE) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_import_p) + +/* True if this decl is in the entity hash & array. This means that + some variant was imported, even if DECL_MODULE_IMPORT_P is false. */ +#define DECL_MODULE_ENTITY_P(NODE) \ + (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (NODE))->u.base.module_entity_p) + +/* True if there are unloaded specializations keyed to this template. */ +#define DECL_MODULE_PENDING_SPECIALIZATIONS_P(NODE) \ + (DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE)) \ + ->u.base.module_pending_specializations_p) + +/* True if this class has unloaded members. These should be loaded + before we do member lookups. While this may be better on the + classtype, I think we can get this behaviour for enums too. But + perhaps those need to be immediately loaded? (Particularly if + unscoped). */ +#define DECL_MODULE_PENDING_MEMBERS_P(NODE) \ + (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE)) \ + ->u.base.module_pending_members_p) + +/* Whether this is an exported DECL. Held on any decl that can appear + at namespace scope (function, var, type, template, const or + namespace). templates copy from their template_result, consts have + it for unscoped enums. */ +#define DECL_MODULE_EXPORT_P(NODE) TREE_LANG_FLAG_3 (NODE) + +/* DECL that has attached decls for ODR-relatedness. */ +#define DECL_ATTACHED_DECLS_P(NODE) \ + (DECL_LANG_SPECIFIC (NODE)->u.base.attached_decls_p) + + /* The list of local parameters introduced by this requires-expression, in the form of a chain of PARM_DECLs. */ #define REQUIRES_EXPR_PARMS(NODE) \ @@ -1644,6 +1795,7 @@ enum cp_tree_node_structure_enum { TS_CP_TPI, TS_CP_PTRMEM, TS_CP_OVERLOAD, + TS_CP_MODULE_VECTOR, TS_CP_BASELINK, TS_CP_TEMPLATE_DECL, TS_CP_DEFERRED_PARSE, @@ -1665,6 +1817,7 @@ union GTY((desc ("cp_tree_node_structure (&%h)"), struct template_parm_index GTY ((tag ("TS_CP_TPI"))) tpi; struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem; struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload; + struct tree_module_vec GTY ((tag ("TS_CP_MODULE_VECTOR"))) module_vec; struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink; struct tree_template_decl GTY ((tag ("TS_CP_TEMPLATE_DECL"))) template_decl; struct tree_deferred_parse GTY ((tag ("TS_CP_DEFERRED_PARSE"))) deferred_parse; @@ -2645,15 +2799,15 @@ enum lang_decl_selector /* Flags shared by all forms of DECL_LANG_SPECIFIC. Some of the flags live here only to make lang_decl_min/fn smaller. Do - not make this struct larger than 32 bits; instead, make sel smaller. */ + not make this struct larger than 32 bits. */ struct GTY(()) lang_decl_base { - /* Larger than necessary for faster access. */ - ENUM_BITFIELD(lang_decl_selector) selector : 16; + ENUM_BITFIELD(lang_decl_selector) selector : 3; ENUM_BITFIELD(languages) language : 1; unsigned use_template : 2; unsigned not_really_extern : 1; /* var or fn */ unsigned initialized_in_class : 1; /* var or fn */ + unsigned threadprivate_or_deleted_p : 1; /* var or fn */ /* anticipated_p is no longer used for anticipated_decls (fn, type or template). It is used as DECL_OMP_PRIVATIZED_MEMBER in @@ -2662,11 +2816,22 @@ struct GTY(()) lang_decl_base { unsigned friend_or_tls : 1; /* var, fn, type or template */ unsigned unknown_bound_p : 1; /* var */ unsigned odr_used : 1; /* var or fn */ - unsigned spare : 1; unsigned concept_p : 1; /* applies to vars and functions */ unsigned var_declared_inline_p : 1; /* var */ unsigned dependent_init_p : 1; /* var */ - /* 2 spare bits */ + + unsigned module_purview_p : 1; /* in module purview (not GMF) */ + unsigned module_import_p : 1; /* from an import */ + unsigned module_entity_p : 1; /* is in the entitity ary & + hash. */ + /* Has specializations or members yet to load. */ + unsigned module_pending_specializations_p : 1; + unsigned module_pending_members_p : 1; + + /* Is in the decl-attached hash table, (with attached decls). */ + unsigned attached_decls_p : 1; + + /* 10 spare bits. */ }; /* True for DECL codes which have template info and access. */ @@ -3099,6 +3264,13 @@ struct GTY(()) lang_decl { (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \ ->u.base.friend_or_tls) +/* True of a TEMPLATE_DECL that is a template class friend. Such + decls are not pushed until instantiated (as they may depend on + parameters of the befriending class). DECL_CHAIN is the + befriending class. */ +#define DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P(NODE) \ + (DECL_LANG_FLAG_4 (TEMPLATE_DECL_CHECK (NODE))) + /* Nonzero if the thread-local variable was declared with __thread as opposed to thread_local. */ #define DECL_GNU_TLS_P(NODE) \ @@ -3340,7 +3512,8 @@ struct GTY(()) lang_decl { /* 1 iff VAR_DECL node NODE is a type-info decl. This flag is set for both the primary typeinfo object and the associated NTBS name. */ -#define DECL_TINFO_P(NODE) TREE_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)) +#define DECL_TINFO_P(NODE) \ + TREE_LANG_FLAG_4 (TREE_CHECK2 (NODE,VAR_DECL,TYPE_DECL)) /* 1 iff VAR_DECL node NODE is virtual table or VTT. We forward to DECL_VIRTUAL_P from the common code, as that has the semantics we @@ -6092,6 +6277,13 @@ struct GTY((chain_next ("%h.next"))) tinst_level { arguments. */ tree tldcl, targs; + /* For modules we need to know (a) the modules on the path of + instantiation and (b) the transitive imports along that path. + Note that these two bitmaps may be inherited from NEXT, if this + decl is in the same module as NEXT (or has no new information). */ + bitmap path; + bitmap visible; + private: /* Return TRUE iff the original node is a split list. */ bool split_list_p () const { return targs; } @@ -6187,6 +6379,7 @@ extern cp_parameter_declarator *no_parameters; /* Various dump ids. */ extern int class_dump_id; +extern int module_dump_id; extern int raw_dump_id; /* in call.c */ @@ -6393,6 +6586,7 @@ extern void check_abi_tags (tree); extern tree missing_abi_tags (tree); extern void fixup_type_variants (tree); extern void fixup_attribute_variants (tree); +extern void build_cdtor_clones (tree, bool, bool, bool); extern void clone_cdtor (tree, bool); extern tree copy_operator_fn (tree, tree_code code); extern void adjust_clone_args (tree); @@ -6775,6 +6977,100 @@ extern bool ctor_omit_inherited_parms (tree); extern tree locate_ctor (tree); extern tree implicitly_declare_fn (special_function_kind, tree, bool, tree, tree); +/* In module.cc */ +class module_state; /* Forward declare. */ +inline bool modules_p () { return flag_modules != 0; } + +#define MK_MODULE (1 << 0) /* This TU is a module. */ +#define MK_GLOBAL (1 << 1) /* Entities are in the global module. */ +#define MK_INTERFACE (1 << 2) /* This TU is an interface. */ +#define MK_PARTITION (1 << 3) /* This TU is a partition. */ +#define MK_EXPORTING (1 << 4) /* We are in an export region. */ +extern unsigned module_kind; + +/* MK_MODULE & MK_GLOBAL have the following combined meanings: + MODULE GLOBAL + 0 0 not a module + 0 1 GMF of named module (we've not yet seen module-decl) + 1 0 purview of named module + 1 1 header unit. */ + +inline bool module_purview_p () +{ return module_kind & MK_MODULE; } +inline bool global_purview_p () +{ return module_kind & MK_GLOBAL; } + +inline bool not_module_p () +{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == 0; } +inline bool named_module_p () +{ /* This is a named module if exactly one of MODULE and GLOBAL is + set. */ + /* The divides are constant shifts! */ + return ((module_kind / MK_MODULE) ^ (module_kind / MK_GLOBAL)) & 1; +} +inline bool header_module_p () +{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == (MK_MODULE | MK_GLOBAL); } +inline bool named_module_purview_p () +{ return (module_kind & (MK_MODULE | MK_GLOBAL)) == MK_MODULE; } +inline bool module_interface_p () +{ return module_kind & MK_INTERFACE; } +inline bool module_partition_p () +{ return module_kind & MK_PARTITION; } +inline bool module_has_cmi_p () +{ return module_kind & (MK_INTERFACE | MK_PARTITION); } + +/* We're currently exporting declarations. */ +inline bool module_exporting_p () +{ return module_kind & MK_EXPORTING; } + +extern module_state *get_module (tree name, module_state *parent = NULL, + bool partition = false); +extern bool module_may_redeclare (tree decl); + +extern int module_initializer_kind (); +extern void module_add_import_initializers (); + +/* Where the namespace-scope decl was originally declared. */ +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; + +/* Where current instance of the decl got declared/defined/instantiated. */ +extern void set_instantiating_module (tree); +extern void set_defining_module (tree); +extern void maybe_attach_decl (tree ctx, tree decl); + +extern void mangle_module (int m, bool include_partition); +extern void mangle_module_fini (); +extern void lazy_load_binding (unsigned mod, tree ns, tree id, mc_slot *mslot); +extern void lazy_load_specializations (tree tmpl); +extern void lazy_load_members (tree decl); +extern bool lazy_specializations_p (unsigned, bool, bool); +extern module_state *preprocess_module (module_state *, location_t, + bool in_purview, + bool is_import, bool export_p, + cpp_reader *reader); +extern void preprocessed_module (cpp_reader *reader); +extern void import_module (module_state *, location_t, bool export_p, + tree attr, cpp_reader *); +extern void declare_module (module_state *, location_t, bool export_p, + tree attr, cpp_reader *); + +extern void module_cpp_undef (cpp_reader *, location_t, cpp_hashnode *); +extern cpp_macro *module_cpp_deferred_macro (cpp_reader *, + location_t, cpp_hashnode *); +extern void init_modules (cpp_reader *); +extern void fini_modules (); +extern void maybe_check_all_macros (cpp_reader *); +extern void finish_module_processing (cpp_reader *); +extern char const *module_name (unsigned, bool header_ok); +extern bitmap get_import_bitmap (); +extern bitmap module_visible_instantiation_path (bitmap *); +extern void module_begin_main_file (cpp_reader *, line_maps *, + const line_map_ordinary *); +extern void module_preprocess_options (cpp_reader *); +extern bool handle_module_option (unsigned opt, const char *arg, int value); /* In optimize.c */ extern bool maybe_clone_body (tree); @@ -7351,6 +7661,7 @@ extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_chain (tree, tree); extern tree build_qualified_name (tree, tree, tree, bool); extern tree build_ref_qualified_type (tree, cp_ref_qualifier); +extern tree make_module_vec (tree, unsigned clusters); inline tree ovl_first (tree) ATTRIBUTE_PURE; extern tree ovl_make (tree fn, tree next = NULL_TREE); @@ -7690,6 +8002,9 @@ extern tree mangle_template_parm_object (tree); extern char *get_mangled_vtable_map_var_name (tree); extern bool mangle_return_type_p (tree); extern tree mangle_decomp (tree, vec &); +extern void mangle_module_substitution (int); +extern void mangle_identifier (char, tree); +extern tree mangle_module_global_init (int); /* in dump.c */ extern bool cp_dump_tree (void *, tree); @@ -7959,14 +8285,16 @@ type_unknown_p (const_tree expr) inline hashval_t named_decl_hash::hash (const value_type decl) { - tree name = OVL_NAME (decl); + tree name = (TREE_CODE (decl) == MODULE_VECTOR + ? MODULE_VECTOR_NAME (decl) : OVL_NAME (decl)); return name ? IDENTIFIER_HASH_VALUE (name) : 0; } inline bool named_decl_hash::equal (const value_type existing, compare_type candidate) { - tree name = OVL_NAME (existing); + tree name = (TREE_CODE (existing) == MODULE_VECTOR + ? MODULE_VECTOR_NAME (existing) : OVL_NAME (existing)); return candidate == name; } diff --git c/gcc/cp/decl.c w/gcc/cp/decl.c index 39f56b81275..1ae696a94ad 100644 --- c/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; } @@ -2816,6 +2859,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: @@ -4102,6 +4159,12 @@ make_unbound_class_template (tree context, tree name, tree parm_list, return tmpl; } + return make_unbound_class_template_raw (context, name, parm_list); +} + +tree +make_unbound_class_template_raw (tree context, tree name, tree parm_list) +{ /* Build the UNBOUND_CLASS_TEMPLATE. */ tree t = cxx_make_type (UNBOUND_CLASS_TEMPLATE); TYPE_CONTEXT (t) = FROB_CONTEXT (context); @@ -4283,7 +4346,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 @@ -4579,6 +4643,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 (); @@ -5390,8 +5442,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. */ @@ -9810,6 +9868,8 @@ grokfndecl (tree ctype, && !processing_template_decl) deduce_noexcept_on_destructor (decl); + set_originating_module (decl); + decl = check_explicit_specialization (orig_declarator, decl, template_count, 2 * funcdef_flag + @@ -10054,6 +10114,8 @@ grokvardecl (tree type, TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); } + set_originating_module (decl); + if (decl_spec_seq_has_spec_p (declspecs, ds_thread)) { if (DECL_EXTERNAL (decl) || TREE_STATIC (decl)) @@ -12907,6 +12969,8 @@ grokdeclarator (const cp_declarator *declarator, revert this subsequently if it determines that the clones should share a common implementation. */ DECL_ABSTRACT_P (decl) = true; + + set_originating_module (decl); } else if (current_class_type && constructor_name_p (unqualified_id, current_class_type)) @@ -13431,6 +13495,8 @@ grokdeclarator (const cp_declarator *declarator, ; /* We already issued a permerror. */ else if (decl && DECL_NAME (decl)) { + set_originating_module (decl, true); + if (initialized) /* Kludge: We need funcdef_flag to be true in do_friend for in-class defaulted functions, but that breaks grokfndecl. @@ -15070,6 +15135,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; @@ -15414,6 +15514,19 @@ start_enum (tree name, tree enumtype, tree underlying_type, "previous definition here"); underlying_type = NULL_TREE; } + + if (flag_modules) + { + 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 @@ -15674,6 +15787,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)) @@ -15696,8 +15814,10 @@ 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. */ for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t)) TYPE_VALUES (t) = TYPE_VALUES (enumtype); @@ -16866,7 +16988,7 @@ maybe_save_function_definition (tree fun) && DECL_DECLARED_CONSTEXPR_P (fun) && !cp_function_chain->invalid_constexpr && !DECL_CLONED_FUNCTION_P (fun)) - register_constexpr_fundef (fun, DECL_SAVED_TREE (fun)); + check_constexpr_fundef (fun, DECL_SAVED_TREE (fun)); } /* Attempt to add a fix-it hint to RICHLOC suggesting the insertion @@ -17307,10 +17429,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)) @@ -17581,6 +17718,7 @@ cp_tree_node_structure (union lang_tree_node * t) case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE; case IDENTIFIER_NODE: return TS_CP_IDENTIFIER; case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR; + case MODULE_VECTOR: return TS_CP_MODULE_VECTOR; case OVERLOAD: return TS_CP_OVERLOAD; case PTRMEM_CST: return TS_CP_PTRMEM; case STATIC_ASSERT: return TS_CP_STATIC_ASSERT; diff --git c/gcc/cp/decl2.c w/gcc/cp/decl2.c index 71107e03010..60bc6444d7c 100644 --- c/gcc/cp/decl2.c +++ w/gcc/cp/decl2.c @@ -4470,6 +4506,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 @@ -4904,6 +4944,9 @@ c_parse_final_cleanups (void) instantiate_pending_templates (retries); ggc_collect (); + if (header_module_p ()) + goto skip; + /* Write out virtual tables as required. Writing out the virtual table for a template class may cause the instantiation of members of that class. If we write out @@ -5102,10 +5147,13 @@ c_parse_final_cleanups (void) pending_statics->length ())) reconsider = true; + skip:; retries++; } while (reconsider); + finish_module_processing (parse_in); + lower_var_init (); generate_mangling_aliases (); @@ -5121,6 +5169,10 @@ c_parse_final_cleanups (void) #pragma interface, etc.) we decided not to emit the definition here. */ && !DECL_INITIAL (decl) + /* A defaulted fn in a header module can be synthesized on + demand later. (In non-header modules we should have + synthesized it above.) */ + && !(DECL_DEFAULTED_FN (decl) && header_module_p ()) /* Don't complain if the template was defined. */ && !(DECL_TEMPLATE_INSTANTIATION (decl) && DECL_INITIAL (DECL_TEMPLATE_RESULT @@ -5154,9 +5206,8 @@ c_parse_final_cleanups (void) splay_tree_foreach (priority_info_map, generate_ctor_and_dtor_functions_for_priority, /*data=*/&locus_at_end_of_parsing); - else if (c_dialect_objc () && objc_static_init_needed_p ()) - /* If this is obj-c++ and we need a static init, call - generate_ctor_or_dtor_function. */ + else if ((c_dialect_objc () && objc_static_init_needed_p ()) + || module_initializer_kind ()) generate_ctor_or_dtor_function (/*constructor_p=*/true, DEFAULT_INIT_PRIORITY, &locus_at_end_of_parsing); @@ -5165,6 +5216,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 c/gcc/cp/error.c w/gcc/cp/error.c index 396558be17f..ad998791bc6 100644 --- c/gcc/cp/error.c +++ w/gcc/cp/error.c @@ -179,6 +179,36 @@ cxx_initialize_diagnostics (diagnostic_context *context) pp->m_format_postprocessor = new cxx_format_postprocessor (); } +static void +dump_module_suffix (cxx_pretty_printer *pp, tree decl) +{ + if (!modules_p ()) + return; + + if (!DECL_CONTEXT (decl)) + return; + + if (TREE_CODE (decl) != CONST_DECL + || !UNSCOPED_ENUM_P (DECL_CONTEXT (decl))) + { + if (!DECL_NAMESPACE_SCOPE_P (decl)) + return; + + if (TREE_CODE (decl) == NAMESPACE_DECL + && !DECL_NAMESPACE_ALIAS (decl) + && (TREE_PUBLIC (decl) || !TREE_PUBLIC (CP_DECL_CONTEXT (decl)))) + return; + } + + if (unsigned m = get_originating_module (decl)) + if (const char *n = module_name (m, false)) + { + pp_character (pp, '@'); + pp->padding = pp_none; + pp_string (pp, n); + } +} + /* Dump a scope, if deemed necessary. */ static void @@ -770,6 +800,8 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags) else pp_cxx_tree_identifier (pp, DECL_NAME (decl)); + dump_module_suffix (pp, decl); + if (tmplate) dump_template_parms (pp, TYPE_TEMPLATE_INFO (t), !CLASSTYPE_USE_TEMPLATE (t), @@ -1074,6 +1106,9 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags) pp_string (pp, M_("")); else pp_string (pp, M_("")); + + dump_module_suffix (pp, t); + if (flags & TFF_DECL_SPECIFIERS) dump_type_suffix (pp, type, flags); } @@ -1891,6 +1926,8 @@ dump_function_name (cxx_pretty_printer *pp, tree t, int flags) else dump_decl (pp, name, flags); + dump_module_suffix (pp, t); + if (DECL_TEMPLATE_INFO (t) && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t) && (TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL diff --git c/gcc/cp/lambda.c w/gcc/cp/lambda.c index 1a1647f465e..f6746d7304b 100644 --- c/gcc/cp/lambda.c +++ w/gcc/cp/lambda.c @@ -1114,6 +1114,8 @@ maybe_add_lambda_conv_op (tree type) while (src) { tree new_node = copy_node (src); + /* We set DECL_CONTEXT of NEW_NODE to the statfn below. + Notice this is creating a recursive type! */ /* Clear TREE_ADDRESSABLE on thunk arguments. */ TREE_ADDRESSABLE (new_node) = 0; @@ -1393,6 +1395,12 @@ record_lambda_scope (tree lambda) { LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope; LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++; + if (lambda_scope) + { + tree closure = LAMBDA_EXPR_CLOSURE (lambda); + gcc_checking_assert (closure); + maybe_attach_decl (lambda_scope, TYPE_NAME (closure)); + } } /* This lambda is an instantiation of a lambda in a template default argument diff --git c/gcc/cp/mangle.c w/gcc/cp/mangle.c index 9fd30011288..6f9c93cb571 100644 --- c/gcc/cp/mangle.c +++ w/gcc/cp/mangle.c @@ -117,6 +117,9 @@ struct GTY(()) globals { /* True if the mangling will be different in C++17 mode. */ bool need_cxx17_warning; + + /* True if we mangled a module name. */ + bool mod; }; static GTY (()) globals G; @@ -832,6 +835,62 @@ write_encoding (const tree decl) } } +/* Interface to substitution and identifer mangling, used by the + module name mangler. */ + +void +mangle_module_substitution (int v) +{ + if (v < 10) + { + write_char ('_'); + write_char ('0' + v); + } + else + { + write_char ('W'); + write_unsigned_number (v - 10); + write_char ('_'); + } +} + +void +mangle_identifier (char c, tree id) +{ + if (c) + write_char (c); + write_source_name (id); +} + +/* If the outermost non-namespace context (including DECL itself) is + a module-linkage decl, mangle the module information. For module + global initializers we need to include the partition part. + + ::= W + E + :: + || _ ;; short backref + || W _ ;; long backref + || P ;; partition introducer +*/ + +static void +write_module (int m, bool include_partition) +{ + G.mod = true; + + write_char ('W'); + mangle_module (m, include_partition); + write_char ('E'); +} + +static void +maybe_write_module (tree decl) +{ + int m = get_originating_module (decl, true); + if (m >= 0) + write_module (m, false); +} + /* Lambdas can have a bit more context for mangling, specifically VAR_DECL or PARM_DECL context, which doesn't belong in DECL_CONTEXT. */ @@ -894,6 +953,9 @@ write_name (tree decl, const int ignore_local_scope) decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); } + if (modules_p ()) + maybe_write_module (decl); + context = decl_mangling_context (decl); gcc_assert (context != NULL_TREE); @@ -3806,14 +3868,13 @@ start_mangling (const tree entity) G.entity = entity; G.need_abi_warning = false; G.need_cxx17_warning = false; + G.mod = false; obstack_free (&name_obstack, name_base); mangle_obstack = &name_obstack; name_base = obstack_alloc (&name_obstack, 0); } -/* Done with mangling. If WARN is true, and the name of G.entity will - be mangled differently in a future version of the ABI, issue a - warning. */ +/* Done with mangling. Release the data. */ static void finish_mangling_internal (void) @@ -3821,6 +3882,9 @@ finish_mangling_internal (void) /* Clear all the substitutions. */ vec_safe_truncate (G.substitutions, 0); + if (G.mod) + mangle_module_fini (); + /* Null-terminate the string. */ write_char ('\0'); } @@ -3865,6 +3929,20 @@ init_mangle (void) subst_identifiers[SUBID_BASIC_IOSTREAM] = get_identifier ("basic_iostream"); } +/* Generate a mangling for MODULE's global initializer fn. */ + +tree +mangle_module_global_init (int module) +{ + start_mangling (NULL_TREE); + + write_string ("_ZGI"); + write_module (module, true); + write_char ('v'); + + return finish_mangling_get_identifier (); +} + /* Generate the mangled name of DECL. */ static tree diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c index aa162d2a4f9..497ac5aafec 100644 --- c/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -40,6 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "type-utils.h" #include "gimplify.h" +#include "bitmap.h" #include "gcc-rich-location.h" #include "selftest.h" #include "target.h" @@ -965,6 +961,9 @@ maybe_new_partial_specialization (tree type) TREE_PRIVATE (d) = (current_access_specifier == access_private_node); TREE_PROTECTED (d) = (current_access_specifier == access_protected_node); + set_instantiating_module (d); + DECL_MODULE_EXPORT_P (d) = DECL_MODULE_EXPORT_P (tmpl); + return t; } @@ -4926,6 +4929,17 @@ build_template_decl (tree decl, tree parms, bool member_template_p) DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl); DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p; + if (modules_p ()) + { + /* Propagate module information from the decl. */ + DECL_MODULE_EXPORT_P (tmpl) = DECL_MODULE_EXPORT_P (decl); + if (DECL_LANG_SPECIFIC (decl)) + { + DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (decl); + gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl)); + } + } + return tmpl; } @@ -6047,6 +6061,14 @@ push_template_decl (tree decl, bool is_friend) tmpl = NULL_TREE; } } + else if (is_friend) + { + /* Record this decl as belonging to the current class. It's + not chained onto anything else. */ + DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (tmpl) = true; + gcc_checking_assert (!DECL_CHAIN (tmpl)); + DECL_CHAIN (tmpl) = current_scope (); + } } else if (tmpl) /* The type may have been completed, or (erroneously) changed. */ @@ -9770,6 +9792,15 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, return error_mark_node; gen_tmpl = most_general_template (templ); + if (flag_modules) + { + tree origin = get_originating_module_decl (gen_tmpl); + load_pending_specializations (CP_DECL_CONTEXT (origin), + DECL_NAME (origin)); + if (DECL_MODULE_PENDING_SPECIALIZATIONS_P (gen_tmpl)) + lazy_load_specializations (gen_tmpl); + } + parmlist = DECL_TEMPLATE_PARMS (gen_tmpl); parm_depth = TMPL_PARMS_DEPTH (parmlist); arg_depth = TMPL_ARGS_DEPTH (arglist); @@ -9990,6 +10021,12 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type)); } + set_instantiating_module (type_decl); + /* Although GEN_TMPL is the TEMPLATE_DECL, it has the same value + of export flag. We want to propagate this because it might + be a friend declaration that pushes a new hidden binding. */ + DECL_MODULE_EXPORT_P (type_decl) = DECL_MODULE_EXPORT_P (gen_tmpl); + if (CLASS_TYPE_P (template_type)) { TREE_PRIVATE (type_decl) @@ -10896,6 +10933,7 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc) new_level->errors = errorcount + sorrycount; new_level->next = NULL; new_level->refcount = 0; + new_level->path = new_level->visible = nullptr; set_refcount_ptr (new_level->next, current_tinst_level); set_refcount_ptr (current_tinst_level, new_level); @@ -11046,6 +11084,7 @@ tsubst_friend_function (tree decl, tree args) DECL_USE_TEMPLATE (new_friend) = 0; if (TREE_CODE (new_friend) == TEMPLATE_DECL) { + DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (new_friend) = false; DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0; DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend)) = DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl)); @@ -13891,6 +13935,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, if (!DECL_DELETED_FN (r)) DECL_INITIAL (r) = NULL_TREE; DECL_CONTEXT (r) = ctx; + set_instantiating_module (r); /* Handle explicit(dependent-expr). */ if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t)) @@ -14214,7 +14259,25 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, TREE_TYPE (r) = TREE_TYPE (inner); DECL_CONTEXT (r) = DECL_CONTEXT (inner); + if (modules_p ()) + { + /* Propagate module information from the decl. */ + DECL_MODULE_EXPORT_P (r) = DECL_MODULE_EXPORT_P (inner); + if (DECL_LANG_SPECIFIC (inner)) + { + DECL_MODULE_PURVIEW_P (r) = DECL_MODULE_PURVIEW_P (inner); + /* If this is a constrained template, the above tsubst of + inner can find the unconstrained template, which may have + come from an import. This is ok, because we don't + register this instantiation (see below). */ + gcc_checking_assert (!DECL_MODULE_IMPORT_P (inner) + || (TEMPLATE_PARMS_CONSTRAINTS + (DECL_TEMPLATE_PARMS (t)))); + DECL_MODULE_IMPORT_P (r) = false; + } + } + DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE; DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE; if (PRIMARY_TEMPLATE_P (t)) @@ -14769,6 +14831,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) SET_DECL_ASSEMBLER_NAME (r, NULL_TREE); if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL)) SET_DECL_RTL (r, NULL); + set_instantiating_module (r); + /* The initializer must not be expanded until it is required; see [temp.inst]. */ DECL_INITIAL (r) = NULL_TREE; @@ -20843,6 +20914,15 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain) (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl)), targ_ptr)); + if (flag_modules) + { + tree origin = get_originating_module_decl (gen_tmpl); + load_pending_specializations (CP_DECL_CONTEXT (origin), + DECL_NAME (origin)); + if (DECL_MODULE_PENDING_SPECIALIZATIONS_P (gen_tmpl)) + lazy_load_specializations (gen_tmpl); + } + /* It would be nice to avoid hashing here and then again in tsubst_decl, but it doesn't seem to be on the hot path. */ spec = retrieve_specialization (gen_tmpl, targ_ptr, 0); @@ -20928,6 +21008,8 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain) DECL_TI_TEMPLATE (fndecl) = tmpl; DECL_TI_ARGS (fndecl) = targ_ptr; + set_instantiating_module (fndecl); + /* Now we know the specialization, compute access previously deferred. Do no access control for inheriting constructors, as we already checked access for the inherited constructor. */ @@ -28002,6 +28082,8 @@ finish_concept_definition (cp_expr id, tree init) DECL_CONTEXT (decl) = current_scope (); DECL_INITIAL (decl) = init; + set_originating_module (decl, false); + /* Push the enclosing template. */ return push_template_decl (decl); } diff --git c/gcc/cp/ptree.c w/gcc/cp/ptree.c index a28b722f571..a216ca59e99 100644 --- c/gcc/cp/ptree.c +++ w/gcc/cp/ptree.c @@ -59,6 +59,42 @@ cxx_print_decl (FILE *file, tree node, int indent) bool need_indent = true; + if (TREE_CODE (node) == FUNCTION_DECL + || TREE_CODE (node) == VAR_DECL + || TREE_CODE (node) == TYPE_DECL + || TREE_CODE (node) == TEMPLATE_DECL + || TREE_CODE (node) == CONCEPT_DECL + || TREE_CODE (node) == NAMESPACE_DECL) + { + unsigned m = 0; + if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_IMPORT_P (node)) + m = get_importing_module (node, true); + + if (const char *name = m == ~0u ? "" : module_name (m, true)) + { + if (need_indent) + indent_to (file, indent + 3); + fprintf (file, " module %d:%s", m, name); + need_indent = false; + } + + if (DECL_LANG_SPECIFIC (node) && DECL_MODULE_PURVIEW_P (node)) + { + if (need_indent) + indent_to (file, indent + 3); + fprintf (file, " purview"); + need_indent = false; + } + } + + if (DECL_MODULE_EXPORT_P (node)) + { + if (need_indent) + indent_to (file, indent + 3); + fprintf (file, " exported"); + need_indent = false; + } + if (DECL_EXTERNAL (node) && DECL_NOT_REALLY_EXTERN (node)) { if (need_indent) @@ -250,6 +286,44 @@ cxx_print_xnode (FILE *file, tree node, int indent) print_node (file, "function", OVL_FUNCTION (node), indent + 4); print_node (file, "next", OVL_CHAIN (node), indent + 4); break; + case MODULE_VECTOR: + { + unsigned len = MODULE_VECTOR_NUM_CLUSTERS (node); + print_node (file, "name", MODULE_VECTOR_NAME (node), indent + 4); + fprintf (file, " clusters %u, alloc %u", len, + MODULE_VECTOR_ALLOC_CLUSTERS (node)); + for (unsigned ix = 0; ix != len; ix++) + { + module_cluster *cluster = &MODULE_VECTOR_CLUSTER (node, ix); + char pfx[20]; + for (unsigned jx = 0; jx != MODULE_VECTOR_SLOTS_PER_CLUSTER; jx++) + if (cluster->indices[jx].span) + { + int len = sprintf (pfx, "module:%u", + cluster->indices[jx].base); + if (cluster->indices[jx].span > 1) + len + += sprintf (&pfx[len], "(+%u)", cluster->indices[jx].span); + len += sprintf (&pfx[len], " cluster:%u/%u", ix, jx); + mc_slot &slot = cluster->slots[jx]; + if (slot.is_lazy ()) + { + indent_to (file, indent + 4); + unsigned lazy = slot.get_lazy (); + fprintf (file, "%s snum:%u flags:%d", + pfx, lazy >> 2, lazy & 3); + } + else if (slot) + print_node (file, pfx, slot, indent + 4); + else + { + indent_to (file, indent + 4); + fprintf (file, "%s NULL", pfx); + } + } + } + } + break; case TEMPLATE_PARM_INDEX: print_node (file, "decl", TEMPLATE_PARM_DECL (node), indent+4); indent_to (file, indent + 3); diff --git c/gcc/cp/semantics.c w/gcc/cp/semantics.c index 352ebe03436..a0888bc6c29 100644 --- c/gcc/cp/semantics.c +++ w/gcc/cp/semantics.c @@ -3225,6 +3225,19 @@ begin_class_definition (tree t) t = make_class_type (TREE_CODE (t)); pushtag (TYPE_IDENTIFIER (t), t); } + + if (flag_modules) + { + 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; @@ -4503,7 +4516,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; } diff --git c/gcc/gdbinit.in w/gcc/gdbinit.in index e951c19db63..eb999d2a808 100644 --- c/gcc/gdbinit.in +++ w/gcc/gdbinit.in @@ -333,6 +333,10 @@ b fancy_abort # Put a breakpoint on internal_error to help with debugging ICEs. b internal_error +# Break on module streaming error +b bytes_in::set_overrun if !overrun +b elf::set_error if !err + set complaints 0 # Don't let abort actually run, as it will make # stdio stop working and therefore the `pr' command above as well. diff --git c/gcc/tree-core.h w/gcc/tree-core.h index c9280a8d3b1..73aa0c3f399 100644 --- c/gcc/tree-core.h +++ w/gcc/tree-core.h @@ -769,6 +769,10 @@ enum tree_index { TI_SAT_UDA_TYPE, TI_SAT_UTA_TYPE, + TI_MODULE_HWM, + /* Nodes below here change during compilation, and should therefore + not be in the C++ module's global tree table. */ + TI_OPTIMIZATION_DEFAULT, TI_OPTIMIZATION_CURRENT, TI_TARGET_OPTION_DEFAULT, diff --git c/libcpp/include/cpplib.h w/libcpp/include/cpplib.h index 8e398863cf6..81be6457951 100644 --- c/libcpp/include/cpplib.h +++ w/libcpp/include/cpplib.h @@ -528,6 +538,9 @@ struct cpp_options one. */ bool phony_targets; + /* Generate dependency info for modules. */ + bool modules; + /* If true, no dependency is generated on the main file. */ bool ignore_main_file; diff --git c/gcc/cp/rtti.c w/gcc/cp/rtti.c index 887aae31bf6..0be9eff54ad 100644 --- c/gcc/cp/rtti.c +++ w/gcc/cp/rtti.c @@ -144,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); } @@ -766,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); @@ -781,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); @@ -955,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)) { @@ -1479,6 +1482,7 @@ get_tinfo_desc (unsigned ix) finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; DECL_CONTEXT (TYPE_NAME (pseudo_type)) = FROB_CONTEXT (global_namespace); + DECL_TINFO_P (TYPE_NAME (pseudo_type)) = true; xref_basetypes (pseudo_type, /*bases=*/NULL_TREE); res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); diff --git c/gcc/cp/tree.c w/gcc/cp/tree.c index 3087c4ab52c..d125fa5e793 100644 --- c/gcc/cp/tree.c +++ w/gcc/cp/tree.c @@ -2218,6 +2226,23 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual) return build_cp_fntype_variant (type, rqual, raises, late); } +tree +make_module_vec (tree name, unsigned clusters MEM_STAT_DECL) +{ + /* Stored in an unsigned short, but we're limited to the number of + modules anyway. */ + gcc_checking_assert (clusters <= (unsigned short)(~0)); + size_t length = (clusters * sizeof (module_cluster) + + sizeof (tree_module_vec) - sizeof (module_cluster)); + tree vec = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); + TREE_SET_CODE (vec, MODULE_VECTOR); + MODULE_VECTOR_NAME (vec) = name; + MODULE_VECTOR_ALLOC_CLUSTERS (vec) = clusters; + MODULE_VECTOR_NUM_CLUSTERS (vec) = 0; + + return vec; +} + /* Make a raw overload node containing FN. */ tree @@ -2237,10 +2262,11 @@ ovl_make (tree fn, tree next) return result; } -/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN - is > 0, if FN is via a using declaration. USING_OR_HIDDEN is < 0, - if FN is hidden. (A decl cannot be both using and hidden.) We - keep the hidden decls first, but remaining ones are unordered. */ +/* Add FN to the (potentially NULL) overload set OVL. USING_OR_HIDDEN is > + zero if this is a using-decl. It is > 1 if we're exporting the + using decl. USING_OR_HIDDEN is < 0, if FN is hidden. (A decl + cannot be both using and hidden.) We keep the hidden decls first, + but remaining ones are unordered. */ tree ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden) @@ -2264,7 +2290,11 @@ ovl_insert (tree fn, tree maybe_ovl, int using_or_hidden) if (using_or_hidden < 0) OVL_HIDDEN_P (maybe_ovl) = true; if (using_or_hidden > 0) - OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true; + { + OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true; + if (using_or_hidden > 1) + OVL_EXPORT_P (maybe_ovl) = true; + } } else maybe_ovl = fn; diff --git c/gcc/cp/class.c w/gcc/cp/class.c index c03737294eb..f4e44a5feba 100644 --- c/gcc/cp/class.c +++ w/gcc/cp/class.c @@ -4901,7 +4901,7 @@ build_clone (tree fn, tree name, bool need_vtt_parm_p, /* Build the clones of FN, return the number of clones built. These will be inserted onto DECL_CHAIN of FN. */ -static void +void build_cdtor_clones (tree fn, bool needs_vtt_p, bool base_omits_inherited_p, bool update_methods) { @@ -6740,6 +6740,8 @@ layout_class_type (tree t, tree *virtuals_p) TYPE_CONTEXT (base_t) = t; DECL_CONTEXT (base_d) = t; + set_instantiating_module (base_d); + /* If the ABI version is not at least two, and the last field was a bit-field, RLI may not be on a byte boundary. In particular, rli_size_unit_so_far might @@ -8719,6 +8721,7 @@ build_self_reference (void) DECL_ARTIFICIAL (decl) = 1; SET_DECL_SELF_REFERENCE_P (decl); set_underlying_type (decl); + set_instantiating_module (decl); if (processing_template_decl) decl = push_template_decl (decl);