Index: cmake/config-ix.cmake
===================================================================
--- cmake/config-ix.cmake
+++ cmake/config-ix.cmake
@@ -203,6 +203,7 @@
 set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
 set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64}
     ${MIPS32} ${MIPS64} ${S390X})
+set(ALL_TYSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
 set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
 set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}
     ${MIPS32} ${MIPS64} ${PPC64} ${S390X})
@@ -393,6 +394,9 @@
   list_intersect(PROFILE_SUPPORTED_ARCH
     ALL_PROFILE_SUPPORTED_ARCH
     SANITIZER_COMMON_SUPPORTED_ARCH)
+  list_intersect(TYSAN_SUPPORTED_ARCH
+    ALL_TYSAN_SUPPORTED_ARCH
+    SANITIZER_COMMON_SUPPORTED_ARCH)
   list_intersect(TSAN_SUPPORTED_ARCH
     ALL_TSAN_SUPPORTED_ARCH
     SANITIZER_COMMON_SUPPORTED_ARCH)
@@ -429,6 +433,7 @@
   filter_available_targets(LSAN_SUPPORTED_ARCH ${ALL_LSAN_SUPPORTED_ARCH})
   filter_available_targets(MSAN_SUPPORTED_ARCH ${ALL_MSAN_SUPPORTED_ARCH})
   filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH})
+  filter_available_targets(TYSAN_SUPPORTED_ARCH ${ALL_TYSAN_SUPPORTED_ARCH})
   filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH})
   filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH})
   filter_available_targets(SAFESTACK_SUPPORTED_ARCH
@@ -464,7 +469,7 @@
   set(OS_NAME "${CMAKE_SYSTEM_NAME}")
 endif()
 
-set(ALL_SANITIZERS asan;dfsan;msan;tsan;safestack;cfi;esan;scudo)
+set(ALL_SANITIZERS asan;dfsan;msan;tysan;tsan;safestack;cfi;esan;scudo)
 set(COMPILER_RT_SANITIZERS_TO_BUILD ${ALL_SANITIZERS} CACHE STRING
     "sanitizers to build if supported on the target (all;${ALL_SANITIZERS})")
 list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}")
@@ -525,6 +530,13 @@
   set(COMPILER_RT_HAS_PROFILE FALSE)
 endif()
 
+if (COMPILER_RT_HAS_SANITIZER_COMMON AND TYSAN_SUPPORTED_ARCH AND
+    OS_NAME MATCHES "Linux")
+  set(COMPILER_RT_HAS_TYSAN TRUE)
+else()
+  set(COMPILER_RT_HAS_TYSAN FALSE)
+endif()
+
 if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
     OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android")
   set(COMPILER_RT_HAS_TSAN TRUE)
Index: lib/tysan/CMakeLists.txt
===================================================================
--- /dev/null
+++ lib/tysan/CMakeLists.txt
@@ -0,0 +1,33 @@
+include_directories(..)
+
+# Runtime library sources and build flags.
+set(TYSAN_RTL_SOURCES
+  tysan.cc
+  tysan_interceptors.cc)
+set(TYSAN_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+append_rtti_flag(OFF TYSAN_COMMON_CFLAGS)
+# Prevent clang from generating libc calls.
+append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding TYSAN_COMMON_CFLAGS)
+
+# Static runtime library.
+add_compiler_rt_component(tysan)
+
+foreach(arch ${TYSAN_SUPPORTED_ARCH})
+  set(TYSAN_CFLAGS ${TYSAN_COMMON_CFLAGS})
+  append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE TYSAN_CFLAGS)
+  add_compiler_rt_runtime(clang_rt.tysan
+    STATIC
+    ARCHS ${arch}
+    SOURCES ${TYSAN_RTL_SOURCES}
+            $<TARGET_OBJECTS:RTInterception.${arch}>
+            $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
+            $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
+    CFLAGS ${TYSAN_CFLAGS}
+    PARENT_TARGET tysan)
+  add_sanitizer_rt_symbols(clang_rt.tysan
+    ARCHS ${arch}
+    EXTRA tysan.syms.extra)
+  add_dependencies(tysan
+    clang_rt.tysan-${arch}-symbols)
+endforeach()
+
Index: lib/tysan/tysan.h
===================================================================
--- /dev/null
+++ lib/tysan/tysan.h
@@ -0,0 +1,85 @@
+//===-- tysan.h -------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+// Private TySan header.
+//===----------------------------------------------------------------------===//
+
+#ifndef TYSAN_H
+#define TYSAN_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+using __sanitizer::uptr;
+using __sanitizer::sptr;
+using __sanitizer::u16;
+
+#include "tysan_platform.h"
+
+extern "C" {
+void tysan_set_type_unknown(const void *addr, uptr size);
+void tysan_copy_types(const void *daddr, const void *saddr, uptr size);
+}
+
+namespace __tysan {
+extern bool tysan_inited;
+extern bool tysan_init_is_running;
+
+void InitializeInterceptors();
+
+enum {
+  TYSAN_MEMBER_TD = 1,
+  TYSAN_STRUCT_TD = 2
+};
+
+struct tysan_member_type_descriptor {
+  struct tysan_type_descriptor *Base;
+  struct tysan_type_descriptor *Access;
+  uptr Offset;
+};
+
+struct tysan_struct_type_descriptor {
+  uptr MemberCount;
+  struct {
+    struct tysan_type_descriptor *Type;
+    uptr Offset;
+  } Members[1]; // Tail allocated.
+  // char Name[]; // Tail allocated.
+};
+
+struct tysan_type_descriptor {
+  uptr Tag;
+  union {
+    tysan_member_type_descriptor Member;
+    tysan_struct_type_descriptor Struct;
+  };
+};
+
+inline tysan_type_descriptor **shadow_for(const void *ptr) {
+  return (tysan_type_descriptor **)
+    ((((uptr) ptr) & AppMask())*sizeof(ptr) + ShadowAddr());
+}
+
+struct Flags {
+#define TYSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "tysan_flags.inc"
+#undef TYSAN_FLAG
+
+  void SetDefaults();
+};
+
+extern Flags flags_data;
+inline Flags &flags() {
+  return flags_data;
+}
+
+}  // namespace __tysan
+
+#endif  // TYSAN_H
Index: lib/tysan/tysan.cc
===================================================================
--- /dev/null
+++ lib/tysan/tysan.cc
@@ -0,0 +1,341 @@
+//===-- tysan.cc --------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+// TypeSanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+#include "tysan/tysan.h"
+
+using namespace __sanitizer;
+using namespace __tysan;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void tysan_set_type_unknown(const void *addr, uptr size) {
+  internal_memset(shadow_for(addr), 0, size*sizeof(uptr));
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void tysan_copy_types(const void *daddr, const void *saddr, uptr size) {
+  internal_memmove(shadow_for(daddr), shadow_for(saddr), size*sizeof(uptr));
+}
+
+static const char *getDisplayName(const char *Name) {
+  if (Name[0] == '\0')
+    return "<anonymous type>";
+
+  // Clang generates tags for C++ types that demangle as typeinfo. Remove the
+  // prefix from the generated string.
+  const char TIPrefix[] = "typeinfo name for ";
+
+  const char *DName = Symbolizer::GetOrInit()->Demangle(Name);
+  if (!internal_strncmp(DName, TIPrefix, sizeof(TIPrefix) - 1))
+    DName += sizeof(TIPrefix) - 1;
+
+  return DName;
+}
+
+static void printTDName(tysan_type_descriptor *td) {
+  if (((sptr) td) <= 0) {
+    Printf("<unknown type>");
+    return;
+  }
+
+  switch (td->Tag) {
+  default:
+    DCHECK(0);
+    break;
+  case TYSAN_MEMBER_TD:
+    printTDName(td->Member.Access);
+    if (td->Member.Access != td->Member.Base) {
+      Printf(" (in ");
+      printTDName(td->Member.Base);
+      Printf(" at offset %u)", td->Member.Offset);
+    }
+    break;
+  case TYSAN_STRUCT_TD:
+    Printf("%s", getDisplayName((char *) (td->Struct.Members +
+                                          td->Struct.MemberCount)));
+    break;
+  } 
+}
+
+static tysan_type_descriptor *getRootTD(tysan_type_descriptor *TD) {
+  tysan_type_descriptor *RootTD = TD;
+
+  do {
+    RootTD = TD;
+
+    if (TD->Tag == TYSAN_STRUCT_TD) {
+      if (TD->Struct.MemberCount > 0)
+        TD = TD->Struct.Members[0].Type;
+      else
+        TD = nullptr;
+    } else if (TD->Tag == TYSAN_MEMBER_TD) {
+      TD = TD->Member.Access;
+    } else {
+      DCHECK(0);
+      break;
+    }
+  } while (TD);
+
+  return RootTD;
+}
+
+static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
+                              tysan_type_descriptor *TDB) {
+  // Walk up the tree starting with TDA to see if we reach TDB.
+  uptr OffsetA = 0, OffsetB = 0;
+  if (TDB->Tag == TYSAN_MEMBER_TD) {
+    OffsetB = TDB->Member.Offset;
+    TDB = TDB->Member.Base;
+  }
+
+  if (TDA->Tag == TYSAN_MEMBER_TD) {
+    OffsetA = TDA->Member.Offset;
+    TDA = TDA->Member.Base;
+  }
+
+  do {
+    if (TDA == TDB)
+      return OffsetA == OffsetB;
+
+    if (TDA->Tag == TYSAN_STRUCT_TD) {
+      if (!TDA->Struct.MemberCount) {
+        DCHECK(0);
+        break;
+      }
+
+      uptr Idx = 0;
+      for (; Idx < TDA->Struct.MemberCount-1; ++Idx) {
+        if (TDA->Struct.Members[Idx].Offset >= OffsetA)
+          break;
+      }
+
+      OffsetA -= TDA->Struct.Members[Idx].Offset;
+      TDA = TDA->Struct.Members[Idx].Type;
+    } else {
+      DCHECK(0);
+      break;
+    }
+  } while (TDA);
+
+  return false;
+}
+
+static bool isAliasingLegal(tysan_type_descriptor *TDA,
+                            tysan_type_descriptor *TDB) {
+  if (TDA == TDB || !TDB || !TDA)
+    return true;
+
+  // Aliasing is legal is the two types have different root nodes.
+  if (getRootTD(TDA) != getRootTD(TDB))
+    return true;
+
+  return isAliasingLegalUp(TDA, TDB) || isAliasingLegalUp(TDB, TDA);
+}
+
+namespace __tysan {
+class Decorator: public __sanitizer::SanitizerCommonDecorator {
+ public:
+  Decorator() : SanitizerCommonDecorator() { }
+  const char *Warning()    { return Red(); }
+  const char *Name()   { return Green(); }
+  const char *End()    { return Default(); }
+};
+}
+
+ALWAYS_INLINE
+static void reportError(void *Addr, int Size, tysan_type_descriptor *TD,
+                        tysan_type_descriptor *OldTD, const char *AccessStr,
+                        const char *DescStr, int Offset, uptr pc, uptr bp,
+                        uptr sp) {
+  Decorator d;
+  Printf("%s", d.Warning());
+  Report("ERROR: TypeSanitizer: type-aliasing-violation on address %p"
+         " (pc %p bp %p sp %p tid %d)\n",
+         Addr, (void *) pc, (void *) bp, (void *) sp, GetTid());
+  Printf("%s", d.End());
+  Printf("%s of size %d at %p with type ", AccessStr, Size, Addr);
+
+  Printf("%s", d.Name());
+  printTDName(TD);
+  Printf("%s", d.End());
+
+  Printf(" %s of type ", DescStr);
+
+  Printf("%s", d.Name());
+  printTDName(OldTD);
+  Printf("%s", d.End());
+
+  if (Offset != 0)
+    Printf(" that starts at offset %d\n", Offset);
+  else
+    Printf("\n");
+
+  if (pc) {
+    BufferedStackTrace ST;
+    ST.Unwind(kStackTraceMax, pc, bp, 0, 0, 0, false);
+    ST.Print();
+  } else {
+    Printf("\n");
+  }
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __tysan_check(void *addr, int size, tysan_type_descriptor *td,
+                     int flags) {
+  GET_CALLER_PC_BP_SP;
+
+  bool IsRead = flags & 1;
+  bool IsWrite = flags & 2;
+  const char *AccessStr;
+  if (IsRead && !IsWrite)
+    AccessStr = "READ";
+  else if (!IsRead && IsWrite)
+    AccessStr = "WRITE";
+  else
+    AccessStr = "ATOMIC UPDATE";
+
+  tysan_type_descriptor **OldTDPtr = shadow_for(addr);
+  tysan_type_descriptor *OldTD = *OldTDPtr;
+  if (((sptr) OldTD) < 0) {
+    int i = -((sptr) OldTD);
+    OldTDPtr -= i;
+    OldTD = *OldTDPtr;
+
+    if (!isAliasingLegal(td, OldTD))
+      reportError(addr, size, td, OldTD, AccessStr,
+                  "accesses part of an existing object", -i, pc, bp, sp);
+
+    return;
+  }
+
+  if (!isAliasingLegal(td, OldTD)) {
+    reportError(addr, size, td, OldTD, AccessStr,
+                "accesses an existing object", 0, pc, bp, sp);
+    return;
+  }
+
+  // These types are allowed to alias (or the stored type is unknown), report
+  // an error if we find an interior type.
+
+  for (int i = 0; i < size; ++i) {
+    OldTDPtr = shadow_for((void *)(((uptr)addr)+i));
+    OldTD = *OldTDPtr;
+    if (((sptr) OldTD) >= 0 && !isAliasingLegal(td, OldTD))
+      reportError(addr, size, td, OldTD, AccessStr,
+                  "partially accesses an object", i, pc, bp, sp);
+  }
+}
+
+Flags __tysan::flags_data;
+
+SANITIZER_INTERFACE_ATTRIBUTE uptr __tysan_shadow_memory_address;
+SANITIZER_INTERFACE_ATTRIBUTE uptr __tysan_app_memory_mask;
+
+#ifdef TYSAN_RUNTIME_VMA
+// Runtime detected VMA size.
+int __tysan::vmaSize;
+#endif
+
+void Flags::SetDefaults() {
+#define TYSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "tysan_flags.inc"
+#undef TYSAN_FLAG
+}
+
+static void RegisterTySanFlags(FlagParser *parser, Flags *f) {
+#define TYSAN_FLAG(Type, Name, DefaultValue, Description) \
+  RegisterFlag(parser, #Name, Description, &f->Name);
+#include "tysan_flags.inc"
+#undef TYSAN_FLAG
+}
+
+static void InitializeFlags() {
+  SetCommonFlagsDefaults();
+  {
+    CommonFlags cf;
+    cf.CopyFrom(*common_flags());
+    cf.external_symbolizer_path = GetEnv("TYSAN_SYMBOLIZER_PATH");
+    OverrideCommonFlags(cf);
+  }
+
+  flags().SetDefaults();
+
+  FlagParser parser;
+  RegisterCommonFlags(&parser);
+  RegisterTySanFlags(&parser, &flags());
+  parser.ParseString(GetEnv("TYSAN_OPTIONS"));
+  InitializeCommonFlags();
+  if (Verbosity()) ReportUnrecognizedFlags();
+  if (common_flags()->help) parser.PrintFlagDescriptions();
+}
+
+static void InitializePlatformEarly() {
+  AvoidCVE_2016_2143();
+#ifdef TYSAN_RUNTIME_VMA
+  vmaSize =
+    (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
+#if defined(__aarch64__)
+  if (vmaSize != 39 && vmaSize != 42 && vmaSize != 48) {
+    Printf("FATAL: TypeSanitizer: unsupported VMA range\n");
+    Printf("FATAL: Found %d - Supported 39, 42 and 48\n", vmaSize);
+    Die();
+  }
+#elif defined(__powerpc64__)
+  if (vmaSize != 44 && vmaSize != 46) {
+    Printf("FATAL: TypeSanitizer: unsupported VMA range\n");
+    Printf("FATAL: Found %d - Supported 44 and 46\n", vmaSize);
+    Die();
+  }
+#endif
+#endif
+
+  __tysan_shadow_memory_address = ShadowAddr();
+  __tysan_app_memory_mask = AppMask();
+}
+
+namespace __tysan {
+bool tysan_inited = false;
+bool tysan_init_is_running;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __tysan_init() {
+  CHECK(!tysan_init_is_running);
+  if (tysan_inited) return;
+  tysan_init_is_running = true;
+
+  InitializeFlags();
+  InitializePlatformEarly();
+
+  InitializeInterceptors();
+
+  MmapFixedNoReserve(ShadowAddr(), AppAddr() - ShadowAddr());
+
+  tysan_init_is_running = false;
+  tysan_inited = true;
+}
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+__attribute__((section(".preinit_array"), used))
+static void (*tysan_init_ptr)() = __tysan_init;
+#endif
+
Index: lib/tysan/tysan.syms.extra
===================================================================
--- /dev/null
+++ lib/tysan/tysan.syms.extra
@@ -0,0 +1,2 @@
+tysan_*
+__tysan_*
Index: lib/tysan/tysan_flags.inc
===================================================================
--- /dev/null
+++ lib/tysan/tysan_flags.inc
@@ -0,0 +1,19 @@
+//===-- tysan_flags.inc ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// TySan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TYSAN_FLAG
+# error "Define TYSAN_FLAG prior to including this file!"
+#endif
+
+// TYSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
Index: lib/tysan/tysan_interceptors.cc
===================================================================
--- /dev/null
+++ lib/tysan/tysan_interceptors.cc
@@ -0,0 +1,228 @@
+//===-- tysan_interceptors.cc ---------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+// Interceptors for standard library functions.
+//===----------------------------------------------------------------------===//
+
+#include "tysan/tysan.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+# define TYSAN_INTERCEPT___STRDUP 1
+#else
+# define TYSAN_INTERCEPT___STRDUP 0
+#endif
+
+#if SANITIZER_LINUX
+extern "C"
+int mallopt(int param, int value);
+#endif
+
+using namespace __sanitizer;
+using namespace __tysan;
+
+static const uptr early_alloc_buf_size = 16384;
+static uptr allocated_bytes;
+static char early_alloc_buf[early_alloc_buf_size];
+
+static bool isInEarlyAllocBuf(const void *ptr) {
+  return ((uptr)ptr >= (uptr)early_alloc_buf &&
+          ((uptr)ptr - (uptr)early_alloc_buf) < sizeof(early_alloc_buf));
+}
+
+// Handle allocation requests early (before all interceptors are setup). dlsym,
+// for example, calls calloc.
+static void *handleEarlyAlloc(uptr size) {
+  void *mem = (void *)&early_alloc_buf[allocated_bytes];
+  allocated_bytes += size;
+  CHECK_LT(allocated_bytes, early_alloc_buf_size);
+  return mem;
+}
+
+INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
+  if (!tysan_inited && REAL(memset) == nullptr)
+    return internal_memset(dst, v, size);
+
+  void *res = REAL(memset)(dst, v, size);
+  tysan_set_type_unknown(dst, size);
+  return res;
+}
+
+INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
+  if (!tysan_inited && REAL(memmove) == nullptr)
+    return internal_memmove(dst, src, size);
+
+  void *res = REAL(memmove)(dst, src, size);
+  tysan_copy_types(dst, src, size);
+  return res;
+}
+
+INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
+  if (!tysan_inited && REAL(memcpy) == nullptr) {
+      // memmove is used here because on some platforms this will also
+      // intercept the memmove implementation.
+      return internal_memmove(dst, src, size);
+  }
+
+  void *res = REAL(memcpy)(dst, src, size);
+  tysan_copy_types(dst, src, size);
+  return res;
+}
+
+INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
+            int fd, OFF_T offset) {
+  void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
+  if (res != (void*)-1)
+    tysan_set_type_unknown(res, RoundUpTo(length, GetPageSize()));
+  return res;
+}
+
+INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
+            int fd, OFF64_T offset) {
+  void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
+  if (res != (void*)-1)
+    tysan_set_type_unknown(res, RoundUpTo(length, GetPageSize()));
+  return res;
+}
+
+INTERCEPTOR(char*, strdup, const char *s) {
+  char *res = REAL(strdup)(s);
+  if (res)
+    tysan_copy_types(res, const_cast<char *>(s), internal_strlen(s));
+  return res; 
+}
+
+#if TYSAN_INTERCEPT___STRDUP
+INTERCEPTOR(char*, __strdup, const char *s) {
+  char *res = REAL(__strdup)(s);
+  if (res)
+    tysan_copy_types(res, const_cast<char *>(s), internal_strlen(s));
+  return res; 
+}
+#endif // TYSAN_INTERCEPT___STRDUP
+
+INTERCEPTOR(void*, malloc, uptr size) {
+  if (tysan_init_is_running && REAL(malloc) == nullptr)
+    return handleEarlyAlloc(size);
+
+  void *res = REAL(malloc)(size);
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
+  void *res = REAL(realloc)(ptr, size);
+  // We might want to copy the types from the original allocation (although
+  // that would require that we knew its size).
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
+  if (tysan_init_is_running && REAL(calloc) == nullptr)
+    return handleEarlyAlloc(nmemb*size);
+
+  void *res = REAL(calloc)(nmemb, size);
+  if (res)
+    tysan_set_type_unknown(res, nmemb*size);
+  return res;
+}
+
+INTERCEPTOR(void, free, void *p) {
+  // There are only a few early allocation requests,
+  // so we simply skip the free.
+  if (isInEarlyAllocBuf(p))
+    return;
+  REAL(free)(p);
+}
+
+INTERCEPTOR(void*, valloc, uptr size) {
+  void *res = REAL(valloc)(size);
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
+  void *res = REAL(memalign)(alignment, size);
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(void*, __libc_memalign, uptr alignment, uptr size) {
+  void *res = REAL(__libc_memalign)(alignment, size);
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(void*, pvalloc, uptr size) {
+  void *res = REAL(pvalloc)(size);
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
+  void *res = REAL(aligned_alloc)(alignment, size);
+  if (res)
+    tysan_set_type_unknown(res, size);
+  return res;
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+  int res = REAL(posix_memalign)(memptr, alignment, size);
+  if (res == 0 && *memptr)
+    tysan_set_type_unknown(*memptr, size);
+  return res;
+}
+
+namespace __tysan {
+void InitializeInterceptors() {
+  static int inited = 0;
+  CHECK_EQ(inited, 0);
+
+  // Instruct libc malloc to consume less memory.
+#if SANITIZER_LINUX
+  mallopt(1, 0);  // M_MXFAST
+  mallopt(-3, 32*1024);  // M_MMAP_THRESHOLD
+#endif
+
+  INTERCEPT_FUNCTION(mmap);
+  INTERCEPT_FUNCTION(mmap64);
+
+  INTERCEPT_FUNCTION(strdup);
+#if TYSAN_INTERCEPT___STRDUP
+  INTERCEPT_FUNCTION(__strdup);
+#endif
+
+  INTERCEPT_FUNCTION(malloc);
+  INTERCEPT_FUNCTION(calloc);
+  INTERCEPT_FUNCTION(free);
+  INTERCEPT_FUNCTION(realloc);
+  INTERCEPT_FUNCTION(valloc);
+  INTERCEPT_FUNCTION(memalign);
+  INTERCEPT_FUNCTION(__libc_memalign);
+  INTERCEPT_FUNCTION(pvalloc);
+  INTERCEPT_FUNCTION(aligned_alloc);
+  INTERCEPT_FUNCTION(posix_memalign);
+
+  INTERCEPT_FUNCTION(memset);
+  INTERCEPT_FUNCTION(memmove);
+  INTERCEPT_FUNCTION(memcpy);
+
+  inited = 1;
+}
+}  // namespace __tysan
Index: lib/tysan/tysan_platform.h
===================================================================
--- /dev/null
+++ lib/tysan/tysan_platform.h
@@ -0,0 +1,125 @@
+//===------------------------ tysan_platform.h ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+// Platform specific information for TySan.
+//===----------------------------------------------------------------------===//
+
+#ifndef TYSAN_PLATFORM_H
+#define TYSAN_PLATFORM_H
+
+namespace __tysan {
+
+#if defined(__x86_64__)
+struct Mapping {
+  static const uptr kShadowAddr = 0x010000000000ull;
+  static const uptr kAppAddr =    0x550000000000ull;
+  static const uptr kAppMemMsk = ~0x780000000000ull;
+};
+#elif defined(__mips64)
+struct Mapping {
+  static const uptr kShadowAddr = 0x2400000000ull;
+  static const uptr kAppAddr =    0xfe00000000ull;
+  static const uptr kAppMemMsk = ~0xf800000000ull;
+};
+#elif defined(__aarch64__)
+struct Mapping39 {
+  static const uptr kShadowAddr = 0x0800000000ull;
+  static const uptr kAppAddr =    0x5500000000ull;
+  static const uptr kAppMemMsk = ~0x7800000000ull;
+};
+
+struct Mapping42 {
+  static const uptr kShadowAddr = 0x10000000000ull;
+  static const uptr kAppAddr =    0x2aa00000000ull;
+  static const uptr kAppMemMsk = ~0x3c000000000ull;
+};
+
+struct Mapping48 {
+  static const uptr kShadowAddr = 0x0002000000000ull;
+  static const uptr kAppAddr =    0x0aaaa00000000ull;
+  static const uptr kAppMemMsk = ~0x0fff800000000ull;
+};
+# define TYSAN_RUNTIME_VMA 1
+#elif defined(__powerpc64__)
+struct Mapping44 {
+  static const uptr kShadowAddr = 0x000100000000ull;
+  static const uptr kAppAddr =    0x0f0000000000ull;
+  static const uptr kAppMemMsk = ~0x0f0000000000ull;
+};
+
+struct Mapping46 {
+  static const uptr kShadowAddr = 0x010000000000ull;
+  static const uptr kAppAddr =    0x3d0000000000ull;
+  static const uptr kAppMemMsk = ~0x3c0000000000ull;
+};
+# define TYSAN_RUNTIME_VMA 1
+#else
+# error "TySan not supported for this platform!"
+#endif
+
+#if TYSAN_RUNTIME_VMA
+extern int vmaSize;
+#endif
+
+enum MappingType {
+  MAPPING_SHADOW_ADDR,
+  MAPPING_APP_ADDR,
+  MAPPING_APP_MASK
+};
+
+template<typename Mapping, int Type>
+uptr MappingImpl(void) {
+  switch (Type) {
+    case MAPPING_SHADOW_ADDR: return Mapping::kShadowAddr;
+    case MAPPING_APP_ADDR: return Mapping::kAppAddr;
+    case MAPPING_APP_MASK: return Mapping::kAppMemMsk;
+  }
+}
+
+template<int Type>
+uptr MappingArchImpl(void) {
+#ifdef __aarch64__
+  switch (vmaSize) {
+    case 39: return MappingImpl<Mapping39, Type>();
+    case 42: return MappingImpl<Mapping42, Type>();
+    case 48: return MappingImpl<Mapping48, Type>();
+  }
+  DCHECK(0);
+  return 0;
+#elif defined(__powerpc64__)
+  if (vmaSize == 44)
+    return MappingImpl<Mapping44, Type>();
+  else
+    return MappingImpl<Mapping46, Type>();
+  DCHECK(0);
+#else
+  return MappingImpl<Mapping, Type>();
+#endif
+}
+
+ALWAYS_INLINE
+uptr ShadowAddr() {
+  return MappingArchImpl<MAPPING_SHADOW_ADDR>();
+}
+
+ALWAYS_INLINE
+uptr AppAddr() {
+  return MappingArchImpl<MAPPING_APP_ADDR>();
+}
+
+ALWAYS_INLINE
+uptr AppMask() {
+  return MappingArchImpl<MAPPING_APP_MASK>();
+}
+
+}  // namespace __tysan
+
+#endif
Index: test/tysan/CMakeLists.txt
===================================================================
--- /dev/null
+++ test/tysan/CMakeLists.txt
@@ -0,0 +1,32 @@
+set(TYSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+set(TYSAN_TESTSUITES)
+
+set(TYSAN_TEST_ARCH ${TYSAN_SUPPORTED_ARCH})
+if(APPLE)
+  darwin_filter_host_archs(TYSAN_SUPPORTED_ARCH TYSAN_TEST_ARCH)
+endif()
+
+foreach(arch ${TYSAN_TEST_ARCH})
+  set(TYSAN_TEST_TARGET_ARCH ${arch})
+  string(TOLOWER "-${arch}" TYSAN_TEST_CONFIG_SUFFIX)
+  get_test_cc_for_arch(${arch} TYSAN_TEST_TARGET_CC TYSAN_TEST_TARGET_CFLAGS)
+  string(TOUPPER ${arch} ARCH_UPPER_CASE)
+  set(CONFIG_NAME ${ARCH_UPPER_CASE}Config)
+
+  configure_lit_site_cfg(
+    ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+    ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+  list(APPEND TYSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+set(TYSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(NOT COMPILER_RT_STANDALONE_BUILD)
+  list(APPEND TYSAN_TEST_DEPS tysan)
+endif()
+
+add_lit_testsuite(check-tysan "Running the TypeSanitizer tests"
+  ${TYSAN_TESTSUITES}
+  DEPENDS ${TYSAN_TEST_DEPS}
+  )
+set_target_properties(check-tysan PROPERTIES FOLDER "Compiler-RT Misc")
Index: test/tysan/anon-ns.cpp
===================================================================
--- /dev/null
+++ test/tysan/anon-ns.cpp
@@ -0,0 +1,43 @@
+// RUN: %clangxx_tysan -O0 %s -c -o %t.o && \
+// RUN:   %clangxx_tysan -O0 %s -DPMAIN -c -o %tm.o && \
+// RUN:   %clangxx_tysan -O0 %t.o %tm.o -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <iostream>
+
+// This test demonstrates that the types from anonymous namespaces are
+// different in different translation units (while the char* type is the same).
+
+namespace {
+struct X {
+  X(int i, int j) : a(i), b(j) {}
+  int a;
+  int b;
+};
+}
+
+#ifdef PMAIN
+void foo(void *context, int i);
+char fbyte(void *context);
+
+int main() {
+  X x(5, 6);
+  foo((void *) &x, 8);
+  std::cout << "fbyte: " << fbyte((void *) &x) << "\n";
+}
+#else
+void foo(void *context, int i) {
+  X *x = (X *) context;
+  x->b = i;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type int (in (anonymous namespace)::X at offset 4) accesses an existing object of type int (in (anonymous namespace)::X at offset 4)
+// CHECK: {{#0 0x.* in foo\(void\*, int\) .*anon-ns.cpp:}}[[@LINE-3]]
+}
+
+char fbyte(void *context) {
+  return *(char *) context;
+}
+#endif
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
Index: test/tysan/anon-same-struct.c
===================================================================
--- /dev/null
+++ test/tysan/anon-same-struct.c
@@ -0,0 +1,23 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+
+// The two anonymous structs are structurally identical. As a result, we don't
+// report an aliasing violation here.
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+ 
+typedef struct { int i1; } s1;
+typedef struct { int i2; } s2;
+ 
+void f(s1 *s1p, s2 *s2p) {
+  s1p->i1 = 2;
+  s2p->i2 = 3;
+  printf("%i\n", s1p->i1);
+}
+ 
+int main() {
+  s1 s = {.i1 = 1};
+  f(&s, (s2 *)&s);
+}
+
Index: test/tysan/anon-struct.c
===================================================================
--- /dev/null
+++ test/tysan/anon-struct.c
@@ -0,0 +1,24 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+ 
+typedef struct { int i1, i1b; } s1;
+typedef struct { int i2, i2b, i2c; } s2;
+ 
+void f(s1 *s1p, s2 *s2p) {
+  s1p->i1 = 2;
+  s2p->i2 = 3;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type int (in <anonymous type> at offset 0) accesses an existing object of type int (in <anonymous type> at offset 0)
+// CHECK: {{#0 0x.* in f .*anon-struct.c:}}[[@LINE-3]]
+  printf("%i\n", s1p->i1);
+}
+ 
+int main() {
+  s1 s = {.i1 = 1, .i1b = 5 };
+  f(&s, (s2 *)&s);
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
Index: test/tysan/basic.c
===================================================================
--- /dev/null
+++ test/tysan/basic.c
@@ -0,0 +1,66 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t 10 >%t.out.0 2>&1
+// RUN: FileCheck %s < %t.out.0
+// RUN: %clang_tysan -O2 %s -o %t && %run %t 10 >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void __attribute__((noinline)) add_flt(float *a) {
+  *a += 2.0f;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 4 at {{.*}} with type float accesses an existing object of type int
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-3]]
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type int
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-6]]
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 4 at {{.*}} with type float accesses an existing object of type long
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-9]]
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type long
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-12]]
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 4 at {{.*}} with type float accesses part of an existing object of type long that starts at offset -4
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-15]]
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type float accesses part of an existing object of type long that starts at offset -4
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-18]]
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 4 at {{.*}} with type float partially accesses an object of type short that starts at offset 2
+// CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-21]]
+}
+
+int main(int argc, char *argv[]) {
+  int x = atoi(argv[1]);
+  add_flt((float *) &x);
+  printf("x = %d\n", x);
+
+  long y = x;
+  add_flt((float *) &y);
+  printf("y = %ld\n", y);
+
+  add_flt(((float *) &y) + 1);
+  printf("y = %ld\n", y);
+
+  char *mem = (char *) malloc(4*sizeof(short));
+  memset(mem, 0, 4*sizeof(short));
+  *(short *) (mem + 2) = x;
+  add_flt((float*) mem);
+  short s1 = *(short *) mem;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 2 at {{.*}} with type short accesses an existing object of type float
+// CHECK: {{#0 0x.* in main .*basic.c:}}[[@LINE-3]]
+  short s2 = *(short *) (mem + 2);
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 2 at {{.*}} with type short accesses part of an existing object of type float that starts at offset -2
+// CHECK: {{#0 0x.* in main .*basic.c:}}[[@LINE-3]]
+  printf("m[0] = %d, m[1] = %d\n", s1, s2);
+  free(mem);
+
+  return 0;
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
Index: test/tysan/char-memcpy.c
===================================================================
--- /dev/null
+++ test/tysan/char-memcpy.c
@@ -0,0 +1,40 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out.0 2>&1
+// RUN: FileCheck %s < %t.out.0
+// RUN: %clang_tysan -O2 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+
+// There's no type-based-aliasing violation here: the memcpy is implemented
+// using only char* or unsigned char* (both of which may alias anything).
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+ 
+void my_memcpy_uchar(void *dest, void *src, int n) {
+  unsigned char *p = dest, *q = src, *end = p + n;
+  while (p < end)
+    *p++ = *q++;
+}
+
+void my_memcpy_char(void *dest, void *src, int n) {
+  char *p = dest, *q = src, *end = p + n;
+  while (p < end)
+    *p++ = *q++;
+}
+
+void test_uchar() {
+  struct S { short x; short *r; } s = { 10, &s.x }, s2;
+  my_memcpy_uchar(&s2, &s, sizeof(struct S));
+  printf("%d\n", *(s2.r));
+}
+
+void test_char() {
+  struct S { short x; short *r; } s = { 10, &s.x }, s2;
+  my_memcpy_char(&s2, &s, sizeof(struct S));
+  printf("%d\n", *(s2.r));
+}
+
+int main() {
+  test_uchar();
+  test_char();
+}
+
Index: test/tysan/global.c
===================================================================
--- /dev/null
+++ test/tysan/global.c
@@ -0,0 +1,31 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+#include <stdlib.h>
+
+float P;
+long L;
+
+int main() {
+  *(int*) &P = 5;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type int accesses an existing object of type float
+// CHECK: {{#0 0x.* in main .*global.c:}}[[@LINE-3]]
+
+  void *mem = malloc(sizeof(long));
+  *(int*) mem = 6;
+  memcpy(mem, &L, sizeof(L));
+  *(int*) mem = 8;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type int accesses an existing object of type long
+// CHECK: {{#0 0x.* in main .*global.c:}}[[@LINE-3]]
+  int r = *(((int*) mem) + 1);
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 4 at {{.*}} with type int accesses part of an existing object of type long that starts at offset -4
+// CHECK: {{#0 0x.* in main .*global.c:}}[[@LINE-3]]
+  free(mem);
+
+  return r;
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
Index: test/tysan/int-long.c
===================================================================
--- /dev/null
+++ test/tysan/int-long.c
@@ -0,0 +1,23 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+ 
+long foo(int *x, long *y) {
+  *x = 0;
+  *y = 1;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 8 at {{.*}} with type long accesses an existing object of type int
+// CHECK: {{#0 0x.* in foo .*int-long.c:}}[[@LINE-3]]
+
+  return *x;
+}
+ 
+int main(void) {
+  long l;
+  printf("%ld\n", foo((int *)&l, &l));
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
+
Index: test/tysan/lit.cfg
===================================================================
--- /dev/null
+++ test/tysan/lit.cfg
@@ -0,0 +1,35 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'TypeSanitizer' + getattr(config, 'name_suffix', 'default')
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Setup default compiler flags used with -fsanitize=type option.
+clang_tysan_cflags = (["-fsanitize=type",
+                      "-mno-omit-leaf-frame-pointer",
+                      "-fno-omit-frame-pointer",
+                      "-fno-optimize-sibling-calls"] +
+                      [config.target_cflags] +
+                      config.debug_info_flags)
+clang_tysan_cxxflags = config.cxx_mode_flags + clang_tysan_cflags
+
+def build_invocation(compile_flags):
+  return " " + " ".join([config.clang] + compile_flags) + " "
+
+config.substitutions.append( ("%clang_tysan ", build_invocation(clang_tysan_cflags)) )
+config.substitutions.append( ("%clangxx_tysan ", build_invocation(clang_tysan_cxxflags)) )
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+# TypeSanitizer tests are currently supported on Linux only.
+if config.host_os not in ['Linux']:
+  config.unsupported = True
+
+if config.target_arch != 'aarch64':
+  config.available_features.add('stable-runtime')
+
Index: test/tysan/lit.site.cfg.in
===================================================================
--- /dev/null
+++ test/tysan/lit.site.cfg.in
@@ -0,0 +1,12 @@
+@LIT_SITE_CFG_IN_HEADER@
+
+# Tool-specific config options.
+config.name_suffix = "@TYSAN_TEST_CONFIG_SUFFIX@"
+config.target_cflags = "@TYSAN_TEST_TARGET_CFLAGS@"
+config.target_arch = "@TYSAN_TEST_TARGET_ARCH@"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@TYSAN_LIT_SOURCE_DIR@/lit.cfg")
Index: test/tysan/ptr-float.c
===================================================================
--- /dev/null
+++ test/tysan/ptr-float.c
@@ -0,0 +1,21 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+float *P;
+void zero_array() {
+   int i;
+   for (i = 0; i < 1; ++i)
+     P[i] = 0.0f;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type any pointer
+// CHECK: {{#0 0x.* in zero_array .*ptr-float.c:}}[[@LINE-3]]
+
+}
+
+int main() {
+  P = (float*)&P;
+  zero_array();
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
Index: test/tysan/struct-offset.c
===================================================================
--- /dev/null
+++ test/tysan/struct-offset.c
@@ -0,0 +1,28 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+#include <stdlib.h>
+ 
+struct X {
+  int i;
+  int j;
+};
+ 
+int foo(struct X *p, struct X *q) {
+  q->j = 1;
+  p->i = 0;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type int (in X at offset 0) accesses an existing object of type int (in X at offset 4)
+// CHECK: {{#0 0x.* in foo .*struct-offset.c:}}[[@LINE-3]]
+  return q->j;
+}
+ 
+int main() {
+  unsigned char *p = malloc(3 * sizeof(int));
+  printf("%i\n", foo((struct X *)(p + sizeof(int)),
+                     (struct X *)p));
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
Index: test/tysan/struct.c
===================================================================
--- /dev/null
+++ test/tysan/struct.c
@@ -0,0 +1,37 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+ 
+typedef struct S1 { int i1; } s1;
+typedef struct S2 { int i2; } s2;
+
+void g(int *i) {
+  *i = 5;
+  printf("%i\n", *i);
+}
+ 
+void h(char *c) {
+  *c = 5;
+  printf("%i\n", (int) *c);
+}
+
+void f(s1 *s1p, s2 *s2p) {
+  s1p->i1 = 2;
+  s2p->i2 = 3;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: WRITE of size 4 at {{.*}} with type int (in S2 at offset 0) accesses an existing object of type int (in S1 at offset 0)
+// CHECK: {{#0 0x.* in f .*struct.c:}}[[@LINE-3]]
+  printf("%i\n", s1p->i1);
+}
+ 
+int main() {
+  s1 s = {.i1 = 1};
+  f(&s, (s2 *)&s);
+  g(&s.i1);
+  h((char *) &s.i1);
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
+
Index: test/tysan/union-wr-wr.c
===================================================================
--- /dev/null
+++ test/tysan/union-wr-wr.c
@@ -0,0 +1,19 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <stdio.h>
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
+int main() {
+  union {
+    int i;
+    short s;
+  } u;
+
+  u.i = 42;
+  u.s = 1;
+
+  printf("%d\n", u.i);
+}
+