diff options
author | Marco Elver <elver@google.com> | 2025-02-16 12:42:06 +0100 |
---|---|---|
committer | Marco Elver <elver@google.com> | 2025-02-26 16:34:33 +0100 |
commit | de10e44b6fe7f3d3cfde3afd8e1222d251172ade (patch) | |
tree | 59669623b492a4a5f3cc45ee8c1a8620e45356a9 /clang/lib/Analysis/ThreadSafety.cpp | |
parent | 3c8c0d4d8d9bbc160d160e683f7a74fd28574dc6 (diff) | |
download | llvm-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.cpp | 30 |
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); } } |