Author: hokein Date: Mon Aug 13 05:50:30 2018 New Revision: 339558 URL: http://llvm.org/viewvc/llvm-project?rev=339558&view=rev Log: Revert "Allow relockable scopes with thread safety attributes."
This reverts commit r339456. The change introduces a new crash, see class SCOPED_LOCKABLE FileLock { public: explicit FileLock() EXCLUSIVE_LOCK_FUNCTION(file_); ~FileLock() UNLOCK_FUNCTION(file_); void Lock() EXCLUSIVE_LOCK_FUNCTION(file_); Mutex file_; }; void relockShared2() { FileLock file_lock; file_lock.Lock(); } Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=339558&r1=339557&r2=339558&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original) +++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Mon Aug 13 05:50:30 2018 @@ -86,8 +86,8 @@ static void warnInvalidLock(ThreadSafety namespace { -/// A set of CapabilityExpr objects, which are compiled from thread safety -/// attributes on a function. +/// A set of CapabilityInfo objects, which are compiled from the +/// requires attributes on a function. class CapExprSet : public SmallVector<CapabilityExpr, 4> { public: /// Push M onto list, but discard duplicates. @@ -944,23 +944,6 @@ public: if (FullyRemove) FSet.removeLock(FactMan, Cp); } - - void Relock(FactSet &FSet, FactManager &FactMan, LockKind LK, - SourceLocation RelockLoc, ThreadSafetyHandler &Handler, - StringRef DiagKind) const { - for (const auto *UnderlyingMutex : UnderlyingMutexes) { - CapabilityExpr UnderCp(UnderlyingMutex, false); - - // We're relocking the underlying mutexes. Warn on double locking. - if (FSet.findLock(FactMan, UnderCp)) - Handler.handleDoubleLock(DiagKind, UnderCp.toString(), RelockLoc); - else { - FSet.removeLock(FactMan, !UnderCp); - FSet.addLock(FactMan, llvm::make_unique<LockableFactEntry>(UnderCp, LK, - RelockLoc)); - } - } - } }; /// Class which implements the core thread safety analysis routines. @@ -991,9 +974,6 @@ public: void removeLock(FactSet &FSet, const CapabilityExpr &CapE, SourceLocation UnlockLoc, bool FullyRemove, LockKind Kind, StringRef DiagKind); - void relockScopedLock(FactSet &FSet, const CapabilityExpr &CapE, - SourceLocation RelockLoc, LockKind Kind, - StringRef DiagKind); template <typename AttrType> void getMutexIDs(CapExprSet &Mtxs, AttrType *Attr, Expr *Exp, @@ -1305,27 +1285,6 @@ void ThreadSafetyAnalyzer::removeLock(Fa DiagKind); } -void ThreadSafetyAnalyzer::relockScopedLock(FactSet &FSet, - const CapabilityExpr &Cp, - SourceLocation RelockLoc, - LockKind Kind, StringRef DiagKind) { - if (Cp.shouldIgnore()) - return; - - const FactEntry *LDat = FSet.findLock(FactMan, Cp); - if (!LDat) { - // FIXME: It's possible to manually destruct the scope and then relock it. - // Should that be a separate warning? For now we pretend nothing happened. - // It's undefined behavior, so not related to thread safety. - return; - } - - // We should only land here if Cp is a scoped capability, so if we have any - // fact, it must be a ScopedLockableFactEntry. - const auto *SLDat = static_cast<const ScopedLockableFactEntry *>(LDat); - SLDat->Relock(FSet, FactMan, Kind, RelockLoc, Handler, DiagKind); -} - /// Extract the list of mutexIDs from the attribute on an expression, /// and push them onto Mtxs, discarding any duplicates. template <typename AttrType> @@ -1767,19 +1726,14 @@ void BuildLockset::handleCall(Expr *Exp, StringRef CapDiagKind = "mutex"; // Figure out if we're constructing an object of scoped lockable class - bool isScopedConstructor = false, isScopedMemberCall = false; + bool isScopedVar = false; if (VD) { if (const auto *CD = dyn_cast<const CXXConstructorDecl>(D)) { const CXXRecordDecl* PD = CD->getParent(); if (PD && PD->hasAttr<ScopedLockableAttr>()) - isScopedConstructor = true; + isScopedVar = true; } } - if (const auto *MCD = dyn_cast<const CXXMemberCallExpr>(Exp)) { - const CXXRecordDecl *PD = MCD->getRecordDecl(); - if (PD && PD->hasAttr<ScopedLockableAttr>()) - isScopedMemberCall = true; - } for(const Attr *At : D->attrs()) { switch (At->getKind()) { @@ -1859,7 +1813,7 @@ void BuildLockset::handleCall(Expr *Exp, POK_FunctionCall, ClassifyDiagnostic(A), Exp->getExprLoc()); // use for adopting a lock - if (isScopedConstructor) { + if (isScopedVar) { Analyzer->getMutexIDs(A->isShared() ? ScopedSharedReqs : ScopedExclusiveReqs, A, Exp, D, VD); @@ -1892,24 +1846,16 @@ void BuildLockset::handleCall(Expr *Exp, Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind); // Add locks. - if (isScopedMemberCall) { - // If the call is on a scoped capability, we need to relock instead. - for (const auto &M : ExclusiveLocksToAdd) - Analyzer->relockScopedLock(FSet, M, Loc, LK_Exclusive, CapDiagKind); - for (const auto &M : SharedLocksToAdd) - Analyzer->relockScopedLock(FSet, M, Loc, LK_Shared, CapDiagKind); - } else { - for (const auto &M : ExclusiveLocksToAdd) - Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>( - M, LK_Exclusive, Loc, isScopedConstructor), - CapDiagKind); - for (const auto &M : SharedLocksToAdd) - Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>( - M, LK_Shared, Loc, isScopedConstructor), - CapDiagKind); - } + for (const auto &M : ExclusiveLocksToAdd) + Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>( + M, LK_Exclusive, Loc, isScopedVar), + CapDiagKind); + for (const auto &M : SharedLocksToAdd) + Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>( + M, LK_Shared, Loc, isScopedVar), + CapDiagKind); - if (isScopedConstructor) { + if (isScopedVar) { // Add the managing object as a dummy mutex, mapped to the underlying mutex. SourceLocation MLoc = VD->getLocation(); DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation()); Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=339558&r1=339557&r2=339558&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Mon Aug 13 05:50:30 2018 @@ -2621,154 +2621,6 @@ void Foo::test5() { } // end namespace ReleasableScopedLock -namespace RelockableScopedLock { - -class SCOPED_LOCKABLE RelockableExclusiveMutexLock { -public: - RelockableExclusiveMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu); - ~RelockableExclusiveMutexLock() EXCLUSIVE_UNLOCK_FUNCTION(); - - void Lock() EXCLUSIVE_LOCK_FUNCTION(); - void Unlock() UNLOCK_FUNCTION(); -}; - -class SCOPED_LOCKABLE RelockableSharedMutexLock { -public: - RelockableSharedMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu); - ~RelockableSharedMutexLock() UNLOCK_FUNCTION(); - - void Lock() SHARED_LOCK_FUNCTION(); - void Unlock() UNLOCK_FUNCTION(); -}; - -class SharedTraits {}; -class ExclusiveTraits {}; - -class SCOPED_LOCKABLE RelockableMutexLock { -public: - RelockableMutexLock(Mutex *mu, SharedTraits) SHARED_LOCK_FUNCTION(mu); - RelockableMutexLock(Mutex *mu, ExclusiveTraits) EXCLUSIVE_LOCK_FUNCTION(mu); - ~RelockableMutexLock() UNLOCK_FUNCTION(); - - void Lock() EXCLUSIVE_LOCK_FUNCTION(); - void Unlock() UNLOCK_FUNCTION(); - - void ReaderLock() SHARED_LOCK_FUNCTION(); - void ReaderUnlock() UNLOCK_FUNCTION(); - - void PromoteShared() UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(); - void DemoteExclusive() UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION(); -}; - -Mutex mu; -int x GUARDED_BY(mu); - -void print(int); - -void write() { - RelockableExclusiveMutexLock scope(&mu); - x = 2; - scope.Unlock(); - - x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} - - scope.Lock(); - x = 4; -} - -void read() { - RelockableSharedMutexLock scope(&mu); - print(x); - scope.Unlock(); - - print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} - x = 3; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} - - scope.Lock(); - print(x); - x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} -} - -void relockExclusive() { - RelockableMutexLock scope(&mu, SharedTraits{}); - print(x); - x = 2; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} - scope.ReaderUnlock(); - - print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} - - scope.Lock(); - print(x); - x = 4; - - scope.DemoteExclusive(); - print(x); - x = 5; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} -} - -void relockShared() { - RelockableMutexLock scope(&mu, ExclusiveTraits{}); - print(x); - x = 2; - scope.Unlock(); - - print(x); // expected-warning {{reading variable 'x' requires holding mutex 'mu'}} - - scope.ReaderLock(); - print(x); - x = 4; // expected-warning {{writing variable 'x' requires holding mutex 'mu' exclusively}} - - scope.PromoteShared(); - print(x); - x = 5; -} - -void doubleUnlock1() { - RelockableExclusiveMutexLock scope(&mu); - scope.Unlock(); - scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}} -} - -void doubleUnlock2() { - RelockableSharedMutexLock scope(&mu); - scope.Unlock(); - scope.Unlock(); // expected-warning {{releasing mutex 'mu' that was not held}} -} - -void doubleLock1() { - RelockableExclusiveMutexLock scope(&mu); - scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} -} - -void doubleLock2() { - RelockableSharedMutexLock scope(&mu); - scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} -} - -void doubleLock3() { - RelockableExclusiveMutexLock scope(&mu); - scope.Unlock(); - scope.Lock(); - scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} -} - -void doubleLock4() { - RelockableSharedMutexLock scope(&mu); - scope.Unlock(); - scope.Lock(); - scope.Lock(); // expected-warning {{acquiring mutex 'mu' that is already held}} -} - -// Doesn't make a lot of sense, just making sure there is no crash. -void destructLock() { - RelockableExclusiveMutexLock scope(&mu); - scope.~RelockableExclusiveMutexLock(); - scope.Lock(); // Maybe this should warn. -} // expected-warning {{releasing mutex 'scope' that was not held}} - -} // end namespace RelockableScopedLock - - namespace TrylockFunctionTest { class Foo { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits