summaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafety.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp59
1 files changed, 30 insertions, 29 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 48f4106b6bae..1208eaf93e25 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -905,11 +905,7 @@ public:
ScopedLockableFactEntry(const CapabilityExpr &CE, SourceLocation Loc)
: FactEntry(CE, LK_Exclusive, Loc, false) {}
- void addExclusiveLock(const CapabilityExpr &M) {
- UnderlyingMutexes.emplace_back(M.sexpr(), UCK_Acquired);
- }
-
- void addSharedLock(const CapabilityExpr &M) {
+ void addLock(const CapabilityExpr &M) {
UnderlyingMutexes.emplace_back(M.sexpr(), UCK_Acquired);
}
@@ -999,7 +995,10 @@ private:
FSet.addLock(FactMan, std::make_unique<LockableFactEntry>(
!Cp, LK_Exclusive, loc));
} else if (Handler) {
- Handler->handleUnmatchedUnlock(DiagKind, Cp.toString(), loc);
+ SourceLocation PrevLoc;
+ if (const FactEntry *Neg = FSet.findLock(FactMan, !Cp))
+ PrevLoc = Neg->loc();
+ Handler->handleUnmatchedUnlock(DiagKind, Cp.toString(), loc, PrevLoc);
}
}
};
@@ -1249,8 +1248,7 @@ static StringRef ClassifyDiagnostic(const ValueDecl *VD) {
}
template <typename AttrTy>
-static typename std::enable_if<!has_arg_iterator_range<AttrTy>::value,
- StringRef>::type
+static std::enable_if_t<!has_arg_iterator_range<AttrTy>::value, StringRef>
ClassifyDiagnostic(const AttrTy *A) {
if (const ValueDecl *VD = getValueDecl(A->getArg()))
return ClassifyDiagnostic(VD);
@@ -1258,8 +1256,7 @@ ClassifyDiagnostic(const AttrTy *A) {
}
template <typename AttrTy>
-static typename std::enable_if<has_arg_iterator_range<AttrTy>::value,
- StringRef>::type
+static std::enable_if_t<has_arg_iterator_range<AttrTy>::value, StringRef>
ClassifyDiagnostic(const AttrTy *A) {
for (const auto *Arg : A->args()) {
if (const ValueDecl *VD = getValueDecl(Arg))
@@ -1328,7 +1325,10 @@ void ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const CapabilityExpr &Cp,
const FactEntry *LDat = FSet.findLock(FactMan, Cp);
if (!LDat) {
- Handler.handleUnmatchedUnlock(DiagKind, Cp.toString(), UnlockLoc);
+ SourceLocation PrevLoc;
+ if (const FactEntry *Neg = FSet.findLock(FactMan, !Cp))
+ PrevLoc = Neg->loc();
+ Handler.handleUnmatchedUnlock(DiagKind, Cp.toString(), UnlockLoc, PrevLoc);
return;
}
@@ -1803,7 +1803,7 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
SourceLocation Loc = Exp->getExprLoc();
CapExprSet ExclusiveLocksToAdd, SharedLocksToAdd;
CapExprSet ExclusiveLocksToRemove, SharedLocksToRemove, GenericLocksToRemove;
- CapExprSet ScopedExclusiveReqs, ScopedSharedReqs;
+ CapExprSet ScopedReqsAndExcludes;
StringRef CapDiagKind = "mutex";
// Figure out if we're constructing an object of scoped lockable class
@@ -1894,19 +1894,20 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
POK_FunctionCall, ClassifyDiagnostic(A),
Exp->getExprLoc());
// use for adopting a lock
- if (isScopedVar) {
- Analyzer->getMutexIDs(A->isShared() ? ScopedSharedReqs
- : ScopedExclusiveReqs,
- A, Exp, D, VD);
- }
+ if (isScopedVar)
+ Analyzer->getMutexIDs(ScopedReqsAndExcludes, A, Exp, D, VD);
}
break;
}
case attr::LocksExcluded: {
const auto *A = cast<LocksExcludedAttr>(At);
- for (auto *Arg : A->args())
+ for (auto *Arg : A->args()) {
warnIfMutexHeld(D, Exp, Arg, ClassifyDiagnostic(A));
+ // use for deferring a lock
+ if (isScopedVar)
+ Analyzer->getMutexIDs(ScopedReqsAndExcludes, A, Exp, D, VD);
+ }
break;
}
@@ -1946,13 +1947,11 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
auto ScopedEntry = std::make_unique<ScopedLockableFactEntry>(Scp, MLoc);
for (const auto &M : ExclusiveLocksToAdd)
- ScopedEntry->addExclusiveLock(M);
- for (const auto &M : ScopedExclusiveReqs)
- ScopedEntry->addExclusiveLock(M);
+ ScopedEntry->addLock(M);
for (const auto &M : SharedLocksToAdd)
- ScopedEntry->addSharedLock(M);
- for (const auto &M : ScopedSharedReqs)
- ScopedEntry->addSharedLock(M);
+ ScopedEntry->addLock(M);
+ for (const auto &M : ScopedReqsAndExcludes)
+ ScopedEntry->addLock(M);
for (const auto &M : ExclusiveLocksToRemove)
ScopedEntry->addExclusiveUnlock(M);
for (const auto &M : SharedLocksToRemove)
@@ -2141,12 +2140,14 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) {
// handle constructors that involve temporaries
if (auto *EWC = dyn_cast<ExprWithCleanups>(E))
- E = EWC->getSubExpr();
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
- if (ICE->getCastKind() == CK_NoOp)
- E = ICE->getSubExpr();
+ E = EWC->getSubExpr()->IgnoreParens();
+ if (auto *CE = dyn_cast<CastExpr>(E))
+ if (CE->getCastKind() == CK_NoOp ||
+ CE->getCastKind() == CK_ConstructorConversion ||
+ CE->getCastKind() == CK_UserDefinedConversion)
+ E = CE->getSubExpr()->IgnoreParens();
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
- E = BTE->getSubExpr();
+ E = BTE->getSubExpr()->IgnoreParens();
if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
const auto *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());