aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ThreadSafety.cpp
diff options
context:
space:
mode:
authorCaitlin Sadowski <supertri@google.com>2011-09-15 17:25:19 +0000
committerCaitlin Sadowski <supertri@google.com>2011-09-15 17:25:19 +0000
commit4e4bc75d3570835e13183c66ac08974cdc016007 (patch)
treec2c143a55fca0297f305816bbc394e4aee78ca29 /lib/Analysis/ThreadSafety.cpp
parent0f50b08940ea0a9a44f2715f49ccf6bc64b95491 (diff)
Thread safety: refactoring various out of scope warnings to use the same inteface. This eliminates a lot of unnecessary duplicated code.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139801 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ThreadSafety.cpp')
-rw-r--r--lib/Analysis/ThreadSafety.cpp101
1 files changed, 21 insertions, 80 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 233f58c432..504a24c0fa 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -598,13 +598,18 @@ void BuildLockset::VisitCXXMemberCallExpr(CXXMemberCallExpr *Exp) {
} // end anonymous namespace
-/// \brief Flags a warning for each lock that is in LSet2 but not LSet1, or
-/// else mutexes that are held shared in one lockset and exclusive in the other.
-static Lockset warnIfNotInFirstSetOrNotSameKind(ThreadSafetyHandler &Handler,
- const Lockset LSet1,
- const Lockset LSet2,
- Lockset Intersection,
- Lockset::Factory &Fact) {
+/// \brief Compute the intersection of two locksets and issue warnings for any
+/// locks in the symmetric difference.
+///
+/// This function is used at a merge point in the CFG when comparing the lockset
+/// of each branch being merged. For example, given the following sequence:
+/// A; if () then B; else C; D; we need to check that the lockset after B and C
+/// are the same. In the event of a difference, we use the intersection of these
+/// two locksets at the start of D.
+static Lockset intersectAndWarn(ThreadSafetyHandler &Handler,
+ const Lockset LSet1, const Lockset LSet2,
+ Lockset::Factory &Fact, LockErrorKind LEK) {
+ Lockset Intersection = LSet1;
for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) {
const MutexID &LSet2Mutex = I.getKey();
const LockData &LSet2LockData = I.getData();
@@ -618,34 +623,16 @@ static Lockset warnIfNotInFirstSetOrNotSameKind(ThreadSafetyHandler &Handler,
}
} else {
Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(),
- LSet2LockData.AcquireLoc);
+ LSet2LockData.AcquireLoc, LEK);
}
}
- return Intersection;
-}
-
-
-/// \brief Compute the intersection of two locksets and issue warnings for any
-/// locks in the symmetric difference.
-///
-/// This function is used at a merge point in the CFG when comparing the lockset
-/// of each branch being merged. For example, given the following sequence:
-/// A; if () then B; else C; D; we need to check that the lockset after B and C
-/// are the same. In the event of a difference, we use the intersection of these
-/// two locksets at the start of D.
-static Lockset intersectAndWarn(ThreadSafetyHandler &Handler,
- const Lockset LSet1, const Lockset LSet2,
- Lockset::Factory &Fact) {
- Lockset Intersection = LSet1;
- Intersection = warnIfNotInFirstSetOrNotSameKind(Handler, LSet1, LSet2,
- Intersection, Fact);
for (Lockset::iterator I = LSet1.begin(), E = LSet1.end(); I != E; ++I) {
if (!LSet2.contains(I.getKey())) {
const MutexID &Mutex = I.getKey();
const LockData &MissingLock = I.getData();
Handler.handleMutexHeldEndOfScope(Mutex.getName(),
- MissingLock.AcquireLoc);
+ MissingLock.AcquireLoc, LEK);
Intersection = Fact.remove(Intersection, Mutex);
}
}
@@ -669,34 +656,6 @@ static SourceLocation getFirstStmtLocation(CFGBlock *Block) {
return Loc;
}
-/// \brief Warn about different locksets along backedges of loops.
-/// This function is called when we encounter a back edge. At that point,
-/// we need to verify that the lockset before taking the backedge is the
-/// same as the lockset before entering the loop.
-///
-/// \param LoopEntrySet Locks before starting the loop
-/// \param LoopReentrySet Locks in the last CFG block of the loop
-static void warnBackEdgeUnequalLocksets(ThreadSafetyHandler &Handler,
- const Lockset LoopReentrySet,
- const Lockset LoopEntrySet,
- SourceLocation FirstLocInLoop,
- Lockset::Factory &Fact) {
- assert(FirstLocInLoop.isValid());
- // Warn for locks held at the start of the loop, but not the end.
- for (Lockset::iterator I = LoopEntrySet.begin(), E = LoopEntrySet.end();
- I != E; ++I) {
- if (!LoopReentrySet.contains(I.getKey())) {
- // We report this error at the location of the first statement in a loop
- Handler.handleNoLockLoopEntry(I.getKey().getName(), FirstLocInLoop);
- }
- }
-
- // Warn for locks held at the end of the loop, but not at the start.
- warnIfNotInFirstSetOrNotSameKind(Handler, LoopEntrySet, LoopReentrySet,
- LoopReentrySet, Fact);
-}
-
-
namespace clang {
namespace thread_safety {
/// \brief Check a function's CFG for thread-safety violations.
@@ -763,7 +722,8 @@ void runThreadSafetyAnalysis(AnalysisContext &AC,
LocksetInitialized = true;
} else {
Entryset = intersectAndWarn(Handler, Entryset,
- ExitLocksets[PrevBlockID], LocksetFactory);
+ ExitLocksets[PrevBlockID], LocksetFactory,
+ LEK_LockedSomePredecessors);
}
}
@@ -787,36 +747,17 @@ void runThreadSafetyAnalysis(AnalysisContext &AC,
continue;
CFGBlock *FirstLoopBlock = *SI;
- SourceLocation FirstLoopLocation = getFirstStmtLocation(FirstLoopBlock);
-
- assert(FirstLoopLocation.isValid());
-
- // Fail gracefully in release code.
- if (!FirstLoopLocation.isValid())
- continue;
-
Lockset PreLoop = EntryLocksets[FirstLoopBlock->getBlockID()];
Lockset LoopEnd = ExitLocksets[CurrBlockID];
- warnBackEdgeUnequalLocksets(Handler, LoopEnd, PreLoop, FirstLoopLocation,
- LocksetFactory);
+ intersectAndWarn(Handler, LoopEnd, PreLoop, LocksetFactory,
+ LEK_LockedSomeLoopIterations);
}
}
+ Lockset InitialLockset = EntryLocksets[CFGraph->getEntry().getBlockID()];
Lockset FinalLockset = ExitLocksets[CFGraph->getExit().getBlockID()];
- if (!FinalLockset.isEmpty()) {
- for (Lockset::iterator I=FinalLockset.begin(), E=FinalLockset.end();
- I != E; ++I) {
- const MutexID &Mutex = I.getKey();
- const LockData &MissingLock = I.getData();
-
- std::string FunName = "<unknown>";
- if (const NamedDecl *ContextDecl = dyn_cast<NamedDecl>(AC.getDecl())) {
- FunName = ContextDecl->getDeclName().getAsString();
- }
-
- Handler.handleNoUnlock(Mutex.getName(), FunName, MissingLock.AcquireLoc);
- }
- }
+ intersectAndWarn(Handler, InitialLockset, FinalLockset, LocksetFactory,
+ LEK_LockedAtEndOfFunction);
}
/// \brief Helper function that returns a LockKind required for the given level