aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafety.cpp
diff options
context:
space:
mode:
authorAaron Puchert <aaronpuchert@alice-dsl.net>2025-04-15 23:21:34 +0200
committerGitHub <noreply@github.com>2025-04-15 23:21:34 +0200
commit9c73eba8aa17cb7ca4248ab1c7f67ea7ec9b50b1 (patch)
tree9a73317d6a54d5d607a9d59e6e1990341534ac90 /clang/lib/Analysis/ThreadSafety.cpp
parentd30a5b41fe72a1dd83714d3e21fd539b91e63c8c (diff)
downloadllvm-9c73eba8aa17cb7ca4248ab1c7f67ea7ec9b50b1.zip
llvm-9c73eba8aa17cb7ca4248ab1c7f67ea7ec9b50b1.tar.gz
llvm-9c73eba8aa17cb7ca4248ab1c7f67ea7ec9b50b1.tar.bz2
Merge similar Clang Thread Safety attributes (#135561)
Some of the old lock-based and new capability-based spellings behave basically in the same way, so merging them simplifies the code significantly. There are two minor functional changes: we only warn (instead of an error) when the try_acquire_capability attribute is used on something else than a function. The alternative would have been to produce an error for the old spelling, but we seem to only warn for all function attributes, so this is arguably more consistent. The second change is that we also check the first argument (which is the value returned for a successful try-acquire) for `this`. But from what I can tell, this code is defunct anyway at the moment (see #31414).
Diffstat (limited to 'clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp60
1 files changed, 5 insertions, 55 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 6b5b493..42fb0fe 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1511,38 +1511,17 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
return;
auto *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
- if(!FunDecl || !FunDecl->hasAttrs())
+ if (!FunDecl || !FunDecl->hasAttr<TryAcquireCapabilityAttr>())
return;
CapExprSet ExclusiveLocksToAdd;
CapExprSet SharedLocksToAdd;
// If the condition is a call to a Trylock function, then grab the attributes
- for (const auto *Attr : FunDecl->attrs()) {
- switch (Attr->getKind()) {
- case attr::TryAcquireCapability: {
- auto *A = cast<TryAcquireCapabilityAttr>(Attr);
- getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
- Exp, FunDecl, PredBlock, CurrBlock, A->getSuccessValue(),
- Negate);
- break;
- };
- case attr::ExclusiveTrylockFunction: {
- const auto *A = cast<ExclusiveTrylockFunctionAttr>(Attr);
- getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl, PredBlock, CurrBlock,
- A->getSuccessValue(), Negate);
- break;
- }
- case attr::SharedTrylockFunction: {
- const auto *A = cast<SharedTrylockFunctionAttr>(Attr);
- getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl, PredBlock, CurrBlock,
- A->getSuccessValue(), Negate);
- break;
- }
- default:
- break;
- }
- }
+ for (const auto *Attr : FunDecl->specific_attrs<TryAcquireCapabilityAttr>())
+ getMutexIDs(Attr->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, Attr,
+ Exp, FunDecl, PredBlock, CurrBlock, Attr->getSuccessValue(),
+ Negate);
// Add and remove locks.
SourceLocation Loc = Exp->getExprLoc();
@@ -1882,29 +1861,6 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
// An assert will add a lock to the lockset, but will not generate
// a warning if it is already there, and will not generate a warning
// if it is not removed.
- case attr::AssertExclusiveLock: {
- const auto *A = cast<AssertExclusiveLockAttr>(At);
-
- CapExprSet AssertLocks;
- Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self);
- for (const auto &AssertLock : AssertLocks)
- Analyzer->addLock(
- FSet, std::make_unique<LockableFactEntry>(
- AssertLock, LK_Exclusive, Loc, FactEntry::Asserted));
- break;
- }
- case attr::AssertSharedLock: {
- const auto *A = cast<AssertSharedLockAttr>(At);
-
- CapExprSet AssertLocks;
- Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self);
- for (const auto &AssertLock : AssertLocks)
- Analyzer->addLock(
- FSet, std::make_unique<LockableFactEntry>(
- AssertLock, LK_Shared, Loc, FactEntry::Asserted));
- break;
- }
-
case attr::AssertCapability: {
const auto *A = cast<AssertCapabilityAttr>(At);
CapExprSet AssertLocks;
@@ -2499,12 +2455,6 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
getMutexIDs(A->isShared() ? SharedLocksAcquired
: ExclusiveLocksAcquired,
A, nullptr, D);
- } else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
- // Don't try to check trylock functions for now.
- return;
- } else if (isa<SharedTrylockFunctionAttr>(Attr)) {
- // Don't try to check trylock functions for now.
- return;
} else if (isa<TryAcquireCapabilityAttr>(Attr)) {
// Don't try to check trylock functions for now.
return;