1*bcaeed49SFangrui Song // RUN: %clangxx_tsan -O1 --std=c++11 %s -o %t && %run %t 2>&1 | FileCheck %s 2*bcaeed49SFangrui Song #include "custom_mutex.h" 3*bcaeed49SFangrui Song 4*bcaeed49SFangrui Song #include <type_traits> 5*bcaeed49SFangrui Song 6*bcaeed49SFangrui Song // Test that the destruction events of a mutex are ignored when the 7*bcaeed49SFangrui Song // annotations request this. 8*bcaeed49SFangrui Song // 9*bcaeed49SFangrui Song // Use after destruction is UB, but __tsan_mutex_linker_init and 10*bcaeed49SFangrui Song // __tsan_mutex_not_static exist to support global variables of mutex type, 11*bcaeed49SFangrui Song // which might be accessed during program shutdown after the class's destructor 12*bcaeed49SFangrui Song // has run. 13*bcaeed49SFangrui Song main()14*bcaeed49SFangrui Songint main() { 15*bcaeed49SFangrui Song std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu1_store; 16*bcaeed49SFangrui Song Mutex* mu1 = reinterpret_cast<Mutex*>(&mu1_store); 17*bcaeed49SFangrui Song new(&mu1_store) Mutex(false, __tsan_mutex_linker_init); 18*bcaeed49SFangrui Song mu1->Lock(); 19*bcaeed49SFangrui Song mu1->~Mutex(); 20*bcaeed49SFangrui Song mu1->Unlock(); 21*bcaeed49SFangrui Song 22*bcaeed49SFangrui Song std::aligned_storage<sizeof(Mutex), alignof(Mutex)>::type mu2_store; 23*bcaeed49SFangrui Song Mutex* mu2 = reinterpret_cast<Mutex*>(&mu2_store); 24*bcaeed49SFangrui Song new(&mu2_store) Mutex(false, 0, __tsan_mutex_not_static); 25*bcaeed49SFangrui Song mu2->Lock(); 26*bcaeed49SFangrui Song mu2->~Mutex(); 27*bcaeed49SFangrui Song mu2->Unlock(); 28*bcaeed49SFangrui Song 29*bcaeed49SFangrui Song fprintf(stderr, "DONE\n"); 30*bcaeed49SFangrui Song return 0; 31*bcaeed49SFangrui Song } 32*bcaeed49SFangrui Song 33*bcaeed49SFangrui Song // CHECK: DONE 34