Thread safety analysis: fixed incorrect error message at the end of a locks_required function.
llvm-svn: 159607
This commit is contained in:
@@ -60,7 +60,8 @@ enum AccessKind {
|
|||||||
enum LockErrorKind {
|
enum LockErrorKind {
|
||||||
LEK_LockedSomeLoopIterations,
|
LEK_LockedSomeLoopIterations,
|
||||||
LEK_LockedSomePredecessors,
|
LEK_LockedSomePredecessors,
|
||||||
LEK_LockedAtEndOfFunction
|
LEK_LockedAtEndOfFunction,
|
||||||
|
LEK_NotLockedAtEndOfFunction
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Handler class for thread safety warnings.
|
/// Handler class for thread safety warnings.
|
||||||
|
|||||||
@@ -1775,6 +1775,9 @@ def warn_double_lock : Warning<
|
|||||||
def warn_no_unlock : Warning<
|
def warn_no_unlock : Warning<
|
||||||
"mutex '%0' is still locked at the end of function">,
|
"mutex '%0' is still locked at the end of function">,
|
||||||
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
|
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
|
||||||
|
def warn_expecting_locked : Warning<
|
||||||
|
"expecting mutex '%0' to be locked at the end of function">,
|
||||||
|
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
|
||||||
// FIXME: improve the error message about locks not in scope
|
// FIXME: improve the error message about locks not in scope
|
||||||
def warn_lock_some_predecessors : Warning<
|
def warn_lock_some_predecessors : Warning<
|
||||||
"mutex '%0' is not locked on every path through here">,
|
"mutex '%0' is not locked on every path through here">,
|
||||||
|
|||||||
@@ -951,7 +951,13 @@ public:
|
|||||||
const CFGBlock *CurrBlock);
|
const CFGBlock *CurrBlock);
|
||||||
|
|
||||||
Lockset intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2,
|
Lockset intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2,
|
||||||
SourceLocation JoinLoc, LockErrorKind LEK);
|
SourceLocation JoinLoc,
|
||||||
|
LockErrorKind LEK1, LockErrorKind LEK2);
|
||||||
|
|
||||||
|
Lockset intersectAndWarn(const Lockset &LSet1, const Lockset &LSet2,
|
||||||
|
SourceLocation JoinLoc, LockErrorKind LEK1) {
|
||||||
|
return intersectAndWarn(LSet1, LSet2, JoinLoc, LEK1, LEK1);
|
||||||
|
}
|
||||||
|
|
||||||
void runAnalysis(AnalysisDeclContext &AC);
|
void runAnalysis(AnalysisDeclContext &AC);
|
||||||
};
|
};
|
||||||
@@ -1541,11 +1547,13 @@ void BuildLockset::VisitDeclStmt(DeclStmt *S) {
|
|||||||
/// \param LSet1 The first lockset.
|
/// \param LSet1 The first lockset.
|
||||||
/// \param LSet2 The second lockset.
|
/// \param LSet2 The second lockset.
|
||||||
/// \param JoinLoc The location of the join point for error reporting
|
/// \param JoinLoc The location of the join point for error reporting
|
||||||
/// \param LEK The error message to report.
|
/// \param LEK1 The error message to report if a mutex is missing from LSet1
|
||||||
|
/// \param LEK2 The error message to report if a mutex is missing from Lset2
|
||||||
Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1,
|
Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1,
|
||||||
const Lockset &LSet2,
|
const Lockset &LSet2,
|
||||||
SourceLocation JoinLoc,
|
SourceLocation JoinLoc,
|
||||||
LockErrorKind LEK) {
|
LockErrorKind LEK1,
|
||||||
|
LockErrorKind LEK2) {
|
||||||
Lockset Intersection = LSet1;
|
Lockset Intersection = LSet1;
|
||||||
|
|
||||||
for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) {
|
for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) {
|
||||||
@@ -1564,7 +1572,7 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1,
|
|||||||
if (!LSet2LockData.Managed)
|
if (!LSet2LockData.Managed)
|
||||||
Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(),
|
Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(),
|
||||||
LSet2LockData.AcquireLoc,
|
LSet2LockData.AcquireLoc,
|
||||||
JoinLoc, LEK);
|
JoinLoc, LEK1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1576,7 +1584,7 @@ Lockset ThreadSafetyAnalyzer::intersectAndWarn(const Lockset &LSet1,
|
|||||||
if (!MissingLock.Managed)
|
if (!MissingLock.Managed)
|
||||||
Handler.handleMutexHeldEndOfScope(Mutex.getName(),
|
Handler.handleMutexHeldEndOfScope(Mutex.getName(),
|
||||||
MissingLock.AcquireLoc,
|
MissingLock.AcquireLoc,
|
||||||
JoinLoc, LEK);
|
JoinLoc, LEK2);
|
||||||
Intersection = LocksetFactory.remove(Intersection, Mutex);
|
Intersection = LocksetFactory.remove(Intersection, Mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1818,7 +1826,8 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
|
|||||||
// FIXME: Should we call this function for all blocks which exit the function?
|
// FIXME: Should we call this function for all blocks which exit the function?
|
||||||
intersectAndWarn(Initial->EntrySet, Final->ExitSet,
|
intersectAndWarn(Initial->EntrySet, Final->ExitSet,
|
||||||
Final->ExitLoc,
|
Final->ExitLoc,
|
||||||
LEK_LockedAtEndOfFunction);
|
LEK_LockedAtEndOfFunction,
|
||||||
|
LEK_NotLockedAtEndOfFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|||||||
@@ -1061,6 +1061,9 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
|
|||||||
case LEK_LockedAtEndOfFunction:
|
case LEK_LockedAtEndOfFunction:
|
||||||
DiagID = diag::warn_no_unlock;
|
DiagID = diag::warn_no_unlock;
|
||||||
break;
|
break;
|
||||||
|
case LEK_NotLockedAtEndOfFunction:
|
||||||
|
DiagID = diag::warn_expecting_locked;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (LocEndOfScope.isInvalid())
|
if (LocEndOfScope.isInvalid())
|
||||||
LocEndOfScope = FunEndLocation;
|
LocEndOfScope = FunEndLocation;
|
||||||
|
|||||||
@@ -2451,6 +2451,22 @@ void Foo::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace UnlockBug {
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
Mutex mutex_;
|
||||||
|
|
||||||
|
void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
|
||||||
|
mutex_.Unlock();
|
||||||
|
} // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
|
||||||
|
|
||||||
|
|
||||||
|
void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
|
||||||
|
mutex_.Unlock();
|
||||||
|
} // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace UnlockBug
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user