aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
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
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')
-rw-r--r--clang/lib/AST/ASTImporter.cpp28
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp60
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp55
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp13
4 files changed, 9 insertions, 147 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index b55b8f2..0062860 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -9425,34 +9425,6 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
From->args_size());
break;
}
- case attr::AssertExclusiveLock: {
- const auto *From = cast<AssertExclusiveLockAttr>(FromAttr);
- AI.importAttr(From,
- AI.importArrayArg(From->args(), From->args_size()).value(),
- From->args_size());
- break;
- }
- case attr::AssertSharedLock: {
- const auto *From = cast<AssertSharedLockAttr>(FromAttr);
- AI.importAttr(From,
- AI.importArrayArg(From->args(), From->args_size()).value(),
- From->args_size());
- break;
- }
- case attr::ExclusiveTrylockFunction: {
- const auto *From = cast<ExclusiveTrylockFunctionAttr>(FromAttr);
- AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(),
- AI.importArrayArg(From->args(), From->args_size()).value(),
- From->args_size());
- break;
- }
- case attr::SharedTrylockFunction: {
- const auto *From = cast<SharedTrylockFunctionAttr>(FromAttr);
- AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(),
- AI.importArrayArg(From->args(), From->args_size()).value(),
- From->args_size());
- break;
- }
case attr::LockReturned: {
const auto *From = cast<LockReturnedAttr>(FromAttr);
AI.importAttr(From, AI.importArg(From->getArg()).value());
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;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 20ea38b..bc891fb 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -538,29 +538,6 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
return true;
}
-static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- SmallVector<Expr *, 1> Args;
- if (!checkLockFunAttrCommon(S, D, AL, Args))
- return;
-
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? nullptr : &Args[0];
- D->addAttr(::new (S.Context)
- AssertSharedLockAttr(S.Context, AL, StartArg, Size));
-}
-
-static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr *, 1> Args;
- if (!checkLockFunAttrCommon(S, D, AL, Args))
- return;
-
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? nullptr : &Args[0];
- D->addAttr(::new (S.Context)
- AssertExclusiveLockAttr(S.Context, AL, StartArg, Size));
-}
-
/// Checks to be sure that the given parameter number is in bounds, and
/// is an integral type. Will emit appropriate diagnostics if this returns
/// false.
@@ -640,26 +617,6 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
return true;
}
-static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, AL, Args))
- return;
-
- D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(
- S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
-}
-
-static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- SmallVector<Expr*, 2> Args;
- if (!checkTryLockFunAttrCommon(S, D, AL, Args))
- return;
-
- D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
- S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
-}
-
static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// check that the argument is lockable object
SmallVector<Expr*, 1> Args;
@@ -7528,12 +7485,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
break;
// Thread safety attributes:
- case ParsedAttr::AT_AssertExclusiveLock:
- handleAssertExclusiveLockAttr(S, D, AL);
- break;
- case ParsedAttr::AT_AssertSharedLock:
- handleAssertSharedLockAttr(S, D, AL);
- break;
case ParsedAttr::AT_PtGuardedVar:
handlePtGuardedVarAttr(S, D, AL);
break;
@@ -7549,18 +7500,12 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_PtGuardedBy:
handlePtGuardedByAttr(S, D, AL);
break;
- case ParsedAttr::AT_ExclusiveTrylockFunction:
- handleExclusiveTrylockFunctionAttr(S, D, AL);
- break;
case ParsedAttr::AT_LockReturned:
handleLockReturnedAttr(S, D, AL);
break;
case ParsedAttr::AT_LocksExcluded:
handleLocksExcludedAttr(S, D, AL);
break;
- case ParsedAttr::AT_SharedTrylockFunction:
- handleSharedTrylockFunctionAttr(S, D, AL);
- break;
case ParsedAttr::AT_AcquiredBefore:
handleAcquiredBeforeAttr(S, D, AL);
break;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 2247ade..0599122 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -19401,13 +19401,7 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
Args = llvm::ArrayRef(AA->args_begin(), AA->args_size());
else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
Args = llvm::ArrayRef(AB->args_begin(), AB->args_size());
- else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
- Arg = ETLF->getSuccessValue();
- Args = llvm::ArrayRef(ETLF->args_begin(), ETLF->args_size());
- } else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
- Arg = STLF->getSuccessValue();
- Args = llvm::ArrayRef(STLF->args_begin(), STLF->args_size());
- } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
+ else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
Arg = LR->getArg();
else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
Args = llvm::ArrayRef(LE->args_begin(), LE->args_size());
@@ -19415,9 +19409,10 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
Args = llvm::ArrayRef(RC->args_begin(), RC->args_size());
else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A))
Args = llvm::ArrayRef(AC->args_begin(), AC->args_size());
- else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A))
+ else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A)) {
+ Arg = AC->getSuccessValue();
Args = llvm::ArrayRef(AC->args_begin(), AC->args_size());
- else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
+ } else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
Args = llvm::ArrayRef(RC->args_begin(), RC->args_size());
if (Arg && !Finder.TraverseStmt(Arg))