[TSan] port all output tests to lit and move them to lit_tests directory. This makes...
authorAlexey Samsonov <samsonov@google.com>
Tue, 18 Sep 2012 07:23:54 +0000 (07:23 +0000)
committerAlexey Samsonov <samsonov@google.com>
Tue, 18 Sep 2012 07:23:54 +0000 (07:23 +0000)
llvm-svn: 164110

70 files changed:
compiler-rt/lib/tsan/Makefile.old
compiler-rt/lib/tsan/lit_tests/CMakeLists.txt
compiler-rt/lib/tsan/lit_tests/free_race.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/free_race2.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/heap_race.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/lit.cfg [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/lit.site.cfg.in [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/memcpy_race.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/mop_with_offset.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/mop_with_offset2.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/mutex_destroy_locked.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/race_on_barrier.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/race_on_barrier2.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/race_on_heap.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/race_on_mutex.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/race_with_finished_thread.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/simple_race.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/simple_race.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/simple_stack.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/simple_stack2.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/sleep_sync.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/sleep_sync2.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/static_init1.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/static_init2.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/static_init3.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/static_init4.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/static_init5.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/suppress_same_address.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/suppress_same_stacks.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/test_output.sh [new file with mode: 0755]
compiler-rt/lib/tsan/lit_tests/thread_leak.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/thread_leak2.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/thread_leak3.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/tiny_race.c [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/virtual_inheritance_compile_bug.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/vptr_benign_race.cc [new file with mode: 0644]
compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc [new file with mode: 0644]
compiler-rt/lib/tsan/output_tests/free_race.c [deleted file]
compiler-rt/lib/tsan/output_tests/free_race2.c [deleted file]
compiler-rt/lib/tsan/output_tests/heap_race.cc [deleted file]
compiler-rt/lib/tsan/output_tests/memcpy_race.cc [deleted file]
compiler-rt/lib/tsan/output_tests/mop_with_offset.cc [deleted file]
compiler-rt/lib/tsan/output_tests/mop_with_offset2.cc [deleted file]
compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc [deleted file]
compiler-rt/lib/tsan/output_tests/race_on_barrier.c [deleted file]
compiler-rt/lib/tsan/output_tests/race_on_barrier2.c [deleted file]
compiler-rt/lib/tsan/output_tests/race_on_heap.cc [deleted file]
compiler-rt/lib/tsan/output_tests/race_on_mutex.c [deleted file]
compiler-rt/lib/tsan/output_tests/race_with_finished_thread.cc [deleted file]
compiler-rt/lib/tsan/output_tests/simple_race.c [deleted file]
compiler-rt/lib/tsan/output_tests/simple_race.cc [deleted file]
compiler-rt/lib/tsan/output_tests/simple_stack.c [deleted file]
compiler-rt/lib/tsan/output_tests/simple_stack2.cc [deleted file]
compiler-rt/lib/tsan/output_tests/sleep_sync.cc [deleted file]
compiler-rt/lib/tsan/output_tests/sleep_sync2.cc [deleted file]
compiler-rt/lib/tsan/output_tests/static_init1.cc [deleted file]
compiler-rt/lib/tsan/output_tests/static_init2.cc [deleted file]
compiler-rt/lib/tsan/output_tests/static_init3.cc [deleted file]
compiler-rt/lib/tsan/output_tests/static_init4.cc [deleted file]
compiler-rt/lib/tsan/output_tests/static_init5.cc [deleted file]
compiler-rt/lib/tsan/output_tests/suppress_same_address.cc [deleted file]
compiler-rt/lib/tsan/output_tests/suppress_same_stacks.cc [deleted file]
compiler-rt/lib/tsan/output_tests/test_output.sh [deleted file]
compiler-rt/lib/tsan/output_tests/thread_leak.c [deleted file]
compiler-rt/lib/tsan/output_tests/thread_leak2.c [deleted file]
compiler-rt/lib/tsan/output_tests/thread_leak3.c [deleted file]
compiler-rt/lib/tsan/output_tests/tiny_race.c [deleted file]
compiler-rt/lib/tsan/output_tests/virtual_inheritance_compile_bug.cc [deleted file]
compiler-rt/lib/tsan/output_tests/vptr_benign_race.cc [deleted file]
compiler-rt/lib/tsan/output_tests/vptr_harmful_race.cc [deleted file]

index 95322730c533a92078e018184b954d739df1fa2c..1273a7873bed7482694f000de6add46bbce78c57 100644 (file)
@@ -53,7 +53,7 @@ test: libtsan tsan_test
 
 run: all
        (ulimit -s 8192; ./tsan_test)
-       ./output_tests/test_output.sh
+       ./lit_tests/test_output.sh
 
 presubmit:
        # Debug build with clang.
index 62cad78704b89a4b38a9b393cdd80dc3780cddb1..4e3273b3ac58274f7599babeca72bfe08fcffd55 100644 (file)
@@ -1,10 +1,34 @@
+configure_lit_site_cfg(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+  )
+
 configure_lit_site_cfg(
   ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
   ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
   )
 
-# Run TSan unit tests.
-if(LLVM_INCLUDE_TESTS)
+if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}")
+  # Run TSan output tests only if we're not cross-compiling,
+  # and can be sure that clang would produce working binaries.
+  set(TSAN_TEST_DEPS
+    clang clang-headers FileCheck count not
+    ${TSAN_RUNTIME_LIBRARIES}
+    )
+  set(TSAN_TEST_PARAMS
+    tsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+    )
+  if(LLVM_INCLUDE_TESTS)
+    list(APPEND ASAN_TEST_DEPS TsanUnitTests)
+  endif()
+  add_lit_testsuite(check-tsan "Running ThreadSanitizer tests"
+    ${CMAKE_CURRENT_BINARY_DIR}
+    PARAMS ${TSAN_TEST_PARAMS}
+    DEPENDS ${TSAN_TEST_DEPS}
+    )
+  set_target_properties(check-tsan PROPERTIES FOLDER "TSan unittests")
+elseif(LLVM_INCLUDE_TESTS)
+  # Otherwise run only TSan unit tests.
   add_lit_testsuite(check-tsan "Running ThreadSanitizer tests"
     ${CMAKE_CURRENT_BINARY_DIR}/Unit
     DEPENDS TsanUnitTests)
diff --git a/compiler-rt/lib/tsan/lit_tests/free_race.c b/compiler-rt/lib/tsan/lit_tests/free_race.c
new file mode 100644 (file)
index 0000000..9200c3b
--- /dev/null
@@ -0,0 +1,43 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+int *mem;
+pthread_mutex_t mtx;
+
+void *Thread1(void *x) {
+  pthread_mutex_lock(&mtx);
+  free(mem);
+  pthread_mutex_unlock(&mtx);
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  usleep(1000000);
+  pthread_mutex_lock(&mtx);
+  mem[0] = 42;
+  pthread_mutex_unlock(&mtx);
+  return NULL;
+}
+
+int main() {
+  mem = (int*)malloc(100);
+  pthread_mutex_init(&mtx, 0);
+  pthread_t t;
+  pthread_create(&t, NULL, Thread1, NULL);
+  Thread2(0);
+  pthread_join(t, NULL);
+  pthread_mutex_destroy(&mtx);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: heap-use-after-free
+// CHECK:   Write of size 4 at {{.*}} by main thread:
+// CHECK:     #0 Thread2
+// CHECK:     #1 main
+// CHECK:   Previous write of size 8 at {{.*}} by thread 1:
+// CHECK:     #0 free
+// CHECK:     #1 Thread1
diff --git a/compiler-rt/lib/tsan/lit_tests/free_race2.c b/compiler-rt/lib/tsan/lit_tests/free_race2.c
new file mode 100644 (file)
index 0000000..095f82e
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+
+void __attribute__((noinline)) foo(int *mem) {
+  free(mem);
+}
+
+void __attribute__((noinline)) bar(int *mem) {
+  mem[0] = 42;
+}
+
+int main() {
+  int *mem = (int*)malloc(100);
+  foo(mem);
+  bar(mem);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: heap-use-after-free
+// CHECK:   Write of size 4 at {{.*}} by main thread:
+// CHECK:     #0 bar
+// CHECK:     #1 main
+// CHECK:   Previous write of size 8 at {{.*}} by main thread:
+// CHECK:     #0 free
+// CHECK:     #1 foo
+// CHECK:     #2 main
diff --git a/compiler-rt/lib/tsan/lit_tests/heap_race.cc b/compiler-rt/lib/tsan/lit_tests/heap_race.cc
new file mode 100644 (file)
index 0000000..297f8db
--- /dev/null
@@ -0,0 +1,20 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+
+void *Thread(void *a) {
+  ((int*)a)[0]++;
+  return NULL;
+}
+
+int main() {
+  int *p = new int(42);
+  pthread_t t;
+  pthread_create(&t, NULL, Thread, p);
+  p[0]++;
+  pthread_join(t, NULL);
+  delete p;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/lit.cfg b/compiler-rt/lib/tsan/lit_tests/lit.cfg
new file mode 100644 (file)
index 0000000..f5e5230
--- /dev/null
@@ -0,0 +1,86 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'ThreadSanitizer'
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+def DisplayNoConfigMessage():
+  lit.fatal("No site specific configuration available! " +
+            "Try running your test from the build tree or running " +
+            "make check-tsan")
+
+# Figure out LLVM source root.
+llvm_src_root = getattr(config, 'llvm_src_root', None)
+if llvm_src_root is None:
+  # We probably haven't loaded the site-specific configuration: the user
+  # is likely trying to run a test file directly, and the site configuration
+  # wasn't created by the build system.
+  tsan_site_cfg = lit.params.get('tsan_site_config', None)
+  if (tsan_site_cfg) and (os.path.exists(tsan_site_cfg)):
+    lit.load_config(config, tsan_site_cfg)
+    raise SystemExit
+
+  # Try to guess the location of site-specific configuration using llvm-config
+  # util that can point where the build tree is.
+  llvm_config = lit.util.which("llvm-config", config.environment["PATH"])
+  if not llvm_config:
+    DisplayNoConfigMessage()
+
+  # Validate that llvm-config points to the same source tree.
+  llvm_src_root = lit.util.capture(["llvm-config", "--src-root"]).strip()
+  tsan_test_src_root = os.path.join(llvm_src_root, "projects", "compiler-rt",
+                                    "lib", "tsan", "lit_tests")
+  if (os.path.realpath(tsan_test_src_root) !=
+      os.path.realpath(config.test_source_root)):
+    DisplayNoConfigMessage()
+
+  # Find out the presumed location of generated site config.
+  llvm_obj_root = lit.util.capture(["llvm-config", "--obj-root"]).strip()
+  tsan_site_cfg = os.path.join(llvm_obj_root, "projects", "compiler-rt",
+                               "lib", "tsan", "lit_tests", "lit.site.cfg")
+  if (not tsan_site_cfg) or (not os.path.exists(tsan_site_cfg)):
+    DisplayNoConfigMessage()
+
+  lit.load_config(config, tsan_site_cfg)
+  raise SystemExit
+
+# Setup attributes common for all compiler-rt projects.
+compiler_rt_lit_cfg = os.path.join(llvm_src_root, "projects", "compiler-rt",
+                                   "lib", "lit.common.cfg")
+if (not compiler_rt_lit_cfg) or (not os.path.exists(compiler_rt_lit_cfg)):
+  lit.fatal("Can't find common compiler-rt lit config at: %r"
+            % compiler_rt_lit_cfg)
+lit.load_config(config, compiler_rt_lit_cfg)
+
+# Setup environment variables for running ThreadSanitizer.
+config.environment['TSAN_OPTIONS'] = "atexit_sleep_ms=0"
+
+# Setup default compiler flags used with -faddress-sanitizer option.
+# FIXME: Review the set of required flags and check if it can be reduced.
+clang_tsan_cflags = ("-fthread-sanitizer "
+                      + "-fPIE "
+                      + "-fno-builtin "
+                      + "-g "
+                      + "-Wall "
+                      + "-pie "
+                      + "-lpthread "
+                      + "-ldl ")
+clang_tsan_cxxflags = "-ccc-clang-cxx -ccc-cxx " + clang_tsan_cflags
+config.substitutions.append( ("%clangxx_tsan ", (" " + config.clang + " " +
+                                                clang_tsan_cxxflags + " ")) )
+config.substitutions.append( ("%clang_tsan ", (" " + config.clang + " " +
+                                              clang_tsan_cflags + " ")) )
+
+# Define CHECK-%os to check for OS-dependent output.
+config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+# ThreadSanitizer tests are currently supported on Linux only.
+if config.host_os not in ['Linux']:
+  config.unsupported = True
diff --git a/compiler-rt/lib/tsan/lit_tests/lit.site.cfg.in b/compiler-rt/lib/tsan/lit_tests/lit.site.cfg.in
new file mode 100644 (file)
index 0000000..b1c6ccf
--- /dev/null
@@ -0,0 +1,19 @@
+## Autogenerated by LLVM/Clang configuration.
+# Do not edit!
+
+config.clang = "@LLVM_BINARY_DIR@/bin/clang"
+config.host_os = "@HOST_OS@"
+config.llvm_src_root = "@LLVM_SOURCE_DIR@"
+config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
+config.target_triple = "@TARGET_TRIPLE@"
+
+# LLVM tools dir can be passed in lit parameters, so try to
+# apply substitution.
+try:
+  config.llvm_tools_dir = config.llvm_tools_dir % lit.params
+except KeyError,e:
+  key, = e.args
+  lit.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key, key))
+
+# Let the main config do the real work.
+lit.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
diff --git a/compiler-rt/lib/tsan/lit_tests/memcpy_race.cc b/compiler-rt/lib/tsan/lit_tests/memcpy_race.cc
new file mode 100644 (file)
index 0000000..c87bc9c
--- /dev/null
@@ -0,0 +1,40 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+char *data = new char[10];
+char *data1 = new char[10];
+char *data2 = new char[10];
+
+void *Thread1(void *x) {
+  memcpy(data+5, data1, 1);
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  usleep(500*1000);
+  memcpy(data+3, data2, 4);
+  return NULL;
+}
+
+int main() {
+  fprintf(stderr, "addr=%p\n", &data[5]);
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  return 0;
+}
+
+// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK:   Write of size 1 at [[ADDR]] by thread 2:
+// CHECK:     #0 memcpy
+// CHECK:     #1 Thread2
+// CHECK:   Previous write of size 1 at [[ADDR]] by thread 1:
+// CHECK:     #0 memcpy
+// CHECK:     #1 Thread1
diff --git a/compiler-rt/lib/tsan/lit_tests/mop_with_offset.cc b/compiler-rt/lib/tsan/lit_tests/mop_with_offset.cc
new file mode 100644 (file)
index 0000000..14ece1a
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void *Thread1(void *x) {
+  int *p = (int*)x;
+  p[0] = 1;
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  usleep(500*1000);
+  char *p = (char*)x;
+  p[2] = 1;
+  return NULL;
+}
+
+int main() {
+  int *data = new int(42);
+  fprintf(stderr, "ptr1=%p\n", data);
+  fprintf(stderr, "ptr2=%p\n", (char*)data + 2);
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, data);
+  pthread_create(&t[1], NULL, Thread2, data);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  delete data;
+}
+
+// CHECK: ptr1=[[PTR1:0x[0-9,a-f]+]]
+// CHECK: ptr2=[[PTR2:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK:   Write of size 1 at [[PTR2]] by thread 2:
+// CHECK:   Previous write of size 4 at [[PTR1]] by thread 1:
diff --git a/compiler-rt/lib/tsan/lit_tests/mop_with_offset2.cc b/compiler-rt/lib/tsan/lit_tests/mop_with_offset2.cc
new file mode 100644 (file)
index 0000000..2a6fde7
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void *Thread1(void *x) {
+  usleep(500*1000);
+  int *p = (int*)x;
+  p[0] = 1;
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  char *p = (char*)x;
+  p[2] = 1;
+  return NULL;
+}
+
+int main() {
+  int *data = new int(42);
+  fprintf(stderr, "ptr1=%p\n", data);
+  fprintf(stderr, "ptr2=%p\n", (char*)data + 2);
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, data);
+  pthread_create(&t[1], NULL, Thread2, data);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  delete data;
+}
+
+// CHECK: ptr1=[[PTR1:0x[0-9,a-f]+]]
+// CHECK: ptr2=[[PTR2:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK:   Write of size 4 at [[PTR1]] by thread 1:
+// CHECK:   Previous write of size 1 at [[PTR2]] by thread 2:
diff --git a/compiler-rt/lib/tsan/lit_tests/mutex_destroy_locked.cc b/compiler-rt/lib/tsan/lit_tests/mutex_destroy_locked.cc
new file mode 100644 (file)
index 0000000..427c643
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <unistd.h>
+
+void *Thread(void *p) {
+  pthread_mutex_lock((pthread_mutex_t*)p);
+  return 0;
+}
+
+int main() {
+  pthread_mutex_t m;
+  pthread_mutex_init(&m, 0);
+  pthread_t t;
+  pthread_create(&t, 0, Thread, &m);
+  usleep(1000*1000);
+  pthread_mutex_destroy(&m);
+  pthread_join(t, 0);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex
+// CHECK:     #0 pthread_mutex_destroy
+// CHECK:     #1 main
+// CHECK:   and:
+// CHECK:     #0 pthread_mutex_lock
+// CHECK:     #1 Thread
+// CHECK:   Mutex {{.*}} created at:
+// CHECK:     #0 pthread_mutex_init
+// CHECK:     #1 main
diff --git a/compiler-rt/lib/tsan/lit_tests/race_on_barrier.c b/compiler-rt/lib/tsan/lit_tests/race_on_barrier.c
new file mode 100644 (file)
index 0000000..491201f
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+pthread_barrier_t B;
+int Global;
+
+void *Thread1(void *x) {
+  pthread_barrier_init(&B, 0, 2);
+  pthread_barrier_wait(&B);
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  usleep(1000000);
+  pthread_barrier_wait(&B);
+  return NULL;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, NULL, Thread1, NULL);
+  Thread2(0);
+  pthread_join(t, NULL);
+  pthread_barrier_destroy(&B);
+  return 0;
+}
+
+// CHECK:      WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/race_on_barrier2.c b/compiler-rt/lib/tsan/lit_tests/race_on_barrier2.c
new file mode 100644 (file)
index 0000000..46a4f50
--- /dev/null
@@ -0,0 +1,31 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+pthread_barrier_t B;
+int Global;
+
+void *Thread1(void *x) {
+  if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD)
+    pthread_barrier_destroy(&B);
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD)
+    pthread_barrier_destroy(&B);
+  return NULL;
+}
+
+int main() {
+  pthread_barrier_init(&B, 0, 2);
+  pthread_t t;
+  pthread_create(&t, NULL, Thread1, NULL);
+  Thread2(0);
+  pthread_join(t, NULL);
+  return 0;
+}
+
+// CHECK:      WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/race_on_heap.cc b/compiler-rt/lib/tsan/lit_tests/race_on_heap.cc
new file mode 100644 (file)
index 0000000..1fdf54d
--- /dev/null
@@ -0,0 +1,47 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void *Thread1(void *p) {
+  *(int*)p = 42;
+  return 0;
+}
+
+void *Thread2(void *p) {
+  *(int*)p = 44;
+  return 0;
+}
+
+void *alloc() {
+  return malloc(99);
+}
+
+void *AllocThread(void* arg) {
+  return alloc();
+}
+
+int main() {
+  void *p = 0;
+  pthread_t t[2];
+  pthread_create(&t[0], 0, AllocThread, 0);
+  pthread_join(t[0], &p);
+  fprintf(stderr, "addr=%p\n", p);
+  pthread_create(&t[0], 0, Thread1, (char*)p + 16);
+  pthread_create(&t[1], 0, Thread2, (char*)p + 16);
+  pthread_join(t[0], 0);
+  pthread_join(t[1], 0);
+  return 0;
+}
+
+// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// ...
+// CHECK:   Location is heap block of size 99 at [[ADDR]] allocated by thread 1:
+// CHCEKL     #0 malloc
+// CHECK:     #1 alloc
+// CHECK:     #2 AllocThread
+// ...
+// CHECK:   Thread 1 (finished) created at:
+// CHECK:     #0 pthread_create
+// CHECK:     #1 main
diff --git a/compiler-rt/lib/tsan/lit_tests/race_on_mutex.c b/compiler-rt/lib/tsan/lit_tests/race_on_mutex.c
new file mode 100644 (file)
index 0000000..6c6697d
--- /dev/null
@@ -0,0 +1,42 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+
+pthread_mutex_t Mtx;
+int Global;
+
+void *Thread1(void *x) {
+  pthread_mutex_init(&Mtx, 0);
+  pthread_mutex_lock(&Mtx);
+  Global = 42;
+  pthread_mutex_unlock(&Mtx);
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  usleep(1000000);
+  pthread_mutex_lock(&Mtx);
+  Global = 43;
+  pthread_mutex_unlock(&Mtx);
+  return NULL;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  pthread_mutex_destroy(&Mtx);
+  return 0;
+}
+
+// CHECK:      WARNING: ThreadSanitizer: data race
+// CHECK-NEXT:   Read of size 1 at {{.*}} by thread 2:
+// CHECK-NEXT:     #0 pthread_mutex_lock
+// CHECK-NEXT:     #1 Thread2{{.*}} {{.*}}race_on_mutex.c:20{{(:3)?}} ({{.*}})
+// CHECK:        Previous write of size 1 at {{.*}} by thread 1:
+// CHECK-NEXT:     #0 pthread_mutex_init {{.*}} ({{.*}})
+// CHECK-NEXT:     #1 Thread1{{.*}} {{.*}}race_on_mutex.c:11{{(:3)?}} ({{.*}})
diff --git a/compiler-rt/lib/tsan/lit_tests/race_with_finished_thread.cc b/compiler-rt/lib/tsan/lit_tests/race_with_finished_thread.cc
new file mode 100644 (file)
index 0000000..e50c22b
--- /dev/null
@@ -0,0 +1,43 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+// Ensure that we can restore a stack of a finished thread.
+
+int g_data;
+
+void __attribute__((noinline)) foobar(int *p) {
+  *p = 42;
+}
+
+void *Thread1(void *x) {
+  foobar(&g_data);
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  usleep(1000*1000);
+  g_data = 43;
+  return NULL;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK:   Write of size 4 at {{.*}} by thread 2:
+// CHECK:   Previous write of size 4 at {{.*}} by thread 1:
+// CHECK:     #0 foobar
+// CHECK:     #1 Thread1
+// CHECK:   Thread 1 (finished) created at:
+// CHECK:     #0 pthread_create
+// CHECK:     #1 main
diff --git a/compiler-rt/lib/tsan/lit_tests/simple_race.c b/compiler-rt/lib/tsan/lit_tests/simple_race.c
new file mode 100644 (file)
index 0000000..44aff89
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+
+int Global;
+
+void *Thread1(void *x) {
+  Global = 42;
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  Global = 43;
+  return NULL;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/simple_race.cc b/compiler-rt/lib/tsan/lit_tests/simple_race.cc
new file mode 100644 (file)
index 0000000..ec29c92
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+
+int Global;
+
+void *Thread1(void *x) {
+  Global++;
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  Global--;
+  return NULL;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/simple_stack.c b/compiler-rt/lib/tsan/lit_tests/simple_stack.c
new file mode 100644 (file)
index 0000000..08f5f65
--- /dev/null
@@ -0,0 +1,66 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+
+void __attribute__((noinline)) foo1() {
+  Global = 42;
+}
+
+void __attribute__((noinline)) bar1() {
+  volatile int tmp = 42; (void)tmp;
+  foo1();
+}
+
+void __attribute__((noinline)) foo2() {
+  volatile int v = Global; (void)v;
+}
+
+void __attribute__((noinline)) bar2() {
+  volatile int tmp = 42; (void)tmp;
+  foo2();
+}
+
+void *Thread1(void *x) {
+  usleep(1000000);
+  bar1();
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  bar2();
+  return NULL;
+}
+
+void StartThread(pthread_t *t, void *(*f)(void*)) {
+  pthread_create(t, NULL, f, NULL);
+}
+
+int main() {
+  pthread_t t[2];
+  StartThread(&t[0], Thread1);
+  StartThread(&t[1], Thread2);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  return 0;
+}
+
+// CHECK:      WARNING: ThreadSanitizer: data race
+// CHECK-NEXT:   Write of size 4 at {{.*}} by thread 1:
+// CHECK-NEXT:     #0 foo1{{.*}} {{.*}}simple_stack.c:9{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #1 bar1{{.*}} {{.*}}simple_stack.c:14{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #2 Thread1{{.*}} {{.*}}simple_stack.c:28{{(:3)?}} ({{.*}})
+// CHECK:        Previous read of size 4 at {{.*}} by thread 2:
+// CHECK-NEXT:     #0 foo2{{.*}} {{.*}}simple_stack.c:18{{(:26)?}} ({{.*}})
+// CHECK-NEXT:     #1 bar2{{.*}} {{.*}}simple_stack.c:23{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #2 Thread2{{.*}} {{.*}}simple_stack.c:33{{(:3)?}} ({{.*}})
+// CHECK:        Thread 1 (running) created at:
+// CHECK-NEXT:     #0 pthread_create {{.*}} ({{.*}})
+// CHECK-NEXT:     #1 StartThread{{.*}} {{.*}}simple_stack.c:38{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack.c:43{{(:3)?}} ({{.*}})
+// CHECK:        Thread 2 ({{.*}}) created at:
+// CHECK-NEXT:     #0 pthread_create {{.*}} ({{.*}})
+// CHECK-NEXT:     #1 StartThread{{.*}} {{.*}}simple_stack.c:38{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack.c:44{{(:3)?}} ({{.*}})
diff --git a/compiler-rt/lib/tsan/lit_tests/simple_stack2.cc b/compiler-rt/lib/tsan/lit_tests/simple_stack2.cc
new file mode 100644 (file)
index 0000000..ed95c68
--- /dev/null
@@ -0,0 +1,53 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Global;
+
+void __attribute__((noinline)) foo1() {
+  Global = 42;
+}
+
+void __attribute__((noinline)) bar1() {
+  volatile int tmp = 42;
+  int tmp2 = tmp;
+  (void)tmp2;
+  foo1();
+}
+
+void __attribute__((noinline)) foo2() {
+  volatile int tmp = Global;
+  int tmp2 = tmp;
+  (void)tmp2;
+}
+
+void __attribute__((noinline)) bar2() {
+  volatile int tmp = 42;
+  int tmp2 = tmp;
+  (void)tmp2;
+  foo2();
+}
+
+void *Thread1(void *x) {
+  usleep(1000000);
+  bar1();
+  return NULL;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, NULL, Thread1, NULL);
+  bar2();
+  pthread_join(t, NULL);
+}
+
+// CHECK:      WARNING: ThreadSanitizer: data race
+// CHECK-NEXT:   Write of size 4 at {{.*}} by thread 1:
+// CHECK-NEXT:     #0 foo1{{.*}} {{.*}}simple_stack2.cc:9{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #1 bar1{{.*}} {{.*}}simple_stack2.cc:16{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #2 Thread1{{.*}} {{.*}}simple_stack2.cc:34{{(:3)?}} ({{.*}})
+// CHECK:        Previous read of size 4 at {{.*}} by main thread:
+// CHECK-NEXT:     #0 foo2{{.*}} {{.*}}simple_stack2.cc:20{{(:28)?}} ({{.*}})
+// CHECK-NEXT:     #1 bar2{{.*}} {{.*}}simple_stack2.cc:29{{(:3)?}} ({{.*}})
+// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack2.cc:41{{(:3)?}} ({{.*}})
diff --git a/compiler-rt/lib/tsan/lit_tests/sleep_sync.cc b/compiler-rt/lib/tsan/lit_tests/sleep_sync.cc
new file mode 100644 (file)
index 0000000..566d04b
--- /dev/null
@@ -0,0 +1,30 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <unistd.h>
+
+int X = 0;
+
+void *Thread(void *p) {
+  X = 42;
+  return 0;
+}
+
+void MySleep() {
+  usleep(100*1000);
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, 0, Thread, 0);
+  MySleep();  // Assume the thread has done the write.
+  X = 43;
+  pthread_join(t, 0);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// ...
+// CHECK:   As if synchronized via sleep:
+// CHECK-NEXT:     #0 usleep
+// CHECK-NEXT:     #1 MySleep
+// CHECK-NEXT:     #2 main
diff --git a/compiler-rt/lib/tsan/lit_tests/sleep_sync2.cc b/compiler-rt/lib/tsan/lit_tests/sleep_sync2.cc
new file mode 100644 (file)
index 0000000..9a51826
--- /dev/null
@@ -0,0 +1,22 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <unistd.h>
+
+int X = 0;
+
+void *Thread(void *p) {
+  X = 42;
+  return 0;
+}
+
+int main() {
+  pthread_t t;
+  usleep(100*1000);
+  pthread_create(&t, 0, Thread, 0);
+  X = 43;
+  pthread_join(t, 0);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK-NOT: As if synchronized via sleep
diff --git a/compiler-rt/lib/tsan/lit_tests/static_init1.cc b/compiler-rt/lib/tsan/lit_tests/static_init1.cc
new file mode 100644 (file)
index 0000000..4faf5bc
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+struct P {
+  int x;
+  int y;
+};
+
+void *Thread(void *x) {
+  static P p = {rand(), rand()};
+  if (p.x > RAND_MAX || p.y > RAND_MAX)
+    exit(1);
+  return 0;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], 0, Thread, 0);
+  pthread_create(&t[1], 0, Thread, 0);
+  pthread_join(t[0], 0);
+  pthread_join(t[1], 0);
+  printf("PASS\n");
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/static_init2.cc b/compiler-rt/lib/tsan/lit_tests/static_init2.cc
new file mode 100644 (file)
index 0000000..96ef821
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+struct Cache {
+  int x;
+  explicit Cache(int x)
+    : x(x) {
+  }
+};
+
+void foo(Cache *my) {
+  static Cache *c = my ? my : new Cache(rand());
+  if (c->x >= RAND_MAX)
+    exit(1);
+}
+
+void *Thread(void *x) {
+  foo(new Cache(rand()));
+  return 0;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], 0, Thread, 0);
+  pthread_create(&t[1], 0, Thread, 0);
+  pthread_join(t[0], 0);
+  pthread_join(t[1], 0);
+  printf("PASS\n");
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/static_init3.cc b/compiler-rt/lib/tsan/lit_tests/static_init3.cc
new file mode 100644 (file)
index 0000000..40fd4b9
--- /dev/null
@@ -0,0 +1,47 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sched.h>
+
+struct Cache {
+  int x;
+};
+
+Cache g_cache;
+
+Cache *CreateCache() {
+  g_cache.x = rand();
+  return &g_cache;
+}
+
+_Atomic(Cache*) queue;
+
+void *Thread1(void *x) {
+  static Cache *c = CreateCache();
+  __c11_atomic_store(&queue, c, 0);
+  return 0;
+}
+
+void *Thread2(void *x) {
+  Cache *c = 0;
+  for (;;) {
+    c = __c11_atomic_load(&queue, 0);
+    if (c)
+      break;
+    sched_yield();
+  }
+  if (c->x >= RAND_MAX)
+    exit(1);
+  return 0;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], 0, Thread1, 0);
+  pthread_create(&t[1], 0, Thread2, 0);
+  pthread_join(t[0], 0);
+  pthread_join(t[1], 0);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/static_init4.cc b/compiler-rt/lib/tsan/lit_tests/static_init4.cc
new file mode 100644 (file)
index 0000000..5ecc399
--- /dev/null
@@ -0,0 +1,37 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sched.h>
+
+struct Cache {
+  int x;
+  explicit Cache(int x)
+    : x(x) {
+  }
+};
+
+int g_other;
+
+Cache *CreateCache() {
+  g_other = rand();
+  return new Cache(rand());
+}
+
+void *Thread1(void *x) {
+  static Cache *c = CreateCache();
+  if (c->x == g_other)
+    exit(1);
+  return 0;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], 0, Thread1, 0);
+  pthread_create(&t[1], 0, Thread1, 0);
+  pthread_join(t[0], 0);
+  pthread_join(t[1], 0);
+  printf("PASS\n");
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/static_init5.cc b/compiler-rt/lib/tsan/lit_tests/static_init5.cc
new file mode 100644 (file)
index 0000000..9d44eb2
--- /dev/null
@@ -0,0 +1,42 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sched.h>
+
+struct Cache {
+  int x;
+  explicit Cache(int x)
+    : x(x) {
+  }
+};
+
+void *AsyncInit(void *p) {
+  return new Cache((int)(long)p);
+}
+
+Cache *CreateCache() {
+  pthread_t t;
+  pthread_create(&t, 0, AsyncInit, (void*)rand());
+  void *res;
+  pthread_join(t, &res);
+  return (Cache*)res;
+}
+
+void *Thread1(void *x) {
+  static Cache *c = CreateCache();
+  if (c->x >= RAND_MAX)
+    exit(1);
+  return 0;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], 0, Thread1, 0);
+  pthread_create(&t[1], 0, Thread1, 0);
+  pthread_join(t[0], 0);
+  pthread_join(t[1], 0);
+  printf("PASS\n");
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/suppress_same_address.cc b/compiler-rt/lib/tsan/lit_tests/suppress_same_address.cc
new file mode 100644 (file)
index 0000000..174d1cc
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+
+int X;
+
+void *Thread1(void *x) {
+  X = 42;
+  X = 66;
+  X = 78;
+  return 0;
+}
+
+void *Thread2(void *x) {
+  X = 11;
+  X = 99;
+  X = 73;
+  return 0;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, 0, Thread1, 0);
+  Thread2(0);
+  pthread_join(t, 0);
+}
+
+// CHECK: ThreadSanitizer: reported 1 warnings
diff --git a/compiler-rt/lib/tsan/lit_tests/suppress_same_stacks.cc b/compiler-rt/lib/tsan/lit_tests/suppress_same_stacks.cc
new file mode 100644 (file)
index 0000000..32bff9d
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+
+volatile int N;  // Prevent loop unrolling.
+int **data;
+
+void *Thread1(void *x) {
+  for (int i = 0; i < N; i++)
+    data[i][0] = 42;
+  return 0;
+}
+
+int main() {
+  N = 4;
+  data = new int*[N];
+  for (int i = 0; i < N; i++)
+    data[i] = new int;
+  pthread_t t;
+  pthread_create(&t, 0, Thread1, 0);
+  Thread1(0);
+  pthread_join(t, 0);
+  for (int i = 0; i < N; i++)
+    delete data[i];
+  delete[] data;
+}
+
+// CHECK: ThreadSanitizer: reported 1 warnings
diff --git a/compiler-rt/lib/tsan/lit_tests/test_output.sh b/compiler-rt/lib/tsan/lit_tests/test_output.sh
new file mode 100755 (executable)
index 0000000..e4c2a4c
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+ulimit -s 8192
+set -e # fail on any error
+
+ROOTDIR=$(dirname $0)/..
+
+# Assuming clang is in path.
+CC=clang
+CXX=clang++
+
+# TODO: add testing for all of -O0...-O3
+CFLAGS="-fthread-sanitizer -fPIE -O1 -g -fno-builtin -Wall"
+LDFLAGS="-pie -lpthread -ldl $ROOTDIR/rtl/libtsan.a"
+
+test_file() {
+  SRC=$1
+  COMPILER=$2
+  echo ----- TESTING $(basename $1)
+  OBJ=$SRC.o
+  EXE=$SRC.exe
+  $COMPILER $SRC $CFLAGS -c -o $OBJ
+  $COMPILER $OBJ $LDFLAGS -o $EXE
+  RES=$(TSAN_OPTIONS="atexit_sleep_ms=0" $EXE 2>&1 || true)
+  if [ "$3" != "" ]; then
+    printf "%s\n" "$RES"
+  fi
+  printf "%s\n" "$RES" | FileCheck $SRC
+  if [ "$3" == "" ]; then
+    rm -f $EXE $OBJ
+  fi
+}
+
+if [ "$1" == "" ]; then
+  for c in $ROOTDIR/lit_tests/*.{c,cc}; do
+    if [[ $c == */failing_* ]]; then
+      echo SKIPPING FAILING TEST $c
+      continue
+    fi
+    COMPILER=$CXX
+    case $c in
+      *.c) COMPILER=$CC
+    esac
+    test_file $c $COMPILER
+  done
+  wait
+else
+  test_file $ROOTDIR/lit_tests/$1 $CXX "DUMP"
+fi
diff --git a/compiler-rt/lib/tsan/lit_tests/thread_leak.c b/compiler-rt/lib/tsan/lit_tests/thread_leak.c
new file mode 100644 (file)
index 0000000..c5e669e
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+
+void *Thread(void *x) {
+  return 0;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, 0, Thread, 0);
+  pthread_join(t, 0);
+  printf("PASS\n");
+  return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
diff --git a/compiler-rt/lib/tsan/lit_tests/thread_leak2.c b/compiler-rt/lib/tsan/lit_tests/thread_leak2.c
new file mode 100644 (file)
index 0000000..39f6b5e
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+
+void *Thread(void *x) {
+  return 0;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, 0, Thread, 0);
+  pthread_detach(t);
+  printf("PASS\n");
+  return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
diff --git a/compiler-rt/lib/tsan/lit_tests/thread_leak3.c b/compiler-rt/lib/tsan/lit_tests/thread_leak3.c
new file mode 100644 (file)
index 0000000..c48219f
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+
+void *Thread(void *x) {
+  return 0;
+}
+
+int main() {
+  pthread_t t;
+  pthread_create(&t, 0, Thread, 0);
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: thread leak
diff --git a/compiler-rt/lib/tsan/lit_tests/tiny_race.c b/compiler-rt/lib/tsan/lit_tests/tiny_race.c
new file mode 100644 (file)
index 0000000..44cc133
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+int Global;
+void *Thread1(void *x) {
+  Global = 42;
+  return x;
+}
+int main() {
+  pthread_t t;
+  pthread_create(&t, NULL, Thread1, NULL);
+  Global = 43;
+  pthread_join(t, NULL);
+  return Global;
+}
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/virtual_inheritance_compile_bug.cc b/compiler-rt/lib/tsan/lit_tests/virtual_inheritance_compile_bug.cc
new file mode 100644 (file)
index 0000000..2275b8b
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for http://code.google.com/p/thread-sanitizer/issues/detail?id=3.
+// The C++ variant is much more compact that the LLVM IR equivalent.
+
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <stdio.h>
+struct AAA              {  virtual long aaa () { return 0; } };  // NOLINT
+struct BBB: virtual AAA { unsigned long bbb; };  // NOLINT
+struct CCC: virtual AAA { };
+struct DDD: CCC, BBB { DDD(); };  // NOLINT
+DDD::DDD()  { }
+int main() {
+  DDD d;
+  printf("OK\n");
+}
+// CHECK: OK
diff --git a/compiler-rt/lib/tsan/lit_tests/vptr_benign_race.cc b/compiler-rt/lib/tsan/lit_tests/vptr_benign_race.cc
new file mode 100644 (file)
index 0000000..8c9fc59
--- /dev/null
@@ -0,0 +1,51 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+struct A {
+  A() {
+    sem_init(&sem_, 0, 0);
+  }
+  virtual void F() {
+  }
+  void Done() {
+    sem_post(&sem_);
+  }
+  virtual ~A() {
+  }
+  sem_t sem_;
+};
+
+struct B : A {
+  virtual void F() {
+  }
+  virtual ~B() {
+    sem_wait(&sem_);
+    sem_destroy(&sem_);
+  }
+};
+
+static A *obj = new B;
+
+void *Thread1(void *x) {
+  obj->F();
+  obj->Done();
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  delete obj;
+  return NULL;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+  fprintf(stderr, "PASS\n");
+}
+// CHECK: PASS
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc b/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc
new file mode 100644 (file)
index 0000000..f51ba7e
--- /dev/null
@@ -0,0 +1,49 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+struct A {
+  A() {
+    sem_init(&sem_, 0, 0);
+  }
+  virtual void F() {
+  }
+  void Done() {
+    sem_post(&sem_);
+  }
+  virtual ~A() {
+    sem_wait(&sem_);
+    sem_destroy(&sem_);
+  }
+  sem_t sem_;
+};
+
+struct B : A {
+  virtual void F() {
+  }
+  virtual ~B() { }
+};
+
+static A *obj = new B;
+
+void *Thread1(void *x) {
+  obj->F();
+  obj->Done();
+  return NULL;
+}
+
+void *Thread2(void *x) {
+  delete obj;
+  return NULL;
+}
+
+int main() {
+  pthread_t t[2];
+  pthread_create(&t[0], NULL, Thread1, NULL);
+  pthread_create(&t[1], NULL, Thread2, NULL);
+  pthread_join(t[0], NULL);
+  pthread_join(t[1], NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/free_race.c b/compiler-rt/lib/tsan/output_tests/free_race.c
deleted file mode 100644 (file)
index fb7fbac..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
-
-int *mem;
-pthread_mutex_t mtx;
-
-void *Thread1(void *x) {
-  pthread_mutex_lock(&mtx);
-  free(mem);
-  pthread_mutex_unlock(&mtx);
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  usleep(1000000);
-  pthread_mutex_lock(&mtx);
-  mem[0] = 42;
-  pthread_mutex_unlock(&mtx);
-  return NULL;
-}
-
-int main() {
-  mem = (int*)malloc(100);
-  pthread_mutex_init(&mtx, 0);
-  pthread_t t;
-  pthread_create(&t, NULL, Thread1, NULL);
-  Thread2(0);
-  pthread_join(t, NULL);
-  pthread_mutex_destroy(&mtx);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: heap-use-after-free
-// CHECK:   Write of size 4 at {{.*}} by main thread:
-// CHECK:     #0 Thread2
-// CHECK:     #1 main
-// CHECK:   Previous write of size 8 at {{.*}} by thread 1:
-// CHECK:     #0 free
-// CHECK:     #1 Thread1
-
diff --git a/compiler-rt/lib/tsan/output_tests/free_race2.c b/compiler-rt/lib/tsan/output_tests/free_race2.c
deleted file mode 100644 (file)
index 7b2bdec..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <stdlib.h>
-
-void __attribute__((noinline)) foo(int *mem) {
-  free(mem);
-}
-
-void __attribute__((noinline)) bar(int *mem) {
-  mem[0] = 42;
-}
-
-int main() {
-  int *mem = (int*)malloc(100);
-  foo(mem);
-  bar(mem);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: heap-use-after-free
-// CHECK:   Write of size 4 at {{.*}} by main thread:
-// CHECK:     #0 bar
-// CHECK:     #1 main
-// CHECK:   Previous write of size 8 at {{.*}} by main thread:
-// CHECK:     #0 free
-// CHECK:     #1 foo
-// CHECK:     #2 main
-
diff --git a/compiler-rt/lib/tsan/output_tests/heap_race.cc b/compiler-rt/lib/tsan/output_tests/heap_race.cc
deleted file mode 100644 (file)
index e92bb37..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-
-void *Thread(void *a) {
-  ((int*)a)[0]++;
-  return NULL;
-}
-
-int main() {
-  int *p = new int(42);
-  pthread_t t;
-  pthread_create(&t, NULL, Thread, p);
-  p[0]++;
-  pthread_join(t, NULL);
-  delete p;
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/memcpy_race.cc b/compiler-rt/lib/tsan/output_tests/memcpy_race.cc
deleted file mode 100644 (file)
index c6b79a7..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <pthread.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-char *data = new char[10];
-char *data1 = new char[10];
-char *data2 = new char[10];
-
-void *Thread1(void *x) {
-  memcpy(data+5, data1, 1);
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  usleep(500*1000);
-  memcpy(data+3, data2, 4);
-  return NULL;
-}
-
-int main() {
-  fprintf(stderr, "addr=%p\n", &data[5]);
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  return 0;
-}
-
-// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK:   Write of size 1 at [[ADDR]] by thread 2:
-// CHECK:     #0 memcpy
-// CHECK:     #1 Thread2
-// CHECK:   Previous write of size 1 at [[ADDR]] by thread 1:
-// CHECK:     #0 memcpy
-// CHECK:     #1 Thread1
-
diff --git a/compiler-rt/lib/tsan/output_tests/mop_with_offset.cc b/compiler-rt/lib/tsan/output_tests/mop_with_offset.cc
deleted file mode 100644 (file)
index fc497bf..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <pthread.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <unistd.h>
-
-void *Thread1(void *x) {
-  int *p = (int*)x;
-  p[0] = 1;
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  usleep(500*1000);
-  char *p = (char*)x;
-  p[2] = 1;
-  return NULL;
-}
-
-int main() {
-  int *data = new int(42);
-  fprintf(stderr, "ptr1=%p\n", data);
-  fprintf(stderr, "ptr2=%p\n", (char*)data + 2);
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, data);
-  pthread_create(&t[1], NULL, Thread2, data);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  delete data;
-}
-
-// CHECK: ptr1=[[PTR1:0x[0-9,a-f]+]]
-// CHECK: ptr2=[[PTR2:0x[0-9,a-f]+]]
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK:   Write of size 1 at [[PTR2]] by thread 2:
-// CHECK:   Previous write of size 4 at [[PTR1]] by thread 1:
-
diff --git a/compiler-rt/lib/tsan/output_tests/mop_with_offset2.cc b/compiler-rt/lib/tsan/output_tests/mop_with_offset2.cc
deleted file mode 100644 (file)
index bbeda55..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <pthread.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <unistd.h>
-
-void *Thread1(void *x) {
-  usleep(500*1000);
-  int *p = (int*)x;
-  p[0] = 1;
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  char *p = (char*)x;
-  p[2] = 1;
-  return NULL;
-}
-
-int main() {
-  int *data = new int(42);
-  fprintf(stderr, "ptr1=%p\n", data);
-  fprintf(stderr, "ptr2=%p\n", (char*)data + 2);
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, data);
-  pthread_create(&t[1], NULL, Thread2, data);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  delete data;
-}
-
-// CHECK: ptr1=[[PTR1:0x[0-9,a-f]+]]
-// CHECK: ptr2=[[PTR2:0x[0-9,a-f]+]]
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK:   Write of size 4 at [[PTR1]] by thread 1:
-// CHECK:   Previous write of size 1 at [[PTR2]] by thread 2:
-
diff --git a/compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc b/compiler-rt/lib/tsan/output_tests/mutex_destroy_locked.cc
deleted file mode 100644 (file)
index f6ab874..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <pthread.h>
-#include <unistd.h>
-
-void *Thread(void *p) {
-  pthread_mutex_lock((pthread_mutex_t*)p);
-  return 0;
-}
-
-int main() {
-  pthread_mutex_t m;
-  pthread_mutex_init(&m, 0);
-  pthread_t t;
-  pthread_create(&t, 0, Thread, &m);
-  usleep(1000*1000);
-  pthread_mutex_destroy(&m);
-  pthread_join(t, 0);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex
-// CHECK:     #0 pthread_mutex_destroy
-// CHECK:     #1 main
-// CHECK:   and:
-// CHECK:     #0 pthread_mutex_lock
-// CHECK:     #1 Thread
-// CHECK:   Mutex {{.*}} created at:
-// CHECK:     #0 pthread_mutex_init
-// CHECK:     #1 main
-
diff --git a/compiler-rt/lib/tsan/output_tests/race_on_barrier.c b/compiler-rt/lib/tsan/output_tests/race_on_barrier.c
deleted file mode 100644 (file)
index 98d7a1d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
-
-pthread_barrier_t B;
-int Global;
-
-void *Thread1(void *x) {
-  pthread_barrier_init(&B, 0, 2);
-  pthread_barrier_wait(&B);
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  usleep(1000000);
-  pthread_barrier_wait(&B);
-  return NULL;
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, NULL, Thread1, NULL);
-  Thread2(0);
-  pthread_join(t, NULL);
-  pthread_barrier_destroy(&B);
-  return 0;
-}
-
-// CHECK:      WARNING: ThreadSanitizer: data race
-
diff --git a/compiler-rt/lib/tsan/output_tests/race_on_barrier2.c b/compiler-rt/lib/tsan/output_tests/race_on_barrier2.c
deleted file mode 100644 (file)
index dbdb6b5..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
-
-pthread_barrier_t B;
-int Global;
-
-void *Thread1(void *x) {
-  if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD)
-    pthread_barrier_destroy(&B);
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD)
-    pthread_barrier_destroy(&B);
-  return NULL;
-}
-
-int main() {
-  pthread_barrier_init(&B, 0, 2);
-  pthread_t t;
-  pthread_create(&t, NULL, Thread1, NULL);
-  Thread2(0);
-  pthread_join(t, NULL);
-  return 0;
-}
-
-// CHECK:      WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/race_on_heap.cc b/compiler-rt/lib/tsan/output_tests/race_on_heap.cc
deleted file mode 100644 (file)
index 09a461c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-void *Thread1(void *p) {
-  *(int*)p = 42;
-  return 0;
-}
-
-void *Thread2(void *p) {
-  *(int*)p = 44;
-  return 0;
-}
-
-void *alloc() {
-  return malloc(99);
-}
-
-void *AllocThread(void* arg) {
-  return alloc();
-}
-
-int main() {
-  void *p = 0;
-  pthread_t t[2];
-  pthread_create(&t[0], 0, AllocThread, 0);
-  pthread_join(t[0], &p);
-  fprintf(stderr, "addr=%p\n", p);
-  pthread_create(&t[0], 0, Thread1, (char*)p + 16);
-  pthread_create(&t[1], 0, Thread2, (char*)p + 16);
-  pthread_join(t[0], 0);
-  pthread_join(t[1], 0);
-  return 0;
-}
-
-// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
-// CHECK: WARNING: ThreadSanitizer: data race
-// ...
-// CHECK:   Location is heap block of size 99 at [[ADDR]] allocated by thread 1:
-// CHCEKL     #0 malloc
-// CHECK:     #1 alloc
-// CHECK:     #2 AllocThread
-// ...
-// CHECK:   Thread 1 (finished) created at:
-// CHECK:     #0 pthread_create
-// CHECK:     #1 main
diff --git a/compiler-rt/lib/tsan/output_tests/race_on_mutex.c b/compiler-rt/lib/tsan/output_tests/race_on_mutex.c
deleted file mode 100644 (file)
index 3ee9494..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
-
-pthread_mutex_t Mtx;
-int Global;
-
-void *Thread1(void *x) {
-  pthread_mutex_init(&Mtx, 0);
-  pthread_mutex_lock(&Mtx);
-  Global = 42;
-  pthread_mutex_unlock(&Mtx);
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  usleep(1000000);
-  pthread_mutex_lock(&Mtx);
-  Global = 43;
-  pthread_mutex_unlock(&Mtx);
-  return NULL;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  pthread_mutex_destroy(&Mtx);
-  return 0;
-}
-
-// CHECK:      WARNING: ThreadSanitizer: data race
-// CHECK-NEXT:   Read of size 1 at {{.*}} by thread 2:
-// CHECK-NEXT:     #0 pthread_mutex_lock
-// CHECK-NEXT:     #1 Thread2{{.*}} {{.*}}race_on_mutex.c:19{{(:3)?}} ({{.*}})
-// CHECK:        Previous write of size 1 at {{.*}} by thread 1:
-// CHECK-NEXT:     #0 pthread_mutex_init {{.*}} ({{.*}})
-// CHECK-NEXT:     #1 Thread1{{.*}} {{.*}}race_on_mutex.c:10{{(:3)?}} ({{.*}})
diff --git a/compiler-rt/lib/tsan/output_tests/race_with_finished_thread.cc b/compiler-rt/lib/tsan/output_tests/race_with_finished_thread.cc
deleted file mode 100644 (file)
index 1f60f4b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <pthread.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-// Ensure that we can restore a stack of a finished thread.
-
-int g_data;
-
-void __attribute__((noinline)) foobar(int *p) {
-  *p = 42;
-}
-
-void *Thread1(void *x) {
-  foobar(&g_data);
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  usleep(1000*1000);
-  g_data = 43;
-  return NULL;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK:   Write of size 4 at {{.*}} by thread 2:
-// CHECK:   Previous write of size 4 at {{.*}} by thread 1:
-// CHECK:     #0 foobar
-// CHECK:     #1 Thread1
-// CHECK:   Thread 1 (finished) created at:
-// CHECK:     #0 pthread_create
-// CHECK:     #1 main
-
diff --git a/compiler-rt/lib/tsan/output_tests/simple_race.c b/compiler-rt/lib/tsan/output_tests/simple_race.c
deleted file mode 100644 (file)
index ed831fd..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-
-int Global;
-
-void *Thread1(void *x) {
-  Global = 42;
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  Global = 43;
-  return NULL;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/simple_race.cc b/compiler-rt/lib/tsan/output_tests/simple_race.cc
deleted file mode 100644 (file)
index 8d2cabf..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-
-int Global;
-
-void *Thread1(void *x) {
-  Global++;
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  Global--;
-  return NULL;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/simple_stack.c b/compiler-rt/lib/tsan/output_tests/simple_stack.c
deleted file mode 100644 (file)
index 12c5f5e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <unistd.h>
-
-int Global;
-
-void __attribute__((noinline)) foo1() {
-  Global = 42;
-}
-
-void __attribute__((noinline)) bar1() {
-  volatile int tmp = 42; (void)tmp;
-  foo1();
-}
-
-void __attribute__((noinline)) foo2() {
-  volatile int v = Global; (void)v;
-}
-
-void __attribute__((noinline)) bar2() {
-  volatile int tmp = 42; (void)tmp;
-  foo2();
-}
-
-void *Thread1(void *x) {
-  usleep(1000000);
-  bar1();
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  bar2();
-  return NULL;
-}
-
-void StartThread(pthread_t *t, void *(*f)(void*)) {
-  pthread_create(t, NULL, f, NULL);
-}
-
-int main() {
-  pthread_t t[2];
-  StartThread(&t[0], Thread1);
-  StartThread(&t[1], Thread2);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  return 0;
-}
-
-// CHECK:      WARNING: ThreadSanitizer: data race
-// CHECK-NEXT:   Write of size 4 at {{.*}} by thread 1:
-// CHECK-NEXT:     #0 foo1{{.*}} {{.*}}simple_stack.c:8{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #1 bar1{{.*}} {{.*}}simple_stack.c:13{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #2 Thread1{{.*}} {{.*}}simple_stack.c:27{{(:3)?}} ({{.*}})
-// CHECK:        Previous read of size 4 at {{.*}} by thread 2:
-// CHECK-NEXT:     #0 foo2{{.*}} {{.*}}simple_stack.c:17{{(:26)?}} ({{.*}})
-// CHECK-NEXT:     #1 bar2{{.*}} {{.*}}simple_stack.c:22{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #2 Thread2{{.*}} {{.*}}simple_stack.c:32{{(:3)?}} ({{.*}})
-// CHECK:        Thread 1 (running) created at:
-// CHECK-NEXT:     #0 pthread_create {{.*}} ({{.*}})
-// CHECK-NEXT:     #1 StartThread{{.*}} {{.*}}simple_stack.c:37{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack.c:42{{(:3)?}} ({{.*}})
-// CHECK:        Thread 2 ({{.*}}) created at:
-// CHECK-NEXT:     #0 pthread_create {{.*}} ({{.*}})
-// CHECK-NEXT:     #1 StartThread{{.*}} {{.*}}simple_stack.c:37{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack.c:43{{(:3)?}} ({{.*}})
diff --git a/compiler-rt/lib/tsan/output_tests/simple_stack2.cc b/compiler-rt/lib/tsan/output_tests/simple_stack2.cc
deleted file mode 100644 (file)
index 5605415..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <unistd.h>
-
-int Global;
-
-void __attribute__((noinline)) foo1() {
-  Global = 42;
-}
-
-void __attribute__((noinline)) bar1() {
-  volatile int tmp = 42;
-  int tmp2 = tmp;
-  (void)tmp2;
-  foo1();
-}
-
-void __attribute__((noinline)) foo2() {
-  volatile int tmp = Global;
-  int tmp2 = tmp;
-  (void)tmp2;
-}
-
-void __attribute__((noinline)) bar2() {
-  volatile int tmp = 42;
-  int tmp2 = tmp;
-  (void)tmp2;
-  foo2();
-}
-
-void *Thread1(void *x) {
-  usleep(1000000);
-  bar1();
-  return NULL;
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, NULL, Thread1, NULL);
-  bar2();
-  pthread_join(t, NULL);
-}
-
-// CHECK:      WARNING: ThreadSanitizer: data race
-// CHECK-NEXT:   Write of size 4 at {{.*}} by thread 1:
-// CHECK-NEXT:     #0 foo1{{.*}} {{.*}}simple_stack2.cc:8{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #1 bar1{{.*}} {{.*}}simple_stack2.cc:15{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #2 Thread1{{.*}} {{.*}}simple_stack2.cc:33{{(:3)?}} ({{.*}})
-// CHECK:        Previous read of size 4 at {{.*}} by main thread:
-// CHECK-NEXT:     #0 foo2{{.*}} {{.*}}simple_stack2.cc:19{{(:28)?}} ({{.*}})
-// CHECK-NEXT:     #1 bar2{{.*}} {{.*}}simple_stack2.cc:28{{(:3)?}} ({{.*}})
-// CHECK-NEXT:     #2 main{{.*}} {{.*}}simple_stack2.cc:40{{(:3)?}} ({{.*}})
diff --git a/compiler-rt/lib/tsan/output_tests/sleep_sync.cc b/compiler-rt/lib/tsan/output_tests/sleep_sync.cc
deleted file mode 100644 (file)
index a130f15..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <pthread.h>
-#include <unistd.h>
-
-int X = 0;
-
-void *Thread(void *p) {
-  X = 42;
-  return 0;
-}
-
-void MySleep() {
-  usleep(100*1000);
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, 0, Thread, 0);
-  MySleep();  // Assume the thread has done the write.
-  X = 43;
-  pthread_join(t, 0);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
-// ...
-// CHECK:   As if synchronized via sleep:
-// CHECK-NEXT:     #0 usleep
-// CHECK-NEXT:     #1 MySleep
-// CHECK-NEXT:     #2 main
-
diff --git a/compiler-rt/lib/tsan/output_tests/sleep_sync2.cc b/compiler-rt/lib/tsan/output_tests/sleep_sync2.cc
deleted file mode 100644 (file)
index 017b9ba..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <pthread.h>
-#include <unistd.h>
-
-int X = 0;
-
-void *Thread(void *p) {
-  X = 42;
-  return 0;
-}
-
-int main() {
-  pthread_t t;
-  usleep(100*1000);
-  pthread_create(&t, 0, Thread, 0);
-  X = 43;
-  pthread_join(t, 0);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK-NOT: As if synchronized via sleep
diff --git a/compiler-rt/lib/tsan/output_tests/static_init1.cc b/compiler-rt/lib/tsan/output_tests/static_init1.cc
deleted file mode 100644 (file)
index 75d2819..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-struct P {
-  int x;
-  int y;
-};
-
-void *Thread(void *x) {
-  static P p = {rand(), rand()};
-  if (p.x > RAND_MAX || p.y > RAND_MAX)
-    exit(1);
-  return 0;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], 0, Thread, 0);
-  pthread_create(&t[1], 0, Thread, 0);
-  pthread_join(t[0], 0);
-  pthread_join(t[1], 0);
-}
-
-// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/static_init2.cc b/compiler-rt/lib/tsan/output_tests/static_init2.cc
deleted file mode 100644 (file)
index 8d41061..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-struct Cache {
-  int x;
-  explicit Cache(int x)
-    : x(x) {
-  }
-};
-
-void foo(Cache *my) {
-  static Cache *c = my ? my : new Cache(rand());
-  if (c->x >= RAND_MAX)
-    exit(1);
-}
-
-void *Thread(void *x) {
-  foo(new Cache(rand()));
-  return 0;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], 0, Thread, 0);
-  pthread_create(&t[1], 0, Thread, 0);
-  pthread_join(t[0], 0);
-  pthread_join(t[1], 0);
-}
-
-// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/static_init3.cc b/compiler-rt/lib/tsan/output_tests/static_init3.cc
deleted file mode 100644 (file)
index 718f811..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sched.h>
-
-struct Cache {
-  int x;
-};
-
-Cache g_cache;
-
-Cache *CreateCache() {
-  g_cache.x = rand();
-  return &g_cache;
-}
-
-_Atomic(Cache*) queue;
-
-void *Thread1(void *x) {
-  static Cache *c = CreateCache();
-  __c11_atomic_store(&queue, c, 0);
-  return 0;
-}
-
-void *Thread2(void *x) {
-  Cache *c = 0;
-  for (;;) {
-    c = __c11_atomic_load(&queue, 0);
-    if (c)
-      break;
-    sched_yield();
-  }
-  if (c->x >= RAND_MAX)
-    exit(1);
-  return 0;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], 0, Thread1, 0);
-  pthread_create(&t[1], 0, Thread2, 0);
-  pthread_join(t[0], 0);
-  pthread_join(t[1], 0);
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/static_init4.cc b/compiler-rt/lib/tsan/output_tests/static_init4.cc
deleted file mode 100644 (file)
index 175d464..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sched.h>
-
-struct Cache {
-  int x;
-  explicit Cache(int x)
-    : x(x) {
-  }
-};
-
-int g_other;
-
-Cache *CreateCache() {
-  g_other = rand();
-  return new Cache(rand());
-}
-
-void *Thread1(void *x) {
-  static Cache *c = CreateCache();
-  if (c->x == g_other)
-    exit(1);
-  return 0;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], 0, Thread1, 0);
-  pthread_create(&t[1], 0, Thread1, 0);
-  pthread_join(t[0], 0);
-  pthread_join(t[1], 0);
-}
-
-// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/static_init5.cc b/compiler-rt/lib/tsan/output_tests/static_init5.cc
deleted file mode 100644 (file)
index 89c1137..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sched.h>
-
-struct Cache {
-  int x;
-  explicit Cache(int x)
-    : x(x) {
-  }
-};
-
-void *AsyncInit(void *p) {
-  return new Cache((int)(long)p);
-}
-
-Cache *CreateCache() {
-  pthread_t t;
-  pthread_create(&t, 0, AsyncInit, (void*)rand());
-  void *res;
-  pthread_join(t, &res);
-  return (Cache*)res;
-}
-
-void *Thread1(void *x) {
-  static Cache *c = CreateCache();
-  if (c->x >= RAND_MAX)
-    exit(1);
-  return 0;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], 0, Thread1, 0);
-  pthread_create(&t[1], 0, Thread1, 0);
-  pthread_join(t[0], 0);
-  pthread_join(t[1], 0);
-}
-
-// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/suppress_same_address.cc b/compiler-rt/lib/tsan/output_tests/suppress_same_address.cc
deleted file mode 100644 (file)
index 6e98970..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <pthread.h>
-
-int X;
-
-void *Thread1(void *x) {
-  X = 42;
-  X = 66;
-  X = 78;
-  return 0;
-}
-
-void *Thread2(void *x) {
-  X = 11;
-  X = 99;
-  X = 73;
-  return 0;
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, 0, Thread1, 0);
-  Thread2(0);
-  pthread_join(t, 0);
-}
-
-// CHECK: ThreadSanitizer: reported 1 warnings
-
diff --git a/compiler-rt/lib/tsan/output_tests/suppress_same_stacks.cc b/compiler-rt/lib/tsan/output_tests/suppress_same_stacks.cc
deleted file mode 100644 (file)
index 6046a4e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <pthread.h>
-
-volatile int N;  // Prevent loop unrolling.
-int **data;
-
-void *Thread1(void *x) {
-  for (int i = 0; i < N; i++)
-    data[i][0] = 42;
-  return 0;
-}
-
-int main() {
-  N = 4;
-  data = new int*[N];
-  for (int i = 0; i < N; i++)
-    data[i] = new int;
-  pthread_t t;
-  pthread_create(&t, 0, Thread1, 0);
-  Thread1(0);
-  pthread_join(t, 0);
-  for (int i = 0; i < N; i++)
-    delete data[i];
-  delete[] data;
-}
-
-// CHECK: ThreadSanitizer: reported 1 warnings
-
diff --git a/compiler-rt/lib/tsan/output_tests/test_output.sh b/compiler-rt/lib/tsan/output_tests/test_output.sh
deleted file mode 100755 (executable)
index bd9cd91..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-ulimit -s 8192
-set -e # fail on any error
-
-ROOTDIR=$(dirname $0)/..
-
-# Assuming clang is in path.
-CC=clang
-CXX=clang++
-
-# TODO: add testing for all of -O0...-O3
-CFLAGS="-fthread-sanitizer -fPIE -O1 -g -fno-builtin -Wall"
-LDFLAGS="-pie -lpthread -ldl $ROOTDIR/rtl/libtsan.a"
-
-test_file() {
-  SRC=$1
-  COMPILER=$2
-  echo ----- TESTING $(basename $1)
-  OBJ=$SRC.o
-  EXE=$SRC.exe
-  $COMPILER $SRC $CFLAGS -c -o $OBJ
-  $COMPILER $OBJ $LDFLAGS -o $EXE
-  RES=$(TSAN_OPTIONS="atexit_sleep_ms=0" $EXE 2>&1 || true)
-  if [ "$3" != "" ]; then
-    printf "%s\n" "$RES"
-  fi
-  printf "%s\n" "$RES" | FileCheck $SRC
-  if [ "$3" == "" ]; then
-    rm -f $EXE $OBJ
-  fi
-}
-
-if [ "$1" == "" ]; then
-  for c in $ROOTDIR/output_tests/*.{c,cc}; do
-    if [[ $c == */failing_* ]]; then
-      echo SKIPPING FAILING TEST $c
-      continue
-    fi
-    COMPILER=$CXX
-    case $c in
-      *.c) COMPILER=$CC
-    esac
-    test_file $c $COMPILER
-  done
-  wait
-else
-  test_file $ROOTDIR/output_tests/$1 $CXX "DUMP"
-fi
diff --git a/compiler-rt/lib/tsan/output_tests/thread_leak.c b/compiler-rt/lib/tsan/output_tests/thread_leak.c
deleted file mode 100644 (file)
index 88a11be..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <pthread.h>
-
-void *Thread(void *x) {
-  return 0;
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, 0, Thread, 0);
-  pthread_join(t, 0);
-  return 0;
-}
-
-// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
-
diff --git a/compiler-rt/lib/tsan/output_tests/thread_leak2.c b/compiler-rt/lib/tsan/output_tests/thread_leak2.c
deleted file mode 100644 (file)
index 71e9c50..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <pthread.h>
-
-void *Thread(void *x) {
-  return 0;
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, 0, Thread, 0);
-  pthread_detach(t);
-  return 0;
-}
-
-// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
-
diff --git a/compiler-rt/lib/tsan/output_tests/thread_leak3.c b/compiler-rt/lib/tsan/output_tests/thread_leak3.c
deleted file mode 100644 (file)
index 058b6e5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <pthread.h>
-
-void *Thread(void *x) {
-  return 0;
-}
-
-int main() {
-  pthread_t t;
-  pthread_create(&t, 0, Thread, 0);
-  return 0;
-}
-
-// CHECK: WARNING: ThreadSanitizer: thread leak
-
diff --git a/compiler-rt/lib/tsan/output_tests/tiny_race.c b/compiler-rt/lib/tsan/output_tests/tiny_race.c
deleted file mode 100644 (file)
index 3a8d192..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <pthread.h>
-int Global;
-void *Thread1(void *x) {
-  Global = 42;
-  return x;
-}
-int main() {
-  pthread_t t;
-  pthread_create(&t, NULL, Thread1, NULL);
-  Global = 43;
-  pthread_join(t, NULL);
-  return Global;
-}
-// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/virtual_inheritance_compile_bug.cc b/compiler-rt/lib/tsan/output_tests/virtual_inheritance_compile_bug.cc
deleted file mode 100644 (file)
index 6198e8a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Regression test for http://code.google.com/p/thread-sanitizer/issues/detail?id=3.
-// The C++ variant is much more compact that the LLVM IR equivalent.
-#include <stdio.h>
-struct AAA              {  virtual long aaa () { return 0; } };  // NOLINT
-struct BBB: virtual AAA { unsigned long bbb; };  // NOLINT
-struct CCC: virtual AAA { };
-struct DDD: CCC, BBB { DDD(); };  // NOLINT
-DDD::DDD()  { }
-int main() {
-  DDD d;
-  printf("OK\n");
-}
-// CHECK: OK
diff --git a/compiler-rt/lib/tsan/output_tests/vptr_benign_race.cc b/compiler-rt/lib/tsan/output_tests/vptr_benign_race.cc
deleted file mode 100644 (file)
index fec4ffb..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <pthread.h>
-#include <semaphore.h>
-#include <stdio.h>
-
-struct A {
-  A() {
-    sem_init(&sem_, 0, 0);
-  }
-  virtual void F() {
-  }
-  void Done() {
-    sem_post(&sem_);
-  }
-  virtual ~A() {
-  }
-  sem_t sem_;
-};
-
-struct B : A {
-  virtual void F() {
-  }
-  virtual ~B() {
-    sem_wait(&sem_);
-    sem_destroy(&sem_);
-  }
-};
-
-static A *obj = new B;
-
-void *Thread1(void *x) {
-  obj->F();
-  obj->Done();
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  delete obj;
-  return NULL;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-  fprintf(stderr, "PASS\n");
-}
-// CHECK: PASS
-// CHECK-NOT: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/output_tests/vptr_harmful_race.cc b/compiler-rt/lib/tsan/output_tests/vptr_harmful_race.cc
deleted file mode 100644 (file)
index a19e6ab..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <pthread.h>
-#include <semaphore.h>
-#include <stdio.h>
-
-struct A {
-  A() {
-    sem_init(&sem_, 0, 0);
-  }
-  virtual void F() {
-  }
-  void Done() {
-    sem_post(&sem_);
-  }
-  virtual ~A() {
-    sem_wait(&sem_);
-    sem_destroy(&sem_);
-  }
-  sem_t sem_;
-};
-
-struct B : A {
-  virtual void F() {
-  }
-  virtual ~B() { }
-};
-
-static A *obj = new B;
-
-void *Thread1(void *x) {
-  obj->F();
-  obj->Done();
-  return NULL;
-}
-
-void *Thread2(void *x) {
-  delete obj;
-  return NULL;
-}
-
-int main() {
-  pthread_t t[2];
-  pthread_create(&t[0], NULL, Thread1, NULL);
-  pthread_create(&t[1], NULL, Thread2, NULL);
-  pthread_join(t[0], NULL);
-  pthread_join(t[1], NULL);
-}
-
-// CHECK: WARNING: ThreadSanitizer: data race