diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 59716e1873e..21251f98a35 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -13332,6 +13332,14 @@ depset::hash::is_tu_local_entity (tree decl, bool explain/*=false*/)
 {
   gcc_checking_assert (DECL_P (decl));
 
+  /* Only types, functions, variables, and template (specialisations)
+     can be TU-local.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != FUNCTION_DECL
+      && TREE_CODE (decl) != VAR_DECL
+      && TREE_CODE (decl) != TEMPLATE_DECL)
+    return false;
+
   /* An explicit type alias is not an entity, and so is never TU-local.
      Neither are the built-in declarations of 'int' and such.  */
   if (TREE_CODE (decl) == TYPE_DECL
@@ -16433,8 +16441,9 @@ module_state::write_namespaces (elf_out *to, vec<depset *> spaces,
       depset *b = spaces[ix];
       tree ns = b->get_entity ();
 
+      /* This could be an anonymous namespace even for a named module,
+	 since we can still emit no-linkage decls.  */
       gcc_checking_assert (TREE_CODE (ns) == NAMESPACE_DECL);
-      gcc_checking_assert (TREE_PUBLIC (ns) || header_module_p ());
 
       unsigned flags = 0;
       if (TREE_PUBLIC (ns))
@@ -20394,13 +20403,25 @@ check_module_decl_linkage (tree decl)
   /* An internal-linkage declaration cannot be generally be exported.
      But it's OK to export any declaration from a header unit, including
      internal linkage declarations.  */
-  if (!header_module_p ()
-      && DECL_MODULE_EXPORT_P (decl)
-      && decl_linkage (decl) == lk_internal)
+  if (!header_module_p () && DECL_MODULE_EXPORT_P (decl))
     {
-      error_at (DECL_SOURCE_LOCATION (decl),
-		"exporting declaration %qD with internal linkage", decl);
-      DECL_MODULE_EXPORT_P (decl) = false;
+      /* Let's additionally treat any exported declaration within an
+	 internal namespace as exporting a declaration with internal
+	 linkage, as this would implicitly also export the internal
+	 linkage namespace.  */
+      if (decl_internal_context_p (decl))
+	{
+	  error_at (DECL_SOURCE_LOCATION (decl),
+		    "exporting declaration %qD declared in unnamed namespace",
+		    decl);
+	  DECL_MODULE_EXPORT_P (decl) = false;
+	}
+      else if (decl_linkage (decl) == lk_internal)
+	{
+	  error_at (DECL_SOURCE_LOCATION (decl),
+		    "exporting declaration %qD with internal linkage", decl);
+	  DECL_MODULE_EXPORT_P (decl) = false;
+	}
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/modules/export-6.C b/gcc/testsuite/g++.dg/modules/export-6.C
index 460cdf08ea9..af54e5fbe87 100644
--- a/gcc/testsuite/g++.dg/modules/export-6.C
+++ b/gcc/testsuite/g++.dg/modules/export-6.C
@@ -16,27 +16,32 @@ export static auto [d] = S{};  // { dg-error "internal linkage" "" { target c++2
 #endif
 
 namespace {
-  export int y = 456;  // { dg-error "internal linkage" }
-  export void h();  // { dg-error "internal linkage" }
-  export void i() {}  // { dg-error "internal linkage" }
-  export template <typename T> void v(); // { dg-error "internal linkage" }
-  export template <typename T> void w() {} // { dg-error "internal linkage" }
-  export auto [e] = S{};  // { dg-error "internal linkage" }
+  export int y = 456;  // { dg-error "exporting" }
+  export void h();  // { dg-error "exporting" }
+  export void i() {}  // { dg-error "exporting" }
+  export template <typename T> void v(); // { dg-error "exporting" }
+  export template <typename T> void w() {} // { dg-error "exporting" }
+  export auto [e] = S{};  // { dg-error "exporting" }
 
-  export namespace ns {}  // { dg-error "internal linkage" }
-  export namespace alias = global;  // { dg-error "internal linkage" }
+  export namespace ns {}  // { dg-error "exporting" }
+  export namespace alias = global;  // { dg-error "exporting" }
 
-  export struct A {};  // { dg-error "internal linkage" }
-  export template <typename T> struct B {};  // { dg-error "internal linkage" }
+  export struct A {};  // { dg-error "exporting" }
+  export template <typename T> struct B {};  // { dg-error "exporting" }
 
-  export enum E {};  // { dg-error "internal linkage" }
-  export enum class F {};  // { dg-error "internal linkage" }
+  export enum E {};  // { dg-error "exporting" }
+  export enum class F {};  // { dg-error "exporting" }
 
-  export template <typename T> using U = int;  // { dg-error "internal linkage" }
+  export template <typename T> using U = int;  // { dg-error "exporting" }
 
 #if __cplusplus >= 202002L
-  export template <typename T> concept C = true;  // { dg-error "internal linkage" "" { target c++20 } }
+  export template <typename T> concept C = true;  // { dg-error "exporting" "" { target c++20 } }
 #endif
+
+  // Also complain about exporting no-linkage decls in an unnamed namespace
+  export typedef int T;  // { dg-error "exporting" }
+  export typedef struct {} *PC;  // { dg-error "exporting" }
+  export using V = int;  // { dg-error "exporting" }
 }
 
 export namespace {}  // { dg-error "exporting unnamed namespace" }
diff --git a/gcc/testsuite/g++.dg/modules/internal-4_b.C b/gcc/testsuite/g++.dg/modules/internal-4_b.C
index 81fc65a69bd..7e4fbfeb1fb 100644
--- a/gcc/testsuite/g++.dg/modules/internal-4_b.C
+++ b/gcc/testsuite/g++.dg/modules/internal-4_b.C
@@ -32,8 +32,8 @@ inline void expose_header_decl() {  // { dg-error "exposes TU-local entity" }
   header_f();
 }
 
-// We additionally consider a namespace with internal linkage as TU-local
-namespace expose_ns = internal_ns;  // { dg-error "exposes TU-local entity" }
+// A namespace with internal linkage is not inherently an exposure.
+namespace expose_ns = internal_ns;  // { dg-bogus "exposes TU-local entity" }
 
 // But we don't consider a weakref as being TU-local, despite being
 // marked static; this is to support uses of weakrefs in header files
diff --git a/gcc/testsuite/g++.dg/modules/using-30_a.C b/gcc/testsuite/g++.dg/modules/using-30_a.C
new file mode 100644
index 00000000000..fc6a67f2bae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-30_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+
+namespace {
+  using A = int;
+  typedef int B;
+}
diff --git a/gcc/testsuite/g++.dg/modules/using-30_b.C b/gcc/testsuite/g++.dg/modules/using-30_b.C
new file mode 100644
index 00000000000..ba06c9de792
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-30_b.C
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodules" }
+
+module M;
+
+A x;
+B y;
diff --git a/gcc/testsuite/g++.dg/modules/using-30_c.C b/gcc/testsuite/g++.dg/modules/using-30_c.C
new file mode 100644
index 00000000000..34dc6f2c98d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-30_c.C
@@ -0,0 +1,13 @@
+// { dg-additional-options "-fmodules" }
+// The different declarations in the anonymous namespace shouldn't clash with
+// those in M.
+
+namespace {
+  using A = double;
+  typedef double B;
+}
+import M;
+int main() {
+  A a = 1.0;
+  B b = 2.0;
+}
