diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c --- a/compiler-rt/lib/profile/GCDAProfiling.c +++ b/compiler-rt/lib/profile/GCDAProfiling.c @@ -628,8 +628,14 @@ } } -COMPILER_RT_VISIBILITY -void llvm_delete_writeout_function_list(void) { +#ifndef _WIN32 +// __attribute__((destructor)) and destructors whose priorities are greater than +// 100 run before this function and can thus be tracked. The priority is +// compatible with GCC 7 onwards. +__attribute__((destructor(100))) +#endif +static void llvm_writeout_and_clear(void) { + llvm_writeout_files(); fn_list_remove(&writeout_fn_list); } @@ -710,8 +716,9 @@ /* Make sure we write out the data and delete the data structures. */ atexit(llvm_delete_reset_function_list); atexit(llvm_delete_flush_function_list); - atexit(llvm_delete_writeout_function_list); - atexit(llvm_writeout_files); +#ifdef _WIN32 + atexit(llvm_writeout_and_clear); +#endif } } diff --git a/compiler-rt/test/profile/Posix/gcov-destructor.c b/compiler-rt/test/profile/Posix/gcov-destructor.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/Posix/gcov-destructor.c @@ -0,0 +1,33 @@ +/// Test that destructors and destructors whose priorities are greater than 100 are tracked. +// RUN: mkdir -p %t.dir && cd %t.dir +// RUN: %clang --coverage %s -o %t +// RUN: rm -f gcov-destructor.gcda && %run %t +// RUN: llvm-cov gcov -t gcov-destructor.gcda | FileCheck %s + +#include + +void before_exec() {} // CHECK: 1: [[#@LINE]]:void before_exec +void after_exec() {} // CHECK-NEXT: 1: [[#@LINE]]:void after_exec + +__attribute__((constructor)) // CHECK: -: [[#@LINE]]:__attribute__ +void constructor() {} // CHECK-NEXT: 1: [[#@LINE]]: + +/// Runs before __llvm_gcov_writeout. +__attribute__((destructor)) // CHECK: -: [[#@LINE]]:__attribute__ +void destructor() {} // CHECK-NEXT: 1: [[#@LINE]]: + +__attribute__((destructor(101))) // CHECK: -: [[#@LINE]]:__attribute__ +void destructor_101() {} // CHECK-NEXT: 1: [[#@LINE]]: + +/// Runs after __llvm_gcov_writeout. +__attribute__((destructor(99))) // CHECK: -: [[#@LINE]]:__attribute__ +void destructor_99() {} // CHECK-NEXT: #####: [[#@LINE]]: + +int main() { + before_exec(); + // Implicit writeout. + execl("/not_exist", "not_exist", (char *)0); + // Still tracked. + after_exec(); + return 0; +}