diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index 70745aa4e7c..064645f980d 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -1070,7 +1070,7 @@ c_common_post_options (const char **pfilename)
 
   if (flag_extern_tls_init)
     {
-      if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK)
+      if (!SUPPORTS_WEAK)
 	{
 	  /* Lazy TLS initialization for a variable in another TU requires
 	     alias and weak reference support.  */
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index f95529a5c9a..c6550c0c2fc 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -3672,9 +3672,8 @@ get_tls_init_fn (tree var)
   if (!flag_extern_tls_init && DECL_EXTERNAL (var))
     return NULL_TREE;
 
-  /* If the variable is internal, or if we can't generate aliases,
-     call the local init function directly.  */
-  if (!TREE_PUBLIC (var) || !TARGET_SUPPORTS_ALIASES)
+  /* If the variable is internal call the local init function directly.  */
+  if (!TREE_PUBLIC (var))
     return get_local_tls_init_fn (DECL_SOURCE_LOCATION (var));
 
   tree sname = mangle_tls_init_fn (var);
@@ -3811,8 +3810,12 @@ generate_tls_wrapper (tree fn)
   if (tree init_fn = get_tls_init_fn (var))
     {
       tree if_stmt = NULL_TREE;
-      /* If init_fn is a weakref, make sure it exists before calling.  */
-      if (lookup_attribute ("weak", DECL_ATTRIBUTES (init_fn)))
+
+      /* If init_fn is a weakref, make sure it exists before calling.
+	 If the target does not support aliases, then we will have generated
+	 a dummy weak function, so there is no need to test its existence.  */
+      if (TARGET_SUPPORTS_ALIASES &&
+	  lookup_attribute ("weak", DECL_ATTRIBUTES (init_fn)))
 	{
 	  if_stmt = begin_if_stmt ();
 	  tree addr = cp_build_addr_expr (init_fn, tf_warning_or_error);
@@ -3837,6 +3840,25 @@ generate_tls_wrapper (tree fn)
   expand_or_defer_fn (finish_function (/*inline_p=*/false));
 }
 
+/* A dummy init function to act as a weak placeholder for a (possibly non-
+   existent) dynamic init.  */
+static void
+generate_tls_dummy_init (tree fn)
+{
+  tree var = DECL_BEFRIENDING_CLASSES (fn);
+  tree init_fn = get_tls_init_fn (var);
+  /* If have no init fn, or it is non-weak, then we do not need to make a
+     dummy.  */
+  if (!init_fn || !lookup_attribute ("weak", DECL_ATTRIBUTES (init_fn)))
+    return;
+  start_preparsed_function (init_fn, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
+  tree body = begin_function_body ();
+  declare_weak (init_fn);
+  finish_return_stmt (NULL_TREE);
+  finish_function_body (body);
+  expand_or_defer_fn (finish_function (/*inline_p=*/false));
+}
+
 /* Start a global constructor or destructor function.  */
 
 static tree
@@ -4626,22 +4648,24 @@ handle_tls_init (void)
   finish_expr_stmt (cp_build_modify_expr (loc, guard, NOP_EXPR,
 					  boolean_true_node,
 					  tf_warning_or_error));
+  auto_vec<tree> direct_calls;
   for (; vars; vars = TREE_CHAIN (vars))
     {
       tree var = TREE_VALUE (vars);
       tree init = TREE_PURPOSE (vars);
       one_static_initialization_or_destruction (/*initp=*/true, var, init);
 
-      /* Output init aliases even with -fno-extern-tls-init.  */
-      if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var))
+      /* Output inits even with -fno-extern-tls-init.
+	 We save the list here and output either an alias or a stub function
+	 below.  */
+      if (TREE_PUBLIC (var))
 	{
           tree single_init_fn = get_tls_init_fn (var);
 	  if (single_init_fn == NULL_TREE)
 	    continue;
-	  cgraph_node *alias
-	    = cgraph_node::get_create (fn)->create_same_body_alias
-		(single_init_fn, fn);
-	  gcc_assert (alias != NULL);
+	  if (single_init_fn == fn)
+	    continue;
+	  direct_calls.safe_push (single_init_fn);
 	}
     }
 
@@ -4649,6 +4673,30 @@ handle_tls_init (void)
   finish_if_stmt (if_stmt);
   finish_function_body (body);
   expand_or_defer_fn (finish_function (/*inline_p=*/false));
+
+  /* For each TLS var that we have an init function, we either emit an alias
+     between that and the tls_init, or a stub function that just calls the
+     tls_init.  */
+  while (!direct_calls.is_empty())
+    {
+      tree single_init_fn = direct_calls.pop ();
+      if (TARGET_SUPPORTS_ALIASES)
+	{
+	  cgraph_node *alias
+	     = cgraph_node::get_create (fn)->create_same_body_alias
+		(single_init_fn, fn);
+	  gcc_assert (alias != NULL);
+	}
+      else
+	{
+	  start_preparsed_function (single_init_fn, NULL_TREE, SF_PRE_PARSED);
+	  tree body = begin_function_body ();
+	  tree r = build_call_expr (fn, 0);
+	  finish_expr_stmt (r);
+	  finish_function_body (body);
+	  expand_or_defer_fn (finish_function (/*inline_p=*/false));
+	}
+    }
 }
 
 /* We're at the end of compilation, so generate any mangling aliases that
@@ -5058,7 +5106,15 @@ c_parse_final_cleanups (void)
 	    }
 
 	  if (!DECL_INITIAL (decl) && decl_tls_wrapper_p (decl))
-	    generate_tls_wrapper (decl);
+	    {
+	      generate_tls_wrapper (decl);
+	      if (!TARGET_SUPPORTS_ALIASES)
+	      /* The wrapper might have a weak reference to an init, we provide
+		 a dummy function to satisfy that here.  The linker/dynamic
+		 loader will override this with the actual init, if one is
+		 required.  */
+		generate_tls_dummy_init (decl);
+	    }
 
 	  if (!DECL_SAVED_TREE (decl))
 	    continue;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc b/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc
new file mode 100644
index 00000000000..bd586286647
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc
@@ -0,0 +1,22 @@
+// PR c++/106435
+#include "pr106435.h"
+
+//#include <iostream>
+
+Foo::Foo() {
+  ++num_calls;
+//  std::cout << "Foo::Foo(this=" << this << ")\n";
+}
+
+int Foo::func() {
+//  std::cout << "Foo::func(this=" << this << ")\n";
+  return num_calls;
+}
+
+thread_local Foo Bar::foo;
+thread_local Foo Bar::baz;
+
+thread_local Foo F = Foo{5};
+
+thread_local void* tl = (void*)&F;
+thread_local void* tl1 = nullptr;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr106435.C b/gcc/testsuite/g++.dg/cpp0x/pr106435.C
new file mode 100644
index 00000000000..9071e032697
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr106435.C
@@ -0,0 +1,24 @@
+// PR c++/106435
+// { dg-do run { target c++11 } }
+// { dg-additional-sources "pr106435-b.cc" }
+
+#include "pr106435.h"
+
+int num_calls = 0;
+
+thread_local Foo Bar::bat;
+
+int main() {
+  int v = Bar::foo.func();
+  if (v != 2)
+    __builtin_abort ();
+  v = Bar::bat.func();
+  if (v != 3)
+    __builtin_abort ();
+  if (F.getX() != 5)
+    __builtin_abort();
+  if  (gt_tl () != (void*)&F)
+    __builtin_abort();
+  if  (gt_tl1 ())
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr106435.h b/gcc/testsuite/g++.dg/cpp0x/pr106435.h
new file mode 100644
index 00000000000..06d3e60484f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr106435.h
@@ -0,0 +1,27 @@
+// PR c++/106435
+#pragma once
+
+extern int num_calls;
+struct Foo {
+  Foo();
+  Foo(int _x) : x(_x) {}
+  int func();
+  int getX () { return x; }
+  int x;
+};
+
+struct Bar {
+  thread_local static Foo foo;
+  thread_local static Foo baz;
+  thread_local static Foo bat;
+};
+
+extern thread_local void* tl;
+
+inline void* gt_tl () {return tl;}
+
+extern thread_local Foo F;
+
+extern thread_local void* tl1;
+
+inline void* gt_tl1 () {return tl1;}
