summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2022-05-09 04:47:14 -0700
committerNathan Sidwell <nathan@acm.org>2022-05-11 06:38:19 -0700
commita92ed39c416b2a92f404d9851fdfea5cae7e6b21 (patch)
tree937940a8cb1ba7ff82afc2385926cdc4519874c9
parent37a8220fa9188470c677abfef50c1b120c0b6c76 (diff)
downloadgcc-a92ed39c416b2a92f404d9851fdfea5cae7e6b21.tar.gz
[c++] Add module attachment
This adds module attachment as a distinct flag to 'in module purview'. A declaration may have neither or both (as before), but can also have just the 'in [named-module] purview', which was previously not representable. This new state allows some cleanup of redeclarations (particularly the builtins), which was a little warty. Some other internal APIs get similarly clarified. gcc/cp/ * cp-tree.h (DECL_MODULE_ATTACH_P): New. (struct lang_decl_base): Add module_attach_p flag. * decl.cc (duplicate_decls): Rework module redeclaration checking. * module.cc (trees_out::lang_decl_bools): Write attach flag. (trees_in::lang_decl_bools): ... and read it back. (trees_out::decl_value): Rework module attachment handling. (trees_in::decl_value): Rename local var to reflect meaning. (trees_in::key_mergeable): Likewise. (get_originating_module): Use DECL_MODULE_ATTACH_P. No need to special-case mangling. (module_may_redeclare): Reimplement. (set_originating_module): Deal with attachment. * name-lookup.cc (maybe_record_mergeable_decl): Deal with attachment. (mergeable_namespace_slots): Likewise. (do_nonmember_using_decl): Likewise. * name-lookup.h (mergeable_namespace_slots): Adjust parm meaning. * ptree.cc (cxx_print_decl): Adjust purview & attach printing.
-rw-r--r--gcc/cp/cp-tree.h14
-rw-r--r--gcc/cp/decl.cc23
-rw-r--r--gcc/cp/module.cc117
-rw-r--r--gcc/cp/name-lookup.cc17
-rw-r--r--gcc/cp/name-lookup.h2
-rw-r--r--gcc/cp/ptree.cc20
6 files changed, 114 insertions, 79 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index cfda8337ad8..e16b8d70846 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1725,6 +1725,11 @@ check_constraint_info (tree t)
#define DECL_MODULE_PURVIEW_P(N) \
(DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (N))->u.base.module_purview_p)
+/* Attached to the named module it is in the purview of. Decls
+ attached to the global module will have this false. */
+#define DECL_MODULE_ATTACH_P(N) \
+ (DECL_LANG_SPECIFIC (DECL_MODULE_CHECK (N))->u.base.module_attach_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)
@@ -2827,13 +2832,8 @@ struct GTY(()) lang_decl_base {
/* The following apply to VAR, FUNCTION, TYPE, CONCEPT, & NAMESPACE
decls. */
- // FIXME: Purview and Attachment are not the same thing, due to
- // linkage-declarations. The modules code presumes they are the
- // same. (For context, linkage-decl semantics was a very late
- // change). We need a module_attachment_p flag, and this will allow
- // some simplification of how we handle header unit entities.
- // Hurrah!
- unsigned module_purview_p : 1; /* in module purview (not GMF) */
+ unsigned module_purview_p : 1; // in named-module purview
+ unsigned module_attach_p : 1; // attached to named module
unsigned module_import_p : 1; /* from an import */
unsigned module_entity_p : 1; /* is in the entitity ary &
hash. */
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 4099fdeca5a..5654bc754e6 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2108,30 +2108,31 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
&& TREE_CODE (olddecl) != NAMESPACE_DECL
&& !hiding)
{
- if (DECL_ARTIFICIAL (olddecl))
+ if (!module_may_redeclare (olddecl))
{
- if (module_attach_p ())
+ if (DECL_ARTIFICIAL (olddecl))
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))
+ return error_mark_node;
+ }
+
+ tree not_tmpl = STRIP_TEMPLATE (olddecl);
+ if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_ATTACH_P (not_tmpl))
+ {
+ if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl))
+ && !DECL_MODULE_EXPORT_P (not_tmpl))
{
error ("conflicting exporting declaration %qD", newdecl);
inform (olddecl_loc, "previous declaration %q#D here", olddecl);
}
}
+ else if (DECL_MODULE_EXPORT_P (newdecl))
+ DECL_MODULE_EXPORT_P (not_tmpl) = true;
}
/* We have committed to returning OLDDECL at this point. */
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 27b8f64ce75..547bf360c4f 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -47,10 +47,14 @@ along with GCC; see the file COPYING3. If not see
module-local index.
Each importable DECL contains several flags. The simple set are
- DECL_EXPORT_P, DECL_MODULE_PURVIEW_P and DECL_MODULE_IMPORT_P. The
- first indicates whether it is exported, the second whether it is in
- the module purview (as opposed to the global module fragment), and
- the third indicates whether it was an import into this TU or not.
+ DECL_MODULE_EXPORT_P, DECL_MODULE_PURVIEW_P, DECL_MODULE_ATTACH_P
+ and DECL_MODULE_IMPORT_P. The first indicates whether it is
+ exported, the second whether it is in module or header-unit
+ purview. The third indicates it is attached to the named module in
+ whose purview it resides and the fourth indicates whether it was an
+ import into this TU or not. DECL_MODULE_ATTACH_P will be false for
+ all decls in a header-unit, and for those in a named module inside
+ a linkage declaration.
The more detailed flags are DECL_MODULE_PARTITION_P,
DECL_MODULE_ENTITY_P. The first is set in a primary interface unit
@@ -2927,7 +2931,7 @@ private:
public:
tree decl_container ();
tree key_mergeable (int tag, merge_kind, tree decl, tree inner, tree type,
- tree container, bool is_mod);
+ tree container, bool is_attached);
unsigned binfo_mergeable (tree *);
private:
@@ -5529,9 +5533,11 @@ trees_out::lang_decl_bools (tree t)
WB (lang->u.base.concept_p);
WB (lang->u.base.var_declared_inline_p);
WB (lang->u.base.dependent_init_p);
- /* When building a header unit, everthing is marked as purview, but
- that's the GM purview, so not what the importer will mean */
+ /* When building a header unit, everthing is marked as purview, (so
+ we know which decls to write). But when we import them we do not
+ want to mark them as in module purview. */
WB (lang->u.base.module_purview_p && !header_module_p ());
+ WB (lang->u.base.module_attach_p);
if (VAR_OR_FUNCTION_DECL_P (t))
WB (lang->u.base.module_keyed_decls_p);
switch (lang->u.base.selector)
@@ -5602,6 +5608,7 @@ trees_in::lang_decl_bools (tree t)
RB (lang->u.base.var_declared_inline_p);
RB (lang->u.base.dependent_init_p);
RB (lang->u.base.module_purview_p);
+ RB (lang->u.base.module_attach_p);
if (VAR_OR_FUNCTION_DECL_P (t))
RB (lang->u.base.module_keyed_decls_p);
switch (lang->u.base.selector)
@@ -7535,14 +7542,14 @@ trees_out::decl_value (tree decl, depset *dep)
or a module entity. This bool merges into the next block
of bools. Sneaky. */
tree o = get_originating_module_decl (decl);
- bool is_mod = false;
+ bool is_attached = false;
tree not_tmpl = STRIP_TEMPLATE (o);
if (DECL_LANG_SPECIFIC (not_tmpl)
- && DECL_MODULE_PURVIEW_P (not_tmpl))
- is_mod = true;
+ && DECL_MODULE_ATTACH_P (not_tmpl))
+ is_attached = true;
- b (is_mod);
+ b (is_attached);
}
b (dep && dep->has_defn ());
}
@@ -7791,7 +7798,7 @@ tree
trees_in::decl_value ()
{
int tag = 0;
- bool is_mod = false;
+ bool is_attached = false;
bool has_defn = false;
unsigned mk_u = u ();
if (mk_u >= MK_hwm || !merge_kind_name[mk_u])
@@ -7812,7 +7819,7 @@ trees_in::decl_value ()
{
if (!(mk & MK_template_mask) && !state->is_header ())
/* See note in trees_out about where this bool is sequenced. */
- is_mod = b ();
+ is_attached = b ();
has_defn = b ();
}
@@ -7916,7 +7923,8 @@ trees_in::decl_value ()
if (TREE_CODE (inner) == FUNCTION_DECL)
parm_tag = fn_parms_init (inner);
- tree existing = key_mergeable (tag, mk, decl, inner, type, container, is_mod);
+ tree existing = key_mergeable (tag, mk, decl, inner, type, container,
+ is_attached);
tree existing_inner = existing;
if (existing)
{
@@ -10652,7 +10660,7 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key)
tree
trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
- tree type, tree container, bool is_mod)
+ tree type, tree container, bool is_attached)
{
const char *kind = "new";
tree existing = NULL_TREE;
@@ -10792,14 +10800,15 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
}
}
}
- else if (is_mod && !(state->is_module () || state->is_partition ()))
+ else if (is_attached
+ && !(state->is_module () || state->is_partition ()))
kind = "unique";
else
{
gcc_checking_assert (mk == MK_named || mk == MK_enum);
tree mvec;
tree *vslot = mergeable_namespace_slots (container, name,
- !is_mod, &mvec);
+ is_attached, &mvec);
existing = check_mergeable_decl (mk, decl, *vslot, key);
if (!existing)
add_mergeable_namespace_entity (vslot, decl);
@@ -10807,7 +10816,7 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
{
/* Note that we now have duplicates to deal with in
name lookup. */
- if (is_mod)
+ if (is_attached)
BINDING_VECTOR_PARTITION_DUPS_P (mvec) = true;
else
BINDING_VECTOR_GLOBAL_DUPS_P (mvec) = true;
@@ -10824,7 +10833,7 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
break;
case TYPE_DECL:
- if (is_mod && !(state->is_module () || state->is_partition ())
+ if (is_attached && !(state->is_module () || state->is_partition ())
/* Implicit member functions can come from
anywhere. */
&& !(DECL_ARTIFICIAL (decl)
@@ -18389,14 +18398,11 @@ get_originating_module (tree decl, bool for_mangle)
if (!DECL_LANG_SPECIFIC (not_tmpl))
return for_mangle ? -1 : 0;
- if (for_mangle && !DECL_MODULE_PURVIEW_P (not_tmpl))
+ if (for_mangle && !DECL_MODULE_ATTACH_P (not_tmpl))
return -1;
int mod = !DECL_MODULE_IMPORT_P (not_tmpl) ? 0 : get_importing_module (owner);
-
- if (for_mangle && (*modules)[mod]->is_header ())
- return -1;
-
+ gcc_checking_assert (!for_mangle || !(*modules)[mod]->is_header ());
return mod;
}
@@ -18416,9 +18422,34 @@ get_importing_module (tree decl, bool flexible)
bool
module_may_redeclare (tree decl)
{
+ for (;;)
+ {
+ tree ctx = CP_DECL_CONTEXT (decl);
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ // Found the namespace-scope decl.
+ break;
+ if (!CLASS_TYPE_P (ctx))
+ // We've met a non-class scope. Such a thing is not
+ // reopenable, so we must be ok.
+ return true;
+ decl = TYPE_NAME (ctx);
+ }
+
+ tree not_tmpl = STRIP_TEMPLATE (decl);
+
+ int use_tpl = 0;
+ if (node_template_info (not_tmpl, use_tpl) && use_tpl)
+ // Specializations of any kind can be redeclared anywhere.
+ // FIXME: Should we be checking this in more places on the scope chain?
+ return true;
+
+ if (!DECL_LANG_SPECIFIC (not_tmpl) || !DECL_MODULE_ATTACH_P (not_tmpl))
+ // Decl is attached to global module. Current scope needs to be too.
+ return !module_attach_p ();
+
module_state *me = (*modules)[0];
module_state *them = me;
- tree not_tmpl = STRIP_TEMPLATE (decl);
+
if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_IMPORT_P (not_tmpl))
{
/* We can be given the TEMPLATE_RESULT. We want the
@@ -18446,30 +18477,14 @@ module_may_redeclare (tree decl)
them = import_entity_module (index);
}
- if (them->is_header ())
- {
- if (!header_module_p ())
- return !module_purview_p ();
-
- if (DECL_SOURCE_LOCATION (decl) == BUILTINS_LOCATION)
- /* This is a builtin, being declared in header-unit. We
- now need to mark it as an export. */
- DECL_MODULE_EXPORT_P (decl) = true;
-
- /* If it came from a header, it's in the global module. */
- return true;
- }
+ // Decl is attached to named module. Current scope needs to be
+ // attaching to the same module.
+ if (!module_attach_p ())
+ return false;
+ // Both attached to named module.
if (me == them)
- return ((DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_PURVIEW_P (not_tmpl))
- == module_purview_p ());
-
- if (!me->name)
- me = me->parent;
-
- /* We can't have found a GMF entity from a named module. */
- gcc_checking_assert (DECL_LANG_SPECIFIC (not_tmpl)
- && DECL_MODULE_PURVIEW_P (not_tmpl));
+ return true;
return me && get_primary (them) == get_primary (me);
}
@@ -18554,11 +18569,17 @@ set_originating_module (tree decl, bool friend_p ATTRIBUTE_UNUSED)
{
set_instantiating_module (decl);
- if (TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)
+ if (!DECL_NAMESPACE_SCOPE_P (decl))
return;
gcc_checking_assert (friend_p || decl == get_originating_module_decl (decl));
+ if (module_attach_p ())
+ {
+ retrofit_lang_decl (decl);
+ DECL_MODULE_ATTACH_P (decl) = true;
+ }
+
if (!module_exporting_p ())
return;
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index a05244df74e..6bed9dac63f 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -3493,11 +3493,13 @@ maybe_record_mergeable_decl (tree *slot, tree name, tree decl)
/* Internal linkage. */
return;
- bool partition = named_module_p ();
+ bool is_attached = (DECL_LANG_SPECIFIC (not_tmpl)
+ && DECL_MODULE_ATTACH_P (not_tmpl));
tree *gslot = get_fixed_binding_slot
- (slot, name, partition ? BINDING_SLOT_PARTITION : BINDING_SLOT_GLOBAL, true);
+ (slot, name, is_attached ? BINDING_SLOT_PARTITION : BINDING_SLOT_GLOBAL,
+ true);
- if (!partition)
+ if (!is_attached)
{
binding_slot &orig
= BINDING_VECTOR_CLUSTER (*slot, 0).slots[BINDING_SLOT_CURRENT];
@@ -3841,11 +3843,12 @@ pushdecl (tree decl, bool hiding)
GMF slot or a module-specific one. */
tree *
-mergeable_namespace_slots (tree ns, tree name, bool is_global, tree *vec)
+mergeable_namespace_slots (tree ns, tree name, bool is_attached, tree *vec)
{
tree *mslot = find_namespace_slot (ns, name, true);
tree *vslot = get_fixed_binding_slot
- (mslot, name, is_global ? BINDING_SLOT_GLOBAL : BINDING_SLOT_PARTITION, true);
+ (mslot, name, is_attached ? BINDING_SLOT_PARTITION : BINDING_SLOT_GLOBAL,
+ true);
gcc_checking_assert (TREE_CODE (*mslot) == BINDING_VECTOR);
*vec = *mslot;
@@ -4832,10 +4835,10 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
if (exporting)
{
/* If the using decl is exported, the things it refers
- to must also be exported (or not in module purview). */
+ to must also be exported (or not habve module attachment). */
if (!DECL_MODULE_EXPORT_P (new_fn)
&& (DECL_LANG_SPECIFIC (new_fn)
- && DECL_MODULE_PURVIEW_P (new_fn)))
+ && DECL_MODULE_ATTACH_P (new_fn)))
{
error ("%q#D does not have external linkage", new_fn);
inform (DECL_SOURCE_LOCATION (new_fn),
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index fa039028847..999db33a7e0 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -471,7 +471,7 @@ extern void pop_from_top_level (void);
extern void push_using_decl_bindings (tree, tree);
/* Lower level interface for modules. */
-extern tree *mergeable_namespace_slots (tree ns, tree name, bool is_global,
+extern tree *mergeable_namespace_slots (tree ns, tree name, bool is_attached,
tree *mvec);
extern void add_mergeable_namespace_entity (tree *slot, tree decl);
extern tree lookup_class_binding (tree ctx, tree name);
diff --git a/gcc/cp/ptree.cc b/gcc/cp/ptree.cc
index 540f1e4c81e..53ce06ccd2d 100644
--- a/gcc/cp/ptree.cc
+++ b/gcc/cp/ptree.cc
@@ -79,12 +79,22 @@ cxx_print_decl (FILE *file, tree node, int indent)
need_indent = false;
}
- if (DECL_LANG_SPECIFIC (ntnode) && DECL_MODULE_PURVIEW_P (ntnode))
+ if (DECL_LANG_SPECIFIC (ntnode))
{
- if (need_indent)
- indent_to (file, indent + 3);
- fprintf (file, " purview");
- need_indent = false;
+ if (DECL_MODULE_PURVIEW_P (ntnode))
+ {
+ if (need_indent)
+ indent_to (file, indent + 3);
+ fprintf (file, " purview");
+ need_indent = false;
+ }
+ if (DECL_MODULE_ATTACH_P (ntnode))
+ {
+ if (need_indent)
+ indent_to (file, indent + 3);
+ fprintf (file, " attached");
+ need_indent = false;
+ }
}
}