diff --git a/gcc/config/i386/winnt-d.c b/gcc/config/i386/winnt-d.c
index b9780258549076c64c9679b1dcacbfd057f9eb17..ea4cd13d0bf6463eb2be145c3548b5d2462b8814 100644
--- a/gcc/config/i386/winnt-d.c
+++ b/gcc/config/i386/winnt-d.c
@@ -78,4 +78,9 @@ winnt_d_register_target_info (void)
 #undef TARGET_D_MINFO_END_NAME
 #define TARGET_D_MINFO_END_NAME "__stop_minfo"
 
+/* Define TARGET_D_TEMPLATES_ALWAYS_COMDAT for Windows targets.  */
+
+#undef TARGET_D_TEMPLATES_ALWAYS_COMDAT
+#define TARGET_D_TEMPLATES_ALWAYS_COMDAT true
+
 struct gcc_targetdm targetdm = TARGETDM_INITIALIZER;
diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def
index aa6bf55e6e691b45dc510f3ea5383479e8f920fe..67647515cf274975e788e9110ec58f126b47096e 100644
--- a/gcc/d/d-target.def
+++ b/gcc/d/d-target.def
@@ -104,5 +104,13 @@ and @var{link_windows} to @code{1} to apply @code{stdcall} to functions with\n\
  bool, (unsigned int *link_system, unsigned int *link_windows),
  hook_bool_uintp_uintp_false)
 
+/* True if instantiations are always COMDAT if they have external linkage.  */
+DEFHOOKPOD
+(d_templates_always_comdat,
+ "This flag is true if instantiated functions and variables are always COMDAT\n\
+if they have external linkage.  If this flag is false, then instantiated\n\
+decls will be emitted as weak symbols.  The default is @code{false}.",
+ bool, false)
+
 /* Close the 'struct gcc_targetdm' definition.  */
 HOOK_VECTOR_END (C90_EMPTY_HACK)
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index c1b6f27514936d5aa0ca016df54f4d014325ae15..bb731a60541dbd92e16019abbc32d1e38072e0d0 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -631,7 +631,6 @@ extern void d_finish_decl (tree);
 extern tree make_thunk (FuncDeclaration *, int);
 extern tree start_function (FuncDeclaration *);
 extern void finish_function (tree);
-extern void mark_needed (tree);
 extern tree get_vtable_decl (ClassDeclaration *);
 extern tree build_new_class_expr (ClassReferenceExp *);
 extern tree aggregate_initializer_decl (AggregateDeclaration *);
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 8948e40e9027e8fb010d10c32ebfdafa49881474..7d1378255bd7b92b282ee49c80a3f81ef210d0cd 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "symtab-thunks.h"
 
 #include "d-tree.h"
+#include "d-target.h"
 
 
 /* Return identifier for the external mangled name of DECL.  */
@@ -1960,8 +1961,8 @@ finish_function (tree old_context)
 /* Mark DECL, which is a VAR_DECL or FUNCTION_DECL as a symbol that
    must be emitted in this, output module.  */
 
-void
-mark_needed (tree decl)
+static void
+d_mark_needed (tree decl)
 {
   TREE_USED (decl) = 1;
 
@@ -2380,6 +2381,18 @@ set_linkage_for_decl (tree decl)
   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
     return d_comdat_linkage (decl);
 
+  /* If all instantiations must go in COMDAT, give them that linkage.
+     This also applies to other extern declarations, so that it is possible
+     for them to override template declarations.  */
+  if (targetdm.d_templates_always_comdat)
+    {
+      /* Make sure that instantiations are not removed.  */
+      if (flag_weak_templates && DECL_INSTANTIATED (decl))
+	d_mark_needed (decl);
+
+      return d_comdat_linkage (decl);
+    }
+
   /* Instantiated variables and functions need to be overridable by any other
      symbol with the same name, so give them weak linkage.  */
   if (DECL_INSTANTIATED (decl))
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 97c8eebcd6f71ce6bae33407a35699d16a612c02..823f85ba9abbaf360b5964e9294801eb72ccf689 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10850,6 +10850,12 @@ and @var{link_windows} to @code{1} to apply @code{stdcall} to functions with
 @code{extern(Windows)} linkage.
 @end deftypefn
 
+@deftypevr {D Target Hook} bool TARGET_D_TEMPLATES_ALWAYS_COMDAT
+This flag is true if instantiated functions and variables are always COMDAT
+if they have external linkage.  If this flag is false, then instantiated
+decls will be emitted as weak symbols.  The default is @code{false}.
+@end deftypevr
+
 @node Named Address Spaces
 @section Adding support for named address spaces
 @cindex named address spaces
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index e2d49ee9f5788dd0dfce1147a63b615f2788eabd..2321a5fc4e02562b6a55e6f3f1afa2e3aee3f4e8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7369,6 +7369,8 @@ floating-point support; they are not included in this mechanism.
 
 @hook TARGET_D_HAS_STDCALL_CONVENTION
 
+@hook TARGET_D_TEMPLATES_ALWAYS_COMDAT
+
 @node Named Address Spaces
 @section Adding support for named address spaces
 @cindex named address spaces