return b ? do_pushdecl_with_scope (x, b) : error_mark_node;
}
+/* Checks if BINDING is a binding that we can export. */
+
+static bool
+check_can_export_using_decl (tree binding)
+{
+ tree decl = STRIP_TEMPLATE (binding);
+
+ /* Linkage is determined by the owner of an enumerator. */
+ if (TREE_CODE (decl) == CONST_DECL)
+ decl = TYPE_NAME (DECL_CONTEXT (decl));
+
+ /* If the using decl is exported, the things it refers
+ to must also be exported (or not have module attachment). */
+ if (!DECL_MODULE_EXPORT_P (decl)
+ && (DECL_LANG_SPECIFIC (decl)
+ && DECL_MODULE_ATTACH_P (decl)))
+ {
+ bool internal_p = !TREE_PUBLIC (decl);
+
+ /* A template in an anonymous namespace doesn't constrain TREE_PUBLIC
+ until it's instantiated, so double-check its context. */
+ if (!internal_p && TREE_CODE (binding) == TEMPLATE_DECL)
+ internal_p = decl_internal_context_p (decl);
+
+ auto_diagnostic_group d;
+ error ("exporting %q#D that does not have external linkage",
+ binding);
+ if (TREE_CODE (decl) == TYPE_DECL && !DECL_IMPLICIT_TYPEDEF_P (decl))
+ /* An un-exported explicit type alias has no linkage. */
+ inform (DECL_SOURCE_LOCATION (binding),
+ "%q#D declared here with no linkage", binding);
+ else if (internal_p)
+ inform (DECL_SOURCE_LOCATION (binding),
+ "%q#D declared here with internal linkage", binding);
+ else
+ inform (DECL_SOURCE_LOCATION (binding),
+ "%q#D declared here with module linkage", binding);
+ return false;
+ }
+
+ return true;
+}
+
/* Process a local-scope or namespace-scope using declaration. LOOKUP
is the result of qualified lookup (both value & type are
significant). FN_SCOPE_P indicates if we're at function-scope (as
tree new_fn = *usings;
bool exporting = revealing_p && module_exporting_p ();
if (exporting)
- {
- /* Module flags for templates are on the template_result. */
- tree decl = STRIP_TEMPLATE (new_fn);
-
- /* If the using decl is exported, the things it refers
- to must also be exported (or not have module attachment). */
- if (!DECL_MODULE_EXPORT_P (decl)
- && (DECL_LANG_SPECIFIC (decl)
- && DECL_MODULE_ATTACH_P (decl)))
- {
- auto_diagnostic_group d;
- error ("%q#D does not have external linkage", new_fn);
- inform (DECL_SOURCE_LOCATION (new_fn),
- "%q#D declared here", new_fn);
- exporting = false;
- }
- }
+ exporting = check_can_export_using_decl (new_fn);
/* [namespace.udecl]
failed = true;
}
else if (insert_p)
- // FIXME:what if we're newly exporting lookup.value
- value = lookup.value;
+ {
+ value = lookup.value;
+ if (revealing_p && module_exporting_p ())
+ check_can_export_using_decl (value);
+ }
/* Now the type binding. */
if (lookup.type && lookup.type != type)
{
- // FIXME: What if we're exporting lookup.type?
if (type && !decls_match (lookup.type, type))
{
diagnose_name_conflict (lookup.type, type);
failed = true;
}
else if (insert_p)
- type = lookup.type;
+ {
+ type = lookup.type;
+ if (revealing_p && module_exporting_p ())
+ check_can_export_using_decl (type);
+ }
}
if (insert_p)
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi !bad }
+
+export module bad;
+
+// internal linkage
+namespace s {
+ namespace {
+ struct a1 {}; // { dg-message "declared here with internal linkage" }
+
+ template <typename T>
+ struct b1; // { dg-message "declared here with internal linkage" }
+
+ int x1; // { dg-message "declared here with internal linkage" }
+
+ template <typename T>
+ T y1; // { dg-message "declared here with internal linkage" }
+
+ void f1(); // { dg-message "declared here with internal linkage" }
+
+ template <typename T>
+ void g1(); // { dg-message "declared here with internal linkage" }
+ }
+}
+
+// module linkage
+namespace m {
+ struct a2 {}; // { dg-message "declared here with module linkage" }
+
+ template <typename T>
+ struct b2; // { dg-message "declared here with module linkage" }
+
+ int x2; // { dg-message "declared here with module linkage" }
+
+ template <typename T>
+ T y2; // { dg-message "declared here with module linkage" }
+
+ void f2(); // { dg-message "declared here with module linkage" }
+
+ template <typename T>
+ void g2(); // { dg-message "declared here with module 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" }
+
+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 <typename T>
+ 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" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+// { dg-module-cmi !bad }
+
+export module bad;
+
+namespace s {
+ namespace {
+ enum e1 { x1 }; // { dg-message "declared here with internal linkage" }
+ enum class e2 { x2 }; // { dg-message "declared here with internal linkage" }
+ }
+}
+
+namespace m {
+ enum e3 { x3 }; // { dg-message "declared here with module linkage" }
+ enum class e4 { x4 }; // { dg-message "declared here with module linkage" }
+}
+
+export using enum s::e1; // { dg-error "does not have external linkage" }
+export using enum s::e2; // { dg-error "does not have external linkage" }
+export using enum m::e3; // { dg-error "does not have external linkage" }
+export using enum m::e4; // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }