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