mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 01:50:34 +08:00
c++: Decl module-specific semantic processing
This adds the module-specific logic to the various declaration processing routines in decl.c and semantic.c. I also adjust the rtti type creation, as those are all in the global module, so we need to temporarily clear the module_kind, when they are being created. Finally, I added init and fini module processing with the initialier giving a fatal error if you try and turn it on (so don't do that yet). gcc/cp/ * decl.c (duplicate_decls): Add module-specific redeclaration logic. (cxx_init_decl_processing): Export the global namespace, maybe initialize modules. (start_decl): Reject local-extern in a module, adjust linkage of template var. (xref_tag_1): Add module-specific redeclaration logic. (start_enum): Likewise. (finish_enum_value_list): Export unscoped members of an exported enum. (grokmethod): Implement p1779 linkage of in-class defined functions. * decl2.c (no_linkage_error): Imports are ok. (c_parse_final_cleanups): Call fini_modules. * lex.c (cxx_dup_lang_specific): Clear some module flags in the copy. * module.cc (module_kind): Define. (module_may_redeclare, set_defining_module): Stubs. (init_modules): Error on modules. (fini_modules): Stub. * rtti.c (push_abi_namespace): Save and reset module_kind. (pop_abi_namespace): Restore module kind. (build_dynamic_cast_1, tinfo_base_init): Adjust. * semantics.c (begin_class_definition): Add module-specific logic. (expand_or_defer_fn_1): Keep bodies of more fns when modules_p.
This commit is contained in:
parent
72217b5ddb
commit
cf97b970fe
149
gcc/cp/decl.c
149
gcc/cp/decl.c
@ -2008,6 +2008,39 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
if (!validate_constexpr_redeclaration (olddecl, newdecl))
|
||||
return error_mark_node;
|
||||
|
||||
if (modules_p ()
|
||||
&& TREE_CODE (CP_DECL_CONTEXT (olddecl)) == NAMESPACE_DECL
|
||||
&& TREE_CODE (olddecl) != NAMESPACE_DECL
|
||||
&& !hiding)
|
||||
{
|
||||
if (DECL_ARTIFICIAL (olddecl))
|
||||
{
|
||||
gcc_checking_assert (!(DECL_LANG_SPECIFIC (olddecl)
|
||||
&& DECL_MODULE_IMPORT_P (olddecl)));
|
||||
if (!(global_purview_p () || not_module_p ()))
|
||||
error ("declaration %qD conflicts with builtin", newdecl);
|
||||
else
|
||||
DECL_MODULE_EXPORT_P (olddecl) = DECL_MODULE_EXPORT_P (newdecl);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!module_may_redeclare (olddecl))
|
||||
{
|
||||
error ("declaration %qD conflicts with import", newdecl);
|
||||
inform (olddecl_loc, "import declared %q#D here", olddecl);
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (DECL_MODULE_EXPORT_P (newdecl)
|
||||
&& !DECL_MODULE_EXPORT_P (olddecl))
|
||||
{
|
||||
error ("conflicting exporting declaration %qD", newdecl);
|
||||
inform (olddecl_loc, "previous declaration %q#D here", olddecl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We have committed to returning OLDDECL at this point. */
|
||||
|
||||
/* If new decl is `static' and an `extern' was seen previously,
|
||||
@ -2218,6 +2251,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
}
|
||||
}
|
||||
|
||||
DECL_MODULE_IMPORT_P (olddecl)
|
||||
= DECL_MODULE_IMPORT_P (old_result)
|
||||
= DECL_MODULE_IMPORT_P (newdecl);
|
||||
|
||||
return olddecl;
|
||||
}
|
||||
|
||||
@ -2836,6 +2873,20 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
|
||||
memcpy ((char *) olddecl + sizeof (struct tree_common),
|
||||
(char *) newdecl + sizeof (struct tree_common),
|
||||
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
|
||||
|
||||
if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl))
|
||||
{
|
||||
/* Repropagate the module information to the template. */
|
||||
tree tmpl = DECL_TI_TEMPLATE (olddecl);
|
||||
|
||||
if (DECL_TEMPLATE_RESULT (tmpl) == olddecl)
|
||||
{
|
||||
DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl);
|
||||
gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl));
|
||||
DECL_MODULE_IMPORT_P (tmpl) = false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (TREE_CODE (newdecl))
|
||||
{
|
||||
case LABEL_DECL:
|
||||
@ -4330,7 +4381,8 @@ cxx_init_decl_processing (void)
|
||||
gcc_assert (global_namespace == NULL_TREE);
|
||||
global_namespace = build_lang_decl (NAMESPACE_DECL, global_identifier,
|
||||
void_type_node);
|
||||
TREE_PUBLIC (global_namespace) = 1;
|
||||
TREE_PUBLIC (global_namespace) = true;
|
||||
DECL_MODULE_EXPORT_P (global_namespace) = true;
|
||||
DECL_CONTEXT (global_namespace)
|
||||
= build_translation_unit_decl (get_identifier (main_input_filename));
|
||||
/* Remember whether we want the empty class passing ABI change warning
|
||||
@ -4629,6 +4681,9 @@ cxx_init_decl_processing (void)
|
||||
if (! supports_one_only ())
|
||||
flag_weak = 0;
|
||||
|
||||
if (modules_p ())
|
||||
init_modules (parse_in);
|
||||
|
||||
make_fname_decl = cp_make_fname_decl;
|
||||
start_fname_decls ();
|
||||
|
||||
@ -5453,8 +5508,14 @@ start_decl (const cp_declarator *declarator,
|
||||
|
||||
if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL)
|
||||
&& current_function_decl)
|
||||
/* A function-scope decl of some namespace-scope decl. */
|
||||
DECL_LOCAL_DECL_P (decl) = true;
|
||||
{
|
||||
/* A function-scope decl of some namespace-scope decl. */
|
||||
DECL_LOCAL_DECL_P (decl) = true;
|
||||
if (named_module_purview_p ())
|
||||
error_at (declarator->id_loc,
|
||||
"block-scope extern declaration %q#D not permitted"
|
||||
" in module purview", decl);
|
||||
}
|
||||
|
||||
/* Enter this declaration into the symbol table. Don't push the plain
|
||||
VAR_DECL for a variable template. */
|
||||
@ -5470,7 +5531,9 @@ start_decl (const cp_declarator *declarator,
|
||||
|
||||
if (VAR_P (decl)
|
||||
&& DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
|
||||
&& !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
|
||||
&& !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl)
|
||||
/* But not templated variables. */
|
||||
&& !(DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
|
||||
{
|
||||
/* This is a const variable with implicit 'static'. Set
|
||||
DECL_THIS_STATIC so we can tell it from variables that are
|
||||
@ -15143,6 +15206,41 @@ xref_tag_1 (enum tag_types tag_code, tree name,
|
||||
inform (location_of (t), "previous declaration %qD", t);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (modules_p ()
|
||||
&& how == TAG_how::CURRENT_ONLY)
|
||||
{
|
||||
tree decl = TYPE_NAME (t);
|
||||
if (!module_may_redeclare (decl))
|
||||
{
|
||||
error ("cannot declare %qD in a different module", decl);
|
||||
inform (DECL_SOURCE_LOCATION (decl), "declared here");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
tree maybe_tmpl = decl;
|
||||
if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t))
|
||||
maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t);
|
||||
|
||||
if (DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_MODULE_IMPORT_P (decl)
|
||||
&& TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL)
|
||||
{
|
||||
/* Push it into this TU's symbol slot. */
|
||||
gcc_checking_assert (current_namespace == CP_DECL_CONTEXT (decl));
|
||||
if (maybe_tmpl != decl)
|
||||
/* We're in the template parm binding level.
|
||||
Pushtag has logic to slide under that, but we're
|
||||
not pushing a *new* type. */
|
||||
push_nested_namespace (CP_DECL_CONTEXT (decl));
|
||||
|
||||
pushdecl (maybe_tmpl);
|
||||
if (maybe_tmpl != decl)
|
||||
pop_nested_namespace (CP_DECL_CONTEXT (decl));
|
||||
}
|
||||
|
||||
set_instantiating_module (maybe_tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
@ -15487,6 +15585,19 @@ start_enum (tree name, tree enumtype, tree underlying_type,
|
||||
"previous definition here");
|
||||
underlying_type = NULL_TREE;
|
||||
}
|
||||
|
||||
if (modules_p ())
|
||||
{
|
||||
if (!module_may_redeclare (TYPE_NAME (enumtype)))
|
||||
{
|
||||
error ("cannot define %qD in different module",
|
||||
TYPE_NAME (enumtype));
|
||||
inform (DECL_SOURCE_LOCATION (TYPE_NAME (enumtype)),
|
||||
"declared here");
|
||||
enumtype = error_mark_node;
|
||||
}
|
||||
set_instantiating_module (TYPE_NAME (enumtype));
|
||||
}
|
||||
}
|
||||
|
||||
if (!enumtype || TREE_CODE (enumtype) != ENUMERAL_TYPE
|
||||
@ -15747,6 +15858,11 @@ finish_enum_value_list (tree enumtype)
|
||||
else
|
||||
underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
|
||||
|
||||
/* If the enum is exported, mark the consts too. */
|
||||
bool export_p = (UNSCOPED_ENUM_P (enumtype)
|
||||
&& DECL_MODULE_EXPORT_P (TYPE_STUB_DECL (enumtype))
|
||||
&& at_namespace_scope_p ());
|
||||
|
||||
/* Convert each of the enumerators to the type of the underlying
|
||||
type of the enumeration. */
|
||||
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
|
||||
@ -15769,6 +15885,8 @@ finish_enum_value_list (tree enumtype)
|
||||
TREE_TYPE (value) = enumtype;
|
||||
}
|
||||
DECL_INITIAL (decl) = value;
|
||||
if (export_p)
|
||||
DECL_MODULE_EXPORT_P (decl) = true;
|
||||
}
|
||||
|
||||
/* Fix up all variant types of this enum type. */
|
||||
@ -17366,10 +17484,25 @@ grokmethod (cp_decl_specifier_seq *declspecs,
|
||||
|
||||
check_template_shadow (fndecl);
|
||||
|
||||
if (TREE_PUBLIC (fndecl))
|
||||
DECL_COMDAT (fndecl) = 1;
|
||||
DECL_DECLARED_INLINE_P (fndecl) = 1;
|
||||
DECL_NO_INLINE_WARNING_P (fndecl) = 1;
|
||||
/* p1779 ABI-Isolation makes inline not a default for in-class
|
||||
definitions in named module purview. If the user explicitly
|
||||
made it inline, grokdeclarator will already have done the right
|
||||
things. */
|
||||
if ((!named_module_purview_p ()
|
||||
|| flag_module_implicit_inline
|
||||
/* Lambda's operator function remains inline. */
|
||||
|| LAMBDA_TYPE_P (DECL_CONTEXT (fndecl)))
|
||||
/* If the user explicitly asked for this to be inline, we don't
|
||||
need to do more, but more importantly we want to warn if we
|
||||
can't inline it. */
|
||||
&& !DECL_DECLARED_INLINE_P (fndecl))
|
||||
{
|
||||
if (TREE_PUBLIC (fndecl))
|
||||
DECL_COMDAT (fndecl) = 1;
|
||||
DECL_DECLARED_INLINE_P (fndecl) = 1;
|
||||
/* It's ok if we can't inline this. */
|
||||
DECL_NO_INLINE_WARNING_P (fndecl) = 1;
|
||||
}
|
||||
|
||||
/* We process method specializations in finish_struct_1. */
|
||||
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
|
||||
|
@ -4531,6 +4531,10 @@ no_linkage_error (tree decl)
|
||||
/* In C++11 it's ok if the decl is defined. */
|
||||
return;
|
||||
|
||||
if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl))
|
||||
/* An imported decl is ok. */
|
||||
return;
|
||||
|
||||
tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
|
||||
if (t == NULL_TREE)
|
||||
/* The type that got us on no_linkage_decls must have gotten a name for
|
||||
@ -5226,6 +5230,8 @@ c_parse_final_cleanups (void)
|
||||
if (priority_info_map)
|
||||
splay_tree_delete (priority_info_map);
|
||||
|
||||
fini_modules ();
|
||||
|
||||
/* Generate any missing aliases. */
|
||||
maybe_apply_pending_pragma_weaks ();
|
||||
|
||||
|
@ -1006,6 +1006,12 @@ cxx_dup_lang_specific_decl (tree node)
|
||||
memcpy (ld, DECL_LANG_SPECIFIC (node), size);
|
||||
DECL_LANG_SPECIFIC (node) = ld;
|
||||
|
||||
/* Directly clear some flags that do not apply to the copy
|
||||
(module_purview_p still does). */
|
||||
ld->u.base.module_entity_p = false;
|
||||
ld->u.base.module_import_p = false;
|
||||
ld->u.base.module_pending_p = false;
|
||||
|
||||
if (GATHER_STATISTICS)
|
||||
{
|
||||
tree_node_counts[(int)lang_decl] += 1;
|
||||
|
@ -65,6 +65,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "intl.h"
|
||||
#include "langhooks.h"
|
||||
|
||||
/* What the current TU is. */
|
||||
unsigned module_kind;
|
||||
|
||||
module_state *
|
||||
get_module (tree, module_state *, bool)
|
||||
{
|
||||
@ -99,11 +102,22 @@ get_originating_module (tree, bool)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
module_may_redeclare (tree)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
set_instantiating_module (tree)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
set_defining_module (tree)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
set_originating_module (tree, bool)
|
||||
{
|
||||
@ -120,3 +134,16 @@ preprocessed_module (cpp_reader *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init_modules (cpp_reader *)
|
||||
{
|
||||
/* Do not turn on yet. */
|
||||
if (modules_p ())
|
||||
fatal_error (input_location,
|
||||
"Shtopp! What are you doing? This is not ready yet.");
|
||||
}
|
||||
|
||||
void
|
||||
fini_modules ()
|
||||
{
|
||||
}
|
||||
|
@ -143,16 +143,20 @@ static bool typeinfo_in_lib_p (tree);
|
||||
|
||||
static int doing_runtime = 0;
|
||||
|
||||
static void
|
||||
static unsigned
|
||||
push_abi_namespace (void)
|
||||
{
|
||||
push_nested_namespace (abi_node);
|
||||
push_visibility ("default", 2);
|
||||
unsigned flags = module_kind;
|
||||
module_kind = 0;
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void
|
||||
pop_abi_namespace (void)
|
||||
pop_abi_namespace (unsigned flags)
|
||||
{
|
||||
module_kind = flags;
|
||||
pop_visibility (2);
|
||||
pop_nested_namespace (abi_node);
|
||||
}
|
||||
@ -765,7 +769,7 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
|
||||
dcast_fn = dynamic_cast_node;
|
||||
if (!dcast_fn)
|
||||
{
|
||||
push_abi_namespace ();
|
||||
unsigned flags = push_abi_namespace ();
|
||||
tree tinfo_ptr = xref_tag (class_type,
|
||||
get_identifier ("__class_type_info"));
|
||||
tinfo_ptr = cp_build_qualified_type (tinfo_ptr, TYPE_QUAL_CONST);
|
||||
@ -780,7 +784,7 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
|
||||
NULL_TREE));
|
||||
dcast_fn = (build_library_fn_ptr
|
||||
(fn_name, fn_type, ECF_LEAF | ECF_PURE | ECF_NOTHROW));
|
||||
pop_abi_namespace ();
|
||||
pop_abi_namespace (flags);
|
||||
dynamic_cast_node = dcast_fn;
|
||||
}
|
||||
result = build_cxx_call (dcast_fn, 4, elems, complain);
|
||||
@ -954,11 +958,11 @@ tinfo_base_init (tinfo_s *ti, tree target)
|
||||
vtable_ptr = ti->vtable;
|
||||
if (!vtable_ptr)
|
||||
{
|
||||
push_abi_namespace ();
|
||||
int flags = push_abi_namespace ();
|
||||
tree real_type = xref_tag (class_type, ti->name);
|
||||
tree real_decl = TYPE_NAME (real_type);
|
||||
DECL_SOURCE_LOCATION (real_decl) = BUILTINS_LOCATION;
|
||||
pop_abi_namespace ();
|
||||
pop_abi_namespace (flags);
|
||||
|
||||
if (!COMPLETE_TYPE_P (real_type))
|
||||
{
|
||||
|
@ -3220,6 +3220,19 @@ begin_class_definition (tree t)
|
||||
t = make_class_type (TREE_CODE (t));
|
||||
pushtag (TYPE_IDENTIFIER (t), t);
|
||||
}
|
||||
|
||||
if (modules_p ())
|
||||
{
|
||||
if (!module_may_redeclare (TYPE_NAME (t)))
|
||||
{
|
||||
error ("cannot declare %qD in a different module", TYPE_NAME (t));
|
||||
inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)), "declared here");
|
||||
return error_mark_node;
|
||||
}
|
||||
set_instantiating_module (TYPE_NAME (t));
|
||||
set_defining_module (TYPE_NAME (t));
|
||||
}
|
||||
|
||||
maybe_process_partial_specialization (t);
|
||||
pushclass (t);
|
||||
TYPE_BEING_DEFINED (t) = 1;
|
||||
@ -4506,7 +4519,8 @@ expand_or_defer_fn_1 (tree fn)
|
||||
it out, even though we haven't. */
|
||||
TREE_ASM_WRITTEN (fn) = 1;
|
||||
/* If this is a constexpr function, keep DECL_SAVED_TREE. */
|
||||
if (!DECL_DECLARED_CONSTEXPR_P (fn))
|
||||
if (!DECL_DECLARED_CONSTEXPR_P (fn)
|
||||
&& !(modules_p () && DECL_DECLARED_INLINE_P (fn)))
|
||||
DECL_SAVED_TREE (fn) = NULL_TREE;
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user