diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 5e75c64eb2b9a..5eba024e83634 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2112,11 +2112,26 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, AccessKind AK, SourceLocation Loc) override { - assert((POK == POK_VarAccess || POK == POK_VarDereference) && - "Only works for variables"); - unsigned DiagID = POK == POK_VarAccess? - diag::warn_variable_requires_any_lock: - diag::warn_var_deref_requires_any_lock; + unsigned DiagID = 0; + switch (POK) { + case POK_VarAccess: + case POK_PassByRef: + case POK_ReturnByRef: + case POK_PassPointer: + case POK_ReturnPointer: + DiagID = diag::warn_variable_requires_any_lock; + break; + case POK_VarDereference: + case POK_PtPassByRef: + case POK_PtReturnByRef: + case POK_PtPassPointer: + case POK_PtReturnPointer: + DiagID = diag::warn_var_deref_requires_any_lock; + break; + case POK_FunctionCall: + llvm_unreachable("Only works for variables"); + break; + } PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << D << getLockKindFromAccessKind(AK)); Warnings.emplace_back(std::move(Warning), getNotes()); diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index d64ed1e5f260a..d82e2484ace1e 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -6196,6 +6196,8 @@ class Return { Mutex mu; Foo foo GUARDED_BY(mu); Foo* foo_ptr PT_GUARDED_BY(mu); + Foo foo_depr GUARDED_VAR; // test deprecated attribute + Foo* foo_ptr_depr PT_GUARDED_VAR; // test deprecated attribute Foo returns_value_locked() { MutexLock lock(&mu); @@ -6297,6 +6299,18 @@ class Return { return *foo_ptr; // expected-warning {{returning the value that 'foo_ptr' points to by reference requires holding mutex 'mu' exclusively}} } + Foo *returns_ptr_deprecated() { + return &foo_depr; // expected-warning {{writing variable 'foo_depr' requires holding any mutex exclusively}} + } + + Foo *returns_pt_ptr_deprecated() { + return foo_ptr_depr; // expected-warning {{writing the value pointed to by 'foo_ptr_depr' requires holding any mutex exclusively}} + } + + Foo &returns_ref_deprecated() { + return *foo_ptr_depr; // expected-warning {{writing the value pointed to by 'foo_ptr_depr' requires holding any mutex exclusively}} + } + // FIXME: Basic alias analysis would help catch cases like below. Foo *returns_ptr_alias() { mu.Lock();