From: Nathaniel Shead Date: Sun, 3 Mar 2024 12:48:17 +0000 (+1100) Subject: c++: Support exporting using-decls in same namespace as target X-Git-Tag: basepoints/gcc-15~830 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ad0f4ef6f74741ea6178a8b795e49effc2bc2a9c;p=thirdparty%2Fgcc.git c++: Support exporting using-decls in same namespace as target Currently a using-declaration bringing a name into its own namespace is a no-op, except for functions. This prevents people from being able to redeclare a name brought in from the GMF as exported, however, which this patch fixes. Apart from marking declarations as exported they are also now marked as effectively being in the module purview (due to the using-decl) so that they are properly processed, as 'add_binding_entity' assumes that declarations not in the module purview cannot possibly be exported. gcc/cp/ChangeLog: * name-lookup.cc (walk_module_binding): Remove completed FIXME. (do_nonmember_using_decl): Mark redeclared entities as exported when needed. Check for re-exporting internal linkage types. gcc/testsuite/ChangeLog: * g++.dg/modules/using-12.C: New test. * g++.dg/modules/using-13.h: New test. * g++.dg/modules/using-13_a.C: New test. * g++.dg/modules/using-13_b.C: New test. Signed-off-by: Nathaniel Shead --- diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 6444db3f0ebf..dce4caf89819 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -4189,7 +4189,7 @@ walk_module_binding (tree binding, bitmap partitions, void *data) { // FIXME: We don't quite deal with using decls naming stat hack - // type. Also using decls exporting something from the same scope. + // type. tree current = binding; unsigned count = 0; @@ -5238,13 +5238,36 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p, } else if (insert_p) { - value = lookup.value; - if (revealing_p && module_exporting_p ()) - check_can_export_using_decl (value); + if (revealing_p + && module_exporting_p () + && check_can_export_using_decl (lookup.value) + && lookup.value == value + && !DECL_MODULE_EXPORT_P (value)) + { + /* We're redeclaring the same value, but this time as + newly exported: make sure to mark it as such. */ + if (TREE_CODE (value) == TEMPLATE_DECL) + { + DECL_MODULE_EXPORT_P (value) = true; + + tree result = DECL_TEMPLATE_RESULT (value); + retrofit_lang_decl (result); + DECL_MODULE_PURVIEW_P (result) = true; + DECL_MODULE_EXPORT_P (result) = true; + } + else + { + retrofit_lang_decl (value); + DECL_MODULE_PURVIEW_P (value) = true; + DECL_MODULE_EXPORT_P (value) = true; + } + } + else + value = lookup.value; } /* Now the type binding. */ - if (lookup.type && lookup.type != type) + if (lookup.type) { if (type && !decls_match (lookup.type, type)) { @@ -5253,9 +5276,20 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p, } else if (insert_p) { - type = lookup.type; - if (revealing_p && module_exporting_p ()) - check_can_export_using_decl (type); + if (revealing_p + && module_exporting_p () + && check_can_export_using_decl (lookup.type) + && lookup.type == type + && !DECL_MODULE_EXPORT_P (type)) + { + /* We're redeclaring the same type, but this time as + newly exported: make sure to mark it as such. */ + retrofit_lang_decl (type); + DECL_MODULE_PURVIEW_P (type) = true; + DECL_MODULE_EXPORT_P (type) = true; + } + else + type = lookup.type; } } diff --git a/gcc/testsuite/g++.dg/modules/using-12.C b/gcc/testsuite/g++.dg/modules/using-12.C new file mode 100644 index 000000000000..54eacf7276eb --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-12.C @@ -0,0 +1,73 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi !bad } + +// Like using-10.C, but test exporting names within the same namespace. + +export module bad; + +// internal linkage +namespace s { + namespace { + struct a1 {}; // { dg-message "declared here with internal linkage" } + + template + struct b1; // { dg-message "declared here with internal linkage" } + + int x1; // { dg-message "declared here with internal linkage" } + + template + T y1; // { dg-message "declared here with internal linkage" } + + void f1(); // { dg-message "declared here with internal linkage" } + + template + void g1(); // { dg-message "declared here with internal linkage" } + + export using s::a1; // { dg-error "does not have external linkage" } + export using s::b1; // { dg-error "does not have external linkage" } + export using s::x1; // { dg-error "does not have external linkage" } + export using s::y1; // { dg-error "does not have external linkage" } + export using s::f1; // { dg-error "does not have external linkage" } + export using s::g1; // { dg-error "does not have external linkage" } + } +} + +// module linkage +namespace m { + struct a2 {}; // { dg-message "declared here with module linkage" } + + template + struct b2; // { dg-message "declared here with module linkage" } + + int x2; // { dg-message "declared here with module linkage" } + + template + T y2; // { dg-message "declared here with module linkage" } + + void f2(); // { dg-message "declared here with module linkage" } + + template + void g2(); // { dg-message "declared here with module linkage" } + + export using m::a2; // { dg-error "does not have external linkage" } + export using m::b2; // { dg-error "does not have external linkage" } + export using m::x2; // { dg-error "does not have external linkage" } + export using m::y2; // { dg-error "does not have external linkage" } + export using m::f2; // { dg-error "does not have external linkage" } + export using m::g2; // { dg-error "does not have external linkage" } +} + +namespace t { + using a = int; // { dg-message "declared here with no linkage" } + + template + using b = int; // { dg-message "declared here with no linkage" } + + typedef int c; // { dg-message "declared here with no linkage" } + + export using t::a; // { dg-error "does not have external linkage" } + export using t::b; // { dg-error "does not have external linkage" } + export using t::c; // { dg-error "does not have external linkage" } +} + +// { dg-prune-output "not writing module" } diff --git a/gcc/testsuite/g++.dg/modules/using-13.h b/gcc/testsuite/g++.dg/modules/using-13.h new file mode 100644 index 000000000000..b8ef2a11cc49 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-13.h @@ -0,0 +1,16 @@ +// Like using-11.h, but additional kinds of declarations. + +struct A {}; + +template struct B {}; +template <> struct B { using foo = int; }; +template struct B { using bar = T; }; + +using C = int; + +inline int D = 0; + +#if __cpp_concepts >= 201907L +template +concept E = true; +#endif diff --git a/gcc/testsuite/g++.dg/modules/using-13_a.C b/gcc/testsuite/g++.dg/modules/using-13_a.C new file mode 100644 index 000000000000..fed33ac2333a --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-13_a.C @@ -0,0 +1,15 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi M } + +module; +#include "using-13.h" + +export module M; +export using ::A; +export using ::B; +export using ::C; +export using ::D; + +#if __cpp_concepts >= 201907L +export using ::E; +#endif diff --git a/gcc/testsuite/g++.dg/modules/using-13_b.C b/gcc/testsuite/g++.dg/modules/using-13_b.C new file mode 100644 index 000000000000..49fa09d39ee5 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-13_b.C @@ -0,0 +1,20 @@ +// { dg-additional-options "-fmodules-ts" } + +import M; + +int main() { + A a; + + // Check all specialisations are correctly exported + B b; + B::foo b1; + B::bar b2; + + C c; + + auto d = D; + +#if __cpp_concepts >= 201907L + auto e = E; +#endif +}