diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 8b0f42951c2..8e0fa3c5bfc 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -212,6 +212,7 @@ Classes used:
 #define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
+#include "target.h"
 #include "cp-tree.h"
 #include "timevar.h"
 #include "stringpool.h"
@@ -5620,6 +5621,14 @@ trees_out::core_bools (tree t, bits_out& bits)
 	bool interface_known = t->decl_common.lang_flag_5;
 	if (VAR_P (t) && (DECL_VTABLE_OR_VTT_P (t) || DECL_TINFO_P (t)))
 	  interface_known = false;
+	/* External linkage functions should also be redetermined on
+	   stream-in, except gnu_inline which is always external.  */
+	if (interface_known
+	    && TREE_CODE (t) == FUNCTION_DECL
+	    && TREE_PUBLIC (t)
+	    && !(DECL_DECLARED_INLINE_P (t)
+		 && lookup_attribute("gnu_inline", DECL_ATTRIBUTES (t))))
+	  interface_known = false;
 	WB (interface_known);
       }
 
@@ -16417,12 +16426,7 @@ module_state::read_cluster (unsigned snum)
 	  cfun->returns_pcc_struct = aggr;
 #endif
 	  cfun->returns_struct = aggr;
-
-	  if (DECL_COMDAT (decl))
-	    // FIXME: Comdat grouping?
-	    comdat_linkage (decl);
-	  note_vague_linkage_fn (decl);
-	  cgraph_node::finalize_function (decl, true);
+	  expand_or_defer_fn (decl);
 	}
 
     }
@@ -18901,22 +18905,7 @@ post_load_processing ()
       dump () && dump ("Post-load processing of %N", decl);
 
       gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl));
-
-      if (DECL_COMDAT (decl))
-	comdat_linkage (decl);
-      if (!TREE_ASM_WRITTEN (decl))
-	{
-	  /* Cloning can cause loading -- specifically operator delete for
-	     the deleting dtor.  */
-	  if (maybe_clone_body (decl))
-	    TREE_ASM_WRITTEN (decl) = 1;
-	  else
-	    {
-	      /* We didn't clone the cdtor, make sure we emit it.  */
-	      note_vague_linkage_fn (decl);
-	      cgraph_node::finalize_function (decl, true);
-	    }
-	}
+      expand_or_defer_fn (decl);
     }
 
   cfun = old_cfun;
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 7c7d3e3c432..914502abe7a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -5504,7 +5504,7 @@ expand_or_defer_fn_1 (tree fn)
 	 need it anymore.  */
       if (!DECL_DECLARED_CONSTEXPR_P (fn)
 	  && !(module_maybe_has_cmi_p () && vague_linkage_p (fn)))
-	DECL_SAVED_TREE (fn) = NULL_TREE;
+	DECL_SAVED_TREE (fn) = void_node;
       return false;
     }
 
diff --git a/gcc/testsuite/g++.dg/modules/pr119154_a.C b/gcc/testsuite/g++.dg/modules/pr119154_a.C
new file mode 100644
index 00000000000..23bd186fe19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119154_a.C
@@ -0,0 +1,6 @@
+// PR c++/119154
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi foo }
+
+export module foo;
+extern "C++" inline __attribute__((__gnu_inline__)) void bar() {}
diff --git a/gcc/testsuite/g++.dg/modules/pr119154_b.C b/gcc/testsuite/g++.dg/modules/pr119154_b.C
new file mode 100644
index 00000000000..1558e717761
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119154_b.C
@@ -0,0 +1,10 @@
+// PR c++/119154
+// { dg-module-do link }
+// { dg-additional-options "-fmodules" }
+
+void bar();
+import foo;
+
+int main() {
+  bar();
+}
