aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafety.cpp
diff options
context:
space:
mode:
authorMarco Elver <elver@google.com>2025-02-16 12:42:06 +0100
committerMarco Elver <elver@google.com>2025-02-26 16:34:33 +0100
commitde10e44b6fe7f3d3cfde3afd8e1222d251172ade (patch)
tree59669623b492a4a5f3cc45ee8c1a8620e45356a9 /clang/lib/Analysis/ThreadSafety.cpp
parent3c8c0d4d8d9bbc160d160e683f7a74fd28574dc6 (diff)
downloadllvm-de10e44b6fe7f3d3cfde3afd8e1222d251172ade.zip
llvm-de10e44b6fe7f3d3cfde3afd8e1222d251172ade.tar.gz
llvm-de10e44b6fe7f3d3cfde3afd8e1222d251172ade.tar.bz2
Thread Safety Analysis: Support warning on passing/returning pointers to guarded variables
Introduce `-Wthread-safety-pointer` to warn when passing or returning pointers to guarded variables or guarded data. This is is analogous to `-Wthread-safety-reference`, which performs similar checks for C++ references. Adding checks for pointer passing is required to avoid false negatives in large C codebases, where data structures are typically implemented through helpers that take pointers to instances of a data structure. The feature is planned to be enabled by default under `-Wthread-safety` in the next release cycle. This gives time for early adopters to address new findings. Pull Request: https://github.com/llvm/llvm-project/pull/127396
Diffstat (limited to 'clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 1bad4eac..6b5b493 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1794,11 +1794,24 @@ void ThreadSafetyAnalyzer::checkPtAccess(const FactSet &FSet, const Expr *Exp,
}
}
- // Pass by reference warnings are under a different flag.
+ // Pass by reference/pointer warnings are under a different flag.
ProtectedOperationKind PtPOK = POK_VarDereference;
- if (POK == POK_PassByRef) PtPOK = POK_PtPassByRef;
- if (POK == POK_ReturnByRef)
+ switch (POK) {
+ case POK_PassByRef:
+ PtPOK = POK_PtPassByRef;
+ break;
+ case POK_ReturnByRef:
PtPOK = POK_PtReturnByRef;
+ break;
+ case POK_PassPointer:
+ PtPOK = POK_PtPassPointer;
+ break;
+ case POK_ReturnPointer:
+ PtPOK = POK_PtReturnPointer;
+ break;
+ default:
+ break;
+ }
const ValueDecl *D = getValueDecl(Exp);
if (!D || !D->hasAttrs())
@@ -2145,6 +2158,8 @@ void BuildLockset::examineArguments(const FunctionDecl *FD,
QualType Qt = (*Param)->getType();
if (Qt->isReferenceType())
checkAccess(*Arg, AK_Read, POK_PassByRef);
+ else if (Qt->isPointerType())
+ checkPtAccess(*Arg, AK_Read, POK_PassPointer);
}
}
@@ -2286,8 +2301,8 @@ void BuildLockset::VisitReturnStmt(const ReturnStmt *S) {
if (!RetVal)
return;
- // If returning by reference, check that the function requires the appropriate
- // capabilities.
+ // If returning by reference or pointer, check that the function requires the
+ // appropriate capabilities.
const QualType ReturnType =
Analyzer->CurrentFunction->getReturnType().getCanonicalType();
if (ReturnType->isLValueReferenceType()) {
@@ -2295,6 +2310,11 @@ void BuildLockset::VisitReturnStmt(const ReturnStmt *S) {
FunctionExitFSet, RetVal,
ReturnType->getPointeeType().isConstQualified() ? AK_Read : AK_Written,
POK_ReturnByRef);
+ } else if (ReturnType->isPointerType()) {
+ Analyzer->checkPtAccess(
+ FunctionExitFSet, RetVal,
+ ReturnType->getPointeeType().isConstQualified() ? AK_Read : AK_Written,
+ POK_ReturnPointer);
}
}