================
@@ -9822,6 +9824,50 @@ void Sema::CheckMaxUnsignedZero(const CallExpr *Call,
         << FixItHint::CreateRemoval(RemovalRange);
 }
 
+//===--- CHECK: Warn on use of `std::atomic_thread_fence` with TSan. 
------===//
+void Sema::CheckUseOfAtomicThreadFenceWithTSan(const CallExpr *Call,
+                                               const FunctionDecl *FDecl) {
+  // Thread sanitizer currently does not support `std::atomic_thread_fence`,
+  // leading to false positives. Example issue:
+  // https://github.com/llvm/llvm-project/issues/52942
+
+  if (!Call || !FDecl)
+    return;
+
+  if (!IsStdFunction(FDecl, "atomic_thread_fence"))
+    return;
+
+  // Check that TSan is enabled in this context
+  const auto EnabledTSanMask =
+      Context.getLangOpts().Sanitize.Mask & (SanitizerKind::Thread);
+  if (!EnabledTSanMask)
+    return;
+
+  // Check that the file isn't in the no-sanitize list
+  const auto &NoSanitizeList = Context.getNoSanitizeList();
+  if (NoSanitizeList.containsLocation(EnabledTSanMask,
+                                      Call->getSourceRange().getBegin()))
+    return;
+
+  // Check that the calling function:
+  //  - Does not have any attributes preventing TSan checking
+  //  - Is not in the ignore list
+  if (const NamedDecl *Caller = getCurFunctionOrMethodDecl()) {
+    if (Caller->hasAttr<DisableSanitizerInstrumentationAttr>())
+      return;
+
+    for (const auto *Attr : Caller->specific_attrs<NoSanitizeAttr>())
+      if (Attr->getMask() & SanitizerKind::Thread)
+        return;
+
+    if (NoSanitizeList.containsFunction(EnabledTSanMask,
+                                        Caller->getQualifiedNameAsString()))
----------------
AaronBallman wrote:

We should have a test that this works. e.g.,
```
struct S {
  void func(int) {
    std::atomic_thread_fence(std::memory_order_relaxed);
  }
  void func(float) {
    std::atomic_thread_fence(std::memory_order_relaxed);
  }
};
```
(I don't know the answer to this, but should the ignore list have `S::func` and 
silence both, or does it support something like `S::func(float)` to silence one 
but not the other? Or perhaps use a mangled name instead of the qualified name? 
Does the qualified name need to support `::foo::bar` as well as `foo::bar`?)

https://github.com/llvm/llvm-project/pull/166542
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to