Skip to content

Commit 8710387

Browse files
authored
Thread Safety Analysis: Fix pointer handling of variables with deprecated attributes (#148974)
de10e44 ("Thread Safety Analysis: Support warning on passing/returning pointers to guarded variables") added checks for passing pointer to guarded variables. While new features do not necessarily need to support the deprecated attributes (`guarded_var`, and `pt_guarded_var`), we need to ensure that such features do not cause the compiler to crash. As such, code such as this: struct { int v __attribute__((guarded_var)); } p; int *g() { return &p.v; // handleNoMutexHeld() with POK_ReturnPointer } Would crash in debug builds with the assertion in handleNoMutexHeld() triggering. The assertion is meant to capture the fact that this helper should only be used for warnings on variables (which the deprecated attributes only applied to). To fix, the function handleNoMutexHeld() should handle all POK cases that apply to variables explicitly, and produce a best-effort warning. We refrain from introducing new warnings to avoid unnecessary code bloat for deprecated features. Fixes: #140330
1 parent 5480fc6 commit 8710387

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,11 +2112,26 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
21122112

21132113
void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
21142114
AccessKind AK, SourceLocation Loc) override {
2115-
assert((POK == POK_VarAccess || POK == POK_VarDereference) &&
2116-
"Only works for variables");
2117-
unsigned DiagID = POK == POK_VarAccess?
2118-
diag::warn_variable_requires_any_lock:
2119-
diag::warn_var_deref_requires_any_lock;
2115+
unsigned DiagID = 0;
2116+
switch (POK) {
2117+
case POK_VarAccess:
2118+
case POK_PassByRef:
2119+
case POK_ReturnByRef:
2120+
case POK_PassPointer:
2121+
case POK_ReturnPointer:
2122+
DiagID = diag::warn_variable_requires_any_lock;
2123+
break;
2124+
case POK_VarDereference:
2125+
case POK_PtPassByRef:
2126+
case POK_PtReturnByRef:
2127+
case POK_PtPassPointer:
2128+
case POK_PtReturnPointer:
2129+
DiagID = diag::warn_var_deref_requires_any_lock;
2130+
break;
2131+
case POK_FunctionCall:
2132+
llvm_unreachable("Only works for variables");
2133+
break;
2134+
}
21202135
PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
21212136
<< D << getLockKindFromAccessKind(AK));
21222137
Warnings.emplace_back(std::move(Warning), getNotes());

clang/test/SemaCXX/warn-thread-safety-analysis.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6196,6 +6196,8 @@ class Return {
61966196
Mutex mu;
61976197
Foo foo GUARDED_BY(mu);
61986198
Foo* foo_ptr PT_GUARDED_BY(mu);
6199+
Foo foo_depr GUARDED_VAR; // test deprecated attribute
6200+
Foo* foo_ptr_depr PT_GUARDED_VAR; // test deprecated attribute
61996201

62006202
Foo returns_value_locked() {
62016203
MutexLock lock(&mu);
@@ -6297,6 +6299,18 @@ class Return {
62976299
return *foo_ptr; // expected-warning {{returning the value that 'foo_ptr' points to by reference requires holding mutex 'mu' exclusively}}
62986300
}
62996301

6302+
Foo *returns_ptr_deprecated() {
6303+
return &foo_depr; // expected-warning {{writing variable 'foo_depr' requires holding any mutex exclusively}}
6304+
}
6305+
6306+
Foo *returns_pt_ptr_deprecated() {
6307+
return foo_ptr_depr; // expected-warning {{writing the value pointed to by 'foo_ptr_depr' requires holding any mutex exclusively}}
6308+
}
6309+
6310+
Foo &returns_ref_deprecated() {
6311+
return *foo_ptr_depr; // expected-warning {{writing the value pointed to by 'foo_ptr_depr' requires holding any mutex exclusively}}
6312+
}
6313+
63006314
// FIXME: Basic alias analysis would help catch cases like below.
63016315
Foo *returns_ptr_alias() {
63026316
mu.Lock();

0 commit comments

Comments
 (0)