
This PR is based on my last PR #132752 (the first commit of this PR), but addressing a different issue. This commit addresses the limitation in `PointerMayBeCaptured` analysis when dealing with derived pointers (e.g. arr+1) as described in issue #132739. The current implementation of `PointerMayBeCaptured` may miss captures of the underlying `alloca` when analyzing derived pointers, leading to some FNs in TSan, as follows: ```cpp void *Thread(void *a) { ((int*)a)[1] = 43; return 0; } int main() { int Arr[2] = {41, 42}; pthread_t t; pthread_create(&t, 0, Thread, &Arr[0]); // Missed instrumentation here due to the FN of PointerMayBeCaptured Arr[1] = 43; barrier_wait(&barrier); pthread_join(t, 0); } ``` Refer to this [godbolt page](https://godbolt.org/z/n67GrxdcE) to get the compilation result of TSan. Even when `PointerMayBeCaptured` working correctly, it should backtrack to the original `alloca` firstly during analysis, causing redundancy to the outer's `findAllocaForValue`. ```cpp const AllocaInst *AI = findAllocaForValue(Addr); // Instead of Addr, we should check whether its base pointer is captured. if (AI && !PointerMayBeCaptured(Addr, true)) ... ``` Key changes: Directly analyze the capture status of the underlying `alloca` instead of derived pointers to ensure accurate capture detection ```cpp const AllocaInst *AI = findAllocaForValue(Addr); // Instead of Addr, we should check whether its base pointer is captured. if (AI && !PointerMayBeCaptured(AI, true)) ... ```
22 lines
458 B
C++
22 lines
458 B
C++
// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
|
|
#include "test.h"
|
|
|
|
void *Thread(void *a) {
|
|
barrier_wait(&barrier);
|
|
((int *)a)[1] = 43;
|
|
return 0;
|
|
}
|
|
|
|
int main() {
|
|
barrier_init(&barrier, 2);
|
|
int Arr[2] = {41, 42};
|
|
pthread_t t;
|
|
pthread_create(&t, 0, Thread, &Arr[0]);
|
|
Arr[1] = 43;
|
|
barrier_wait(&barrier);
|
|
pthread_join(t, 0);
|
|
}
|
|
|
|
// CHECK: WARNING: ThreadSanitizer: data race
|
|
// CHECK: Location is stack of main thread.
|