Index: lib/asan/asan_globals.cc
===================================================================
--- lib/asan/asan_globals.cc	(revision 162207)
+++ lib/asan/asan_globals.cc	(working copy)
@@ -28,11 +28,18 @@
 struct ListOfGlobals {
   const Global *g;
   ListOfGlobals *next;
+  ListOfGlobals *next_dynamic;
+    // The next dynamically initialized global variable.
+  ListOfGlobals *padding;
+  // Size of this struct must be a power of two.
 };
 
 static AsanLock mu_for_globals(LINKER_INITIALIZED);
+static LowLevelAllocator allocator_for_globals(LINKER_INITIALIZED);
 static ListOfGlobals *list_of_globals;
-static LowLevelAllocator allocator_for_globals(LINKER_INITIALIZED);
+// Note that list_of_globals must be populated in LIFO order in each TU, such
+// that the first element in the list is the last global defined in a TU, and
+// the last element in the list is the first global defined in a TU.
 
 void PoisonRedZones(const Global &g)  {
   uptr shadow_rz_size = kGlobalAndStackRedzone >> SHADOW_SCALE;
@@ -76,7 +83,7 @@
 // Register a global variable.
 // This function may be called more than once for every global
 // so we store the globals in a map.
-static void RegisterGlobal(const Global *g) {
+static void RegisterGlobal(Global *g) {
   CHECK(asan_inited);
   CHECK(flags()->report_globals);
   CHECK(AddrIsInMem(g->beg));
@@ -87,6 +94,11 @@
       (ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals));
   l->g = g;
   l->next = list_of_globals;
+  // If the next global isn't dynamic, skip over it.
+  if (list_of_globals && !list_of_globals->g->next_dynamic)
+    l->next_dynamic = list_of_globals->next_dynamic;
+  else
+    l->next_dynamic = list_of_globals;
   list_of_globals = l;
   if (flags()->report_globals >= 2)
     Report("Added Global: beg=%p size=%zu name=%s\n",
@@ -105,6 +117,26 @@
   // implementation. It might not be worth doing anyway.
 }
 
+// Poison all shadow memory for a single global.
+static void PoisonGlobalAndRedzones(const Global *g) {
+  CHECK(asan_inited);
+  CHECK(flags()->check_initialization_order);
+  CHECK(AddrIsInMem(g->beg));
+  CHECK(AddrIsAlignedByGranularity(g->beg));
+  CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+  PoisonShadow(g->beg, g->size_with_redzone, kAsanInitializationOrderMagic);
+}
+
+static void UnpoisonGlobal(const Global *g) {
+  CHECK(asan_inited);
+  CHECK(flags()->check_initialization_order);
+  CHECK(AddrIsInMem(g->beg));
+  CHECK(AddrIsAlignedByGranularity(g->beg));
+  CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+  PoisonShadow(g->beg, g->size_with_redzone, 0);
+  PoisonRedZones(*g);
+}
+
 }  // namespace __asan
 
 // ---------------------- Interface ---------------- {{{1
@@ -133,7 +165,7 @@
 }
 
 // Unregister an array of globals.
-// We must do it when a shared objects gets dlclosed.
+// We must do this when a shared objects gets dlclosed.
 void __asan_unregister_globals(__asan_global *globals, uptr n) {
   if (!flags()->report_globals) return;
   ScopedLock lock(&mu_for_globals);
@@ -141,3 +173,45 @@
     UnregisterGlobal(&globals[i]);
   }
 }
+
+// This method runs immediately prior to dynamic initialization in each TU,
+// when all dynamically initialized globals are unpoisoned.  This method
+// poisons all global variables not defined in this TU, so that a dynamic
+// initializer can only touch global variables in the same TU.
+void __asan_before_dynamic_init(uptr first_addr, uptr last_addr) {
+  if (!flags()->check_initialization_order) return;
+  ScopedLock lock(&mu_for_globals);
+
+  ListOfGlobals *l = list_of_globals;
+  // Don't accidentally poison a global just because it was first on the list.
+  if (l->g->next_dynamic == 0)
+    l = l->next_dynamic;
+  bool global_is_in_this_tu = false;
+  for (; l; l = l->next_dynamic) {
+    const Global *g = l->g;
+    if (g->beg == last_addr)
+      global_is_in_this_tu = true;
+    if (!global_is_in_this_tu)
+      PoisonGlobalAndRedzones(g);
+    if (g->beg == first_addr)
+      global_is_in_this_tu = false;
+  }
+  CHECK(!global_is_in_this_tu);
+}
+
+// This method runs immediately after dynamic initialization in each TU, when
+// all dynamically initialized globals except for those defined in the current
+// TU are poisoned.  It simply unpoisons all dynamically initialized global
+// variables.
+void __asan_after_dynamic_init() {
+  if (!flags()->check_initialization_order) return;
+  ScopedLock lock(&mu_for_globals);
+
+  ListOfGlobals *l = list_of_globals;
+  // Don't accidentally poison a global just because it was first on the list.
+  if (l->g->next_dynamic == 0)
+    l = l->next_dynamic;
+  for (; l; l = l->next_dynamic) {
+    UnpoisonGlobal(l->g);
+  }
+}
Index: lib/asan/asan_flags.h
===================================================================
--- lib/asan/asan_flags.h	(revision 162207)
+++ lib/asan/asan_flags.h	(working copy)
@@ -43,6 +43,8 @@
   // on globals, 1 - detect buffer overflow, 2 - print data about registered
   // globals).
   int  report_globals;
+  // If set, attempts to catch initialization order issues.
+  bool check_initialization_order;
   // Max number of stack frames kept for each allocation.
   int  malloc_context_size;
   // If set, uses custom wrappers and replacements for libc string functions
Index: lib/asan/asan_linux.cc
===================================================================
--- lib/asan/asan_linux.cc	(revision 162207)
+++ lib/asan/asan_linux.cc	(working copy)
@@ -13,13 +13,6 @@
 //===----------------------------------------------------------------------===//
 #ifdef __linux__
 
-#include "asan_interceptors.h"
-#include "asan_internal.h"
-#include "asan_lock.h"
-#include "asan_thread.h"
-#include "sanitizer_common/sanitizer_libc.h"
-#include "sanitizer_common/sanitizer_procmaps.h"
-
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/mman.h>
@@ -36,6 +29,13 @@
 #include <sys/ucontext.h>
 #endif
 
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_lock.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
 extern "C" void* _DYNAMIC;
 
 namespace __asan {
Index: lib/asan/asan_interface.h
===================================================================
--- lib/asan/asan_interface.h	(revision 162207)
+++ lib/asan/asan_interface.h	(working copy)
@@ -38,6 +38,10 @@
     uptr size;               // The original size of the global.
     uptr size_with_redzone;  // The size with the redzone.
     const char *name;          // Name as a C string.
+    __asan_global *next_dynamic;
+      // 1 if the variables has dynamic initialization, 0 otherwise.  This
+      // field is reused in runtime to keep a list of dynamically initialized
+      // globals.
   };
 
   // These two functions should be called by the instrumented code.
@@ -47,6 +51,14 @@
   void __asan_unregister_globals(__asan_global *globals, uptr n)
       SANITIZER_INTERFACE_ATTRIBUTE;
 
+  // These two functions should be called before and after dynamic initializers
+  // run, respectively.  They should be called with parameters describing all
+  // dynamically initialized globals defined in the calling TU.
+  void __asan_before_dynamic_init(uptr first_addr, uptr last_addr)
+      SANITIZER_INTERFACE_ATTRIBUTE;
+  void __asan_after_dynamic_init()
+      SANITIZER_INTERFACE_ATTRIBUTE;
+
   // These two functions are used by the instrumented code in the
   // use-after-return mode. __asan_stack_malloc allocates size bytes of
   // fake stack and __asan_stack_free poisons it. real_stack is a pointer to
Index: lib/asan/output_tests/initialization-nobug.cc
===================================================================
--- lib/asan/output_tests/initialization-nobug.cc	(revision 0)
+++ lib/asan/output_tests/initialization-nobug.cc	(revision 0)
@@ -0,0 +1,76 @@
+// A collection of various initializers which shouldn't trip up initialization
+// order checking.  If main is reached, we know that all of our initializers
+// ran to completion
+
+#include <iostream>
+
+/*============================================================================*/
+// Simple access:
+// Make sure that accessing a global in the same TU is safe
+
+bool condition = true;
+int initializeSameTU() {
+  if (condition)
+    return 0x2a;
+  else
+    return 052;
+}
+int sameTU = initializeSameTU();
+
+/*============================================================================*/
+// Initialize std::cout
+// Check that we don't error on access to std::cout if an object of type
+// ios_base::Init has been initialized.
+int initializeCheckCout(){
+  std::ios_base::Init initilizeCout;
+  std::cout << "Checking std::cout in initializers..." << std::endl;
+  return 7 * 3 * 2;
+}
+int checkCout = initializeCheckCout();
+
+/*============================================================================*/
+// Linker initialized:
+// Check that access to linker initialized globals originating from a different
+// TU's initializer is safe.
+
+int A = (1 << 1) + (1 << 3) + (1 << 5);
+int B;
+int getAB() {
+  return A * B;
+}
+
+/*============================================================================*/
+// Function local statics:
+// Check that access to function local statics originating from a different
+// TU's initializer is safe.
+
+int countCalls(){
+  static int calls;
+  return ++calls;
+}
+
+/*============================================================================*/
+// Constexpr:
+// We need to check that a static global variable initialized with a constexpr 
+// constructor can be accessed during dynamic initialization (as a constexpr 
+// constructor implies that it was initialized during constant initialization,
+// not dynamic initialization).
+
+class Integer {
+  private:
+  int value;
+
+  public:
+  constexpr Integer(int x = 0) : value(x) {}
+  int getValue() {return value;}
+};
+Integer coolestInteger(42);
+int getCoolestInteger(){
+  return coolestInteger.getValue();
+}
+
+int main() {
+  std::cout << "We made it to main, hooray!" << std::endl;
+  // Check-Common: We made it to main, hooray!
+  return 0;
+}
Index: lib/asan/output_tests/initialization-bug-logging-extra.cc
===================================================================
--- lib/asan/output_tests/initialization-bug-logging-extra.cc	(revision 0)
+++ lib/asan/output_tests/initialization-bug-logging-extra.cc	(revision 0)
@@ -0,0 +1,8 @@
+#include <cstdio>
+// 'output' will be initialized dynamically, implying the possibility of
+// initialization order issues
+static FILE* output = stdout;
+
+void logEvent(const char* msg) {
+  fprintf(output, "LOG: %s\n", msg);
+}
Index: lib/asan/output_tests/memcmp_test.cc
===================================================================
--- lib/asan/output_tests/memcmp_test.cc	(revision 162207)
+++ lib/asan/output_tests/memcmp_test.cc	(working copy)
@@ -1,7 +1,7 @@
 #include <string.h>
 int main(int argc, char **argv) {
-  char a1[] = {argc, 2, 3, 4};
-  char a2[] = {1, 2*argc, 3, 4};
+  char a1[] = {static_cast<char>(argc), 2, 3, 4};
+  char a2[] = {1, static_cast<char>(2*argc), 3, 4};
 // Check-Common: AddressSanitizer stack-buffer-overflow
 // Check-Common: {{#0.*memcmp}}
 // Check-Common: {{#1.*main}}
Index: lib/asan/output_tests/initialization-nobug-extra.cc
===================================================================
--- lib/asan/output_tests/initialization-nobug-extra.cc	(revision 0)
+++ lib/asan/output_tests/initialization-nobug-extra.cc	(revision 0)
@@ -0,0 +1,16 @@
+// Linker initialized:
+int getAB();
+static int ab = getAB();
+
+// Function local statics:
+int countCalls();
+static int one   = countCalls();
+static int two   = countCalls();
+static int three = countCalls();
+
+//Constexpr:
+int getCoolestInteger();
+int getExternCoolestInteger() {
+  return getCoolestInteger();
+}
+static int coolest_integer = getExternCoolestInteger();
Index: lib/asan/output_tests/test_output.sh
===================================================================
--- lib/asan/output_tests/test_output.sh	(revision 162207)
+++ lib/asan/output_tests/test_output.sh	(working copy)
@@ -68,6 +68,9 @@
       if [[ "$c" == *"-so" ]]; then
         continue
       fi
+      if [[ "$c" == *"-extra" ]]; then
+        continue
+      fi
       if [[ "$c" == *"-linux" ]]; then
         if [[ "$OS" != "Linux" ]]; then
           continue
@@ -77,10 +80,18 @@
       exe=$c.$b.O$O
       so=$c.$b.O$O-so.so
       echo testing $exe
-      build_command="$CXX $CXXFLAGS -m$b -faddress-sanitizer -O$O $c.cc -o $exe"
+      if [[ -e "$c-extra.cc" ]]
+      then
+        sources="$c.cc $c-extra.cc"
+      else
+        sources="$c.cc"
+      fi
+      asan_flags="-faddress-sanitizer -mllvm -asan-initialization-order"
+      asan_flags="${asan_flags} -m$b -O$O --std=c++11"
+      build_command="$CXX $CXXFLAGS $asan_flags $sources -o $exe"
       [ "$DEBUG" == "1" ] && echo $build_command
       $build_command
-      [ -e "$c_so.cc" ] && $CXX $CXXFLAGS -m$b -faddress-sanitizer -O$O $c_so.cc -fPIC -shared -o $so
+      [ -e "$c_so.cc" ] && $CXX $CXXFLAGS $asan_flags $c_so.cc -fPIC -shared -o $so
       run_program $exe
       # Check common expected lines for OS.
       $FILE_CHECK $c.cc --check-prefix="Check-Common" < $TMP_ASAN_REPORT
Index: lib/asan/output_tests/initialization-bug-logging.cc
===================================================================
--- lib/asan/output_tests/initialization-bug-logging.cc	(revision 0)
+++ lib/asan/output_tests/initialization-bug-logging.cc	(revision 0)
@@ -0,0 +1,42 @@
+void logEvent(const char* msg);
+
+// If 'initializeX' is called from a dynamic initializer, it will either work
+// correctly or segfault, depending on the unspecified order dynamic
+// initializers run in .
+int __attribute__((noinline)) initializeX() {
+  logEvent("Preparing to return 5...");
+  // Check-Common: {{AddressSanitizer initialization-order-fiasco}}
+  // Check-Common: {{READ of size .* at 0x.* thread T0}}
+  // Check-Common: {{#0 0x.* in .*logEvent.* .*initialization-bug-logging-extra.cc:7}}
+  // Check-Common: {{#1 0x.* in .*initializeX.* .*initialization-bug-logging.cc:7}}
+  // Check-Common: {{0x.* is located 0 bytes inside of global variable}}
+  // Check-Common: {{.*output.*}}
+  return 5;
+}
+
+// Examples of safe initialization.
+static const int safe_1 = 42;
+char initializeSafe2() {
+  return '*';
+}
+char safe_2 = initializeSafe2();
+
+// This initializer begins our initialization order problems.
+static int x = initializeX();
+
+// More safe initialization.
+const float safe_3 = 42.0f;
+double initializeSafe4() {
+  // Initializers run top to bottom; this shouldn't print.
+  logEvent("More logging!");
+  // CHECK-NOT: More logging!
+  return 84/2.0;
+}
+static double safe_4 = initializeSafe4();
+
+// ASan should have caused an exit before main runs.
+int main() {
+  logEvent("Our program is now running");
+  // CHECK-NOT: Our program is now running
+  return 0;
+}
Index: lib/asan/asan_rtl.cc
===================================================================
--- lib/asan/asan_rtl.cc	(revision 162207)
+++ lib/asan/asan_rtl.cc	(working copy)
@@ -79,6 +79,7 @@
 
   ParseFlag(str, &f->debug, "debug");
   ParseFlag(str, &f->report_globals, "report_globals");
+  ParseFlag(str, &f->check_initialization_order, "initialization_order");
   ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
   CHECK(f->malloc_context_size <= kMallocContextSize);
 
@@ -116,6 +117,7 @@
   f->redzone = (ASAN_LOW_MEMORY) ? 64 : 128;
   f->debug = false;
   f->report_globals = 1;
+  f->check_initialization_order = true;
   f->malloc_context_size = kMallocContextSize;
   f->replace_str = true;
   f->replace_intrin = true;
Index: lib/asan/asan_poisoning.cc
===================================================================
--- lib/asan/asan_poisoning.cc	(revision 162207)
+++ lib/asan/asan_poisoning.cc	(working copy)
@@ -24,7 +24,7 @@
   CHECK(AddrIsAlignedByGranularity(addr + size));
   uptr shadow_beg = MemToShadow(addr);
   uptr shadow_end = MemToShadow(addr + size);
-  CHECK(REAL(memset) != 0);
+  CHECK_NE(REAL(memset), 0);
   REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
 }
 
Index: lib/asan/asan_report.cc
===================================================================
--- lib/asan/asan_report.cc	(revision 162207)
+++ lib/asan/asan_report.cc	(working copy)
@@ -371,6 +371,9 @@
       case kAsanStackLeftRedzoneMagic:
         bug_descr = "stack-buffer-underflow";
         break;
+      case kAsanInitializationOrderMagic:
+        bug_descr = "initialization-order-fiasco";
+        break;
       case kAsanStackMidRedzoneMagic:
       case kAsanStackRightRedzoneMagic:
       case kAsanStackPartialRedzoneMagic:
Index: lib/asan/asan_internal.h
===================================================================
--- lib/asan/asan_internal.h	(revision 162207)
+++ lib/asan/asan_internal.h	(working copy)
@@ -171,6 +171,7 @@
 const int kAsanStackRightRedzoneMagic = 0xf3;
 const int kAsanStackPartialRedzoneMagic = 0xf4;
 const int kAsanStackAfterReturnMagic = 0xf5;
+const int kAsanInitializationOrderMagic = 0xf6;
 const int kAsanUserPoisonedMemoryMagic = 0xf7;
 const int kAsanGlobalRedzoneMagic = 0xf9;
 const int kAsanInternalHeapMagic = 0xfe;
