@@ -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
@@ -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 <tree> {
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<tree> &);
+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;
}
@@ -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;
@@ -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 ();
@@ -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_("<structured bindings>"));
else
pp_string (pp, M_("<anonymous>"));
+
+ 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
@@ -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
@@ -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.
+
+ <module-name> ::= W <module-id>+ E
+ <module-id> :: <unqualified-name>
+ || _ <digit> ;; short backref
+ || W <number> _ ;; long backref
+ || P <module-id> ;; 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
@@ -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);
}
@@ -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);
@@ -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;
}
@@ -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.
@@ -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,
@@ -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;
@@ -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);
@@ -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;
@@ -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);