diff options
Diffstat (limited to 'clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r-- | clang/lib/Analysis/ThreadSafety.cpp | 59 |
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()); |