[cfe-commits] r139321 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/AnalysisBasedWarnings.cpp test/SemaCXX/warn-thread-safety-analysis.cpp
Caitlin Sadowski
supertri at google.com
Thu Sep 8 14:52:51 PDT 2011
Author: supertri
Date: Thu Sep 8 16:52:50 2011
New Revision: 139321
URL: http://llvm.org/viewvc/llvm-project?rev=139321&view=rev
Log:
Thread Safety: In C++0x Mutexes are the objects that control access to shared variables, while Locks are the objects that acquire and release Mutexes. We switch to this new terminology.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=139321&r1=139320&r2=139321&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 8 16:52:50 2011
@@ -1388,47 +1388,48 @@
def err_attribute_decl_not_lockable : Error<
"%0 attribute can only be applied in a context annotated "
"with 'lockable' attribute">;
-def warn_unlock_but_no_acquire : Warning<
- "unlocking '%0' that was not acquired">,
+def warn_unlock_but_no_lock : Warning<
+ "unlocking '%0' that was not locked">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_double_lock : Warning<
- "locking '%0' that is already acquired">,
+ "locking '%0' that is already locked">,
InGroup<ThreadSafety>, DefaultIgnore;
-def warn_locks_not_released : Warning<
- "lock '%0' is not released at the end of function '%1'">,
+def warn_no_unlock : Warning<
+ "mutex '%0' is still held at the end of function '%1'">,
InGroup<ThreadSafety>, DefaultIgnore;
-def warn_lock_not_released_in_scope : Warning<
- "lock '%0' is not released at the end of its scope">,
+// FIXME: improve the error message about locks not in scope
+def warn_lock_at_end_of_scope : Warning<
+ "mutex '%0' is still held at the end of its scope">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_expecting_lock_held_on_loop : Warning<
- "expecting lock '%0' to be %select{held|held exclusively}1 at start of each "
- "loop">,
+ "expecting lock on '%0' to be %select{held|held exclusively}1 at start of "
+ "each loop">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_lock_exclusive_and_shared : Warning<
- "lock '%0' is held exclusively and shared in the same scope">,
+ "lock '%0' is exclusive and shared in the same scope">,
InGroup<ThreadSafety>, DefaultIgnore;
def note_lock_exclusive_and_shared : Note<
- "the other acquire of lock '%0' is here">,
+ "the other lock of mutex '%0' is here">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_variable_requires_lock : Warning<
- "%select{reading|writing}2 variable '%0' requires lock '%1' to be "
+ "%select{reading|writing}2 variable '%0' requires lock on '%1' to be "
"%select{held|held exclusively}2">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_variable_requires_any_lock : Warning<
"accessing variable '%0' requires some lock">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_var_deref_requires_lock : Warning<
- "%select{reading|writing}2 the value pointed to by '%0' requires lock '%1' to"
- " be %select{held|held exclusively}2">,
+ "%select{reading|writing}2 the value pointed to by '%0' requires lock on '%1'"
+ " to be %select{held|held exclusively}2">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_var_deref_requires_any_lock : Warning<
"accessing the value pointed to by '%0' requires some lock">,
InGroup<ThreadSafety>, DefaultIgnore;
def warn_fun_requires_lock : Warning<
- "calling function '%0' requires %select{shared|exclusive}2 lock '%1'">,
+ "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">,
InGroup<ThreadSafety>, DefaultIgnore;
-def warn_fun_excludes_lock : Warning<
- "cannot call function '%0' while holding lock '%1'">,
+def warn_fun_excludes_mutex : Warning<
+ "cannot call function '%0' while holding mutex '%1'">,
InGroup<ThreadSafety>, DefaultIgnore;
Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=139321&r1=139320&r2=139321&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Thu Sep 8 16:52:50 2011
@@ -676,12 +676,12 @@
}
};
-/// \brief A LockID object uniquely identifies a particular lock acquired, and
+/// \brief A MutexID object uniquely identifies a particular mutex, and
/// is built from an Expr* (i.e. calling a lock function).
///
/// Thread-safety analysis works by comparing lock expressions. Within the
/// body of a function, an expression such as "x->foo->bar.mu" will resolve to
-/// a particular lock object at run-time. Subsequent occurrences of the same
+/// a particular mutex object at run-time. Subsequent occurrences of the same
/// expression (where "same" means syntactic equality) will refer to the same
/// run-time object if three conditions hold:
/// (1) Local variables in the expression, such as "x" have not changed.
@@ -692,7 +692,7 @@
///
/// Clang introduces an additional wrinkle, which is that it is difficult to
/// derive canonical expressions, or compare expressions directly for equality.
-/// Thus, we identify a lock not by an Expr, but by the set of named
+/// Thus, we identify a mutex not by an Expr, but by the set of named
/// declarations that are referenced by the Expr. In other words,
/// x->foo->bar.mu will be a four element vector with the Decls for
/// mu, bar, and foo, and x. The vector will uniquely identify the expression
@@ -704,36 +704,26 @@
/// For example:
/// class C { Mutex Mu; void lock() EXCLUSIVE_LOCK_FUNCTION(this->Mu); };
/// void myFunc(C *X) { ... X->lock() ... }
-/// The original expression for the lock acquired by myFunc is "this->Mu", but
+/// The original expression for the mutex acquired by myFunc is "this->Mu", but
/// "X" is substituted for "this" so we get X->Mu();
///
/// For another example:
/// foo(MyList *L) EXCLUSIVE_LOCKS_REQUIRED(L->Mu) { ... }
/// MyList *MyL;
/// foo(MyL); // requires lock MyL->Mu to be held
-///
-/// FIXME: In C++0x Mutexes are the objects that control access to shared
-/// variables, while Locks are the objects that acquire and release Mutexes. We
-/// may want to switch to this new terminology soon, in which case we should
-/// rename this class "Mutex" and rename "LockId" to "MutexId", as well as
-/// making sure that the terms Lock and Mutex throughout this code are
-/// consistent with C++0x
-///
-/// FIXME: We should also pick one and canonicalize all usage of lock vs acquire
-/// and unlock vs release as verbs.
-class LockID {
+class MutexID {
SmallVector<NamedDecl*, 2> DeclSeq;
/// Build a Decl sequence representing the lock from the given expression.
/// Recursive function that bottoms out when the final DeclRefExpr is reached.
- void buildLock(Expr *Exp) {
+ void buildMutexID(Expr *Exp) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
DeclSeq.push_back(ND);
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
NamedDecl *ND = ME->getMemberDecl();
DeclSeq.push_back(ND);
- buildLock(ME->getBase());
+ buildMutexID(ME->getBase());
} else if (isa<CXXThisExpr>(Exp)) {
return;
} else {
@@ -743,32 +733,32 @@
}
public:
- LockID(Expr *LExpr) {
- buildLock(LExpr);
+ MutexID(Expr *LExpr) {
+ buildMutexID(LExpr);
assert(!DeclSeq.empty());
}
- bool operator==(const LockID &other) const {
+ bool operator==(const MutexID &other) const {
return DeclSeq == other.DeclSeq;
}
- bool operator!=(const LockID &other) const {
+ bool operator!=(const MutexID &other) const {
return !(*this == other);
}
// SmallVector overloads Operator< to do lexicographic ordering. Note that
// we use pointer equality (and <) to compare NamedDecls. This means the order
- // of LockIDs in a lockset is nondeterministic. In order to output
+ // of MutexIDs in a lockset is nondeterministic. In order to output
// diagnostics in a deterministic ordering, we must order all diagnostics to
// output by SourceLocation when iterating through this lockset.
- bool operator<(const LockID &other) const {
+ bool operator<(const MutexID &other) const {
return DeclSeq < other.DeclSeq;
}
- /// \brief Returns the name of the first Decl in the list for a given LockID;
+ /// \brief Returns the name of the first Decl in the list for a given MutexID;
/// e.g. the lock expression foo.bar() has name "bar".
/// The caret will point unambiguously to the lock expression, so using this
- /// name in diagnostics is a way to get simple, and consistent, lock names.
+ /// name in diagnostics is a way to get simple, and consistent, mutex names.
/// We do not want to output the entire expression text for security reasons.
StringRef getName() const {
return DeclSeq.front()->getName();
@@ -795,7 +785,7 @@
/// \brief This is a helper class that stores info about the most recent
/// accquire of a Lock.
///
-/// The main body of the analysis maps LockIDs to LockDatas.
+/// The main body of the analysis maps MutexIDs to LockDatas.
struct LockData {
SourceLocation AcquireLoc;
@@ -824,9 +814,9 @@
}
};
-/// A Lockset maps each LockID (defined above) to information about how it has
+/// A Lockset maps each MutexID (defined above) to information about how it has
/// been locked.
-typedef llvm::ImmutableMap<LockID, LockData> Lockset;
+typedef llvm::ImmutableMap<MutexID, LockData> Lockset;
/// \brief We use this class to visit different types of expressions in
/// CFGBlocks, and build up the lockset.
@@ -842,8 +832,8 @@
void removeLock(SourceLocation UnlockLoc, Expr *LockExp);
void addLock(SourceLocation LockLoc, Expr *LockExp, LockKind LK);
const ValueDecl *getValueDecl(Expr *Exp);
- void warnIfLockNotHeld (const NamedDecl *D, Expr *Exp, AccessKind AK,
- LockID &Lock, unsigned DiagID);
+ void warnIfMutexNotHeld (const NamedDecl *D, Expr *Exp, AccessKind AK,
+ MutexID &Mutex, unsigned DiagID);
void checkAccess(Expr *Exp, AccessKind AK);
void checkDereference(Expr *Exp, AccessKind AK);
@@ -852,13 +842,13 @@
/// \brief Returns true if the lockset contains a lock, regardless of whether
/// the lock is held exclusively or shared.
- bool locksetContains(LockID Lock) {
+ bool locksetContains(MutexID Lock) {
return LSet.lookup(Lock);
}
/// \brief Returns true if the lockset contains a lock with the passed in
/// locktype.
- bool locksetContains(LockID Lock, LockKind KindRequested) const {
+ bool locksetContains(MutexID Lock, LockKind KindRequested) const {
const LockData *LockHeld = LSet.lookup(Lock);
return (LockHeld && KindRequested == LockHeld->LKind);
}
@@ -884,24 +874,24 @@
void BuildLockset::addLock(SourceLocation LockLoc, Expr *LockExp,
LockKind LK) {
// FIXME: deal with acquired before/after annotations
- LockID Lock(LockExp);
- LockData NewLockData(LockLoc, LK);
+ MutexID Mutex(LockExp);
+ LockData NewLock(LockLoc, LK);
// FIXME: Don't always warn when we have support for reentrant locks.
- if (locksetContains(Lock))
- S.Diag(LockLoc, diag::warn_double_lock) << Lock.getName();
- LSet = LocksetFactory.add(LSet, Lock, NewLockData);
+ if (locksetContains(Mutex))
+ S.Diag(LockLoc, diag::warn_double_lock) << Mutex.getName();
+ LSet = LocksetFactory.add(LSet, Mutex, NewLock);
}
/// \brief Remove a lock from the lockset, warning if the lock is not there.
/// \param LockExp The lock expression corresponding to the lock to be removed
/// \param UnlockLoc The source location of the unlock (only used in error msg)
void BuildLockset::removeLock(SourceLocation UnlockLoc, Expr *LockExp) {
- LockID Lock(LockExp);
+ MutexID Mutex(LockExp);
- Lockset NewLSet = LocksetFactory.remove(LSet, Lock);
+ Lockset NewLSet = LocksetFactory.remove(LSet, Mutex);
if(NewLSet == LSet)
- S.Diag(UnlockLoc, diag::warn_unlock_but_no_acquire) << Lock.getName();
+ S.Diag(UnlockLoc, diag::warn_unlock_but_no_lock) << Mutex.getName();
LSet = NewLSet;
}
@@ -919,19 +909,19 @@
/// \brief Warn if the LSet does not contain a lock sufficient to protect access
/// of at least the passed in AccessType.
-void BuildLockset::warnIfLockNotHeld(const NamedDecl *D, Expr *Exp,
- AccessKind AK, LockID &Lock,
- unsigned DiagID) {
+void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, Expr *Exp,
+ AccessKind AK, MutexID &Mutex,
+ unsigned DiagID) {
switch (AK) {
case AK_Read:
- if (!locksetContains(Lock))
+ if (!locksetContains(Mutex))
S.Diag(Exp->getExprLoc(), DiagID)
- << D->getName() << Lock.getName() << LK_Shared;
+ << D->getName() << Mutex.getName() << LK_Shared;
break;
case AK_Written :
- if (!locksetContains(Lock, LK_Exclusive))
+ if (!locksetContains(Mutex, LK_Exclusive))
S.Diag(Exp->getExprLoc(), DiagID)
- << D->getName() << Lock.getName() << LK_Exclusive;
+ << D->getName() << Mutex.getName() << LK_Exclusive;
break;
}
}
@@ -962,15 +952,15 @@
if (ArgAttrs[i]->getKind() != attr::PtGuardedBy)
continue;
const PtGuardedByAttr *PGBAttr = cast<PtGuardedByAttr>(ArgAttrs[i]);
- LockID Lock(PGBAttr->getArg());
- warnIfLockNotHeld(D, Exp, AK, Lock, diag::warn_var_deref_requires_lock);
+ MutexID Mutex(PGBAttr->getArg());
+ warnIfMutexNotHeld(D, Exp, AK, Mutex, diag::warn_var_deref_requires_lock);
}
}
/// \brief Checks guarded_by and guarded_var attributes.
/// Whenever we identify an access (read or write) of a DeclRefExpr or
/// MemberExpr, we need to check whether there are any guarded_by or
-/// guarded_var attributes, and make sure we hold the appropriate locks.
+/// guarded_var attributes, and make sure we hold the appropriate mutexes.
void BuildLockset::checkAccess(Expr *Exp, AccessKind AK) {
const ValueDecl *D = getValueDecl(Exp);
if(!D || !D->hasAttrs())
@@ -985,13 +975,13 @@
if (ArgAttrs[i]->getKind() != attr::GuardedBy)
continue;
const GuardedByAttr *GBAttr = cast<GuardedByAttr>(ArgAttrs[i]);
- LockID Lock(GBAttr->getArg());
- warnIfLockNotHeld(D, Exp, AK, Lock, diag::warn_variable_requires_lock);
+ MutexID Mutex(GBAttr->getArg());
+ warnIfMutexNotHeld(D, Exp, AK, Mutex, diag::warn_variable_requires_lock);
}
}
/// \brief For unary operations which read and write a variable, we need to
-/// check whether we hold any required locks. Reads are checked in
+/// check whether we hold any required mutexes. Reads are checked in
/// VisitCastExpr.
void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
switch (UO->getOpcode()) {
@@ -1010,7 +1000,7 @@
}
/// For binary operations which assign to a variable (writes), we need to check
-/// whether we hold any required locks.
+/// whether we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
void BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
if (!BO->isAssignmentOp())
@@ -1021,7 +1011,7 @@
}
/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
-/// need to ensure we hold any required locks.
+/// need to ensure we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
void BuildLockset::VisitCastExpr(CastExpr *CE) {
if (CE->getCastKind() != CK_LValueToRValue)
@@ -1042,7 +1032,7 @@
AttrType *SpecificAttr = cast<AttrType>(Attr);
if (SpecificAttr->args_size() == 0) {
- // The lock held is the "this" object.
+ // The mutex held is the "this" object.
addLock(ExpLocation, Parent, LK);
return;
}
@@ -1076,19 +1066,19 @@
Attr *Attr = ArgAttrs[i];
switch (Attr->getKind()) {
// When we encounter an exclusive lock function, we need to add the lock
- // to our lockset, marked as exclusive.
+ // to our lockset with kind exclusive.
case attr::ExclusiveLockFunction:
addLocksToSet<ExclusiveLockFunctionAttr>(LK_Exclusive, Attr, Exp);
break;
// When we encounter a shared lock function, we need to add the lock
- // to our lockset, marked as not exclusive
+ // to our lockset with kind shared.
case attr::SharedLockFunction:
addLocksToSet<SharedLockFunctionAttr>(LK_Shared, Attr, Exp);
break;
- // When we encounter an unlock function, we need to remove unlocked locks
- // from the lockset, and flag a warning if they are not there.
+ // When we encounter an unlock function, we need to remove unlocked
+ // mutexes from the lockset, and flag a warning if they are not there.
case attr::UnlockFunction: {
UnlockFunctionAttr *UFAttr = cast<UnlockFunctionAttr>(Attr);
@@ -1112,8 +1102,8 @@
for (ExclusiveLocksRequiredAttr::args_iterator
I = ELRAttr->args_begin(), E = ELRAttr->args_end(); I != E; ++I) {
- LockID Lock(*I);
- warnIfLockNotHeld(D, Exp, AK_Written, Lock,
+ MutexID Mutex(*I);
+ warnIfMutexNotHeld(D, Exp, AK_Written, Mutex,
diag::warn_fun_requires_lock);
}
break;
@@ -1127,8 +1117,8 @@
for (SharedLocksRequiredAttr::args_iterator I = SLRAttr->args_begin(),
E = SLRAttr->args_end(); I != E; ++I) {
- LockID Lock(*I);
- warnIfLockNotHeld(D, Exp, AK_Read, Lock,
+ MutexID Mutex(*I);
+ warnIfMutexNotHeld(D, Exp, AK_Read, Mutex,
diag::warn_fun_requires_lock);
}
break;
@@ -1138,10 +1128,10 @@
LocksExcludedAttr *LEAttr = cast<LocksExcludedAttr>(Attr);
for (LocksExcludedAttr::args_iterator I = LEAttr->args_begin(),
E = LEAttr->args_end(); I != E; ++I) {
- LockID Lock(*I);
- if (locksetContains(Lock))
- S.Diag(ExpLocation, diag::warn_fun_excludes_lock)
- << D->getName() << Lock.getName();
+ MutexID Mutex(*I);
+ if (locksetContains(Mutex))
+ S.Diag(ExpLocation, diag::warn_fun_excludes_mutex)
+ << D->getName() << Mutex.getName();
}
break;
}
@@ -1191,22 +1181,22 @@
Lockset Intersection,
Lockset::Factory &Fact) {
for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) {
- const LockID &LSet2Lock = I.getKey();
+ const MutexID &LSet2Mutex = I.getKey();
const LockData &LSet2LockData = I.getData();
- if (const LockData *LD = LSet1.lookup(LSet2Lock)) {
+ if (const LockData *LD = LSet1.lookup(LSet2Mutex)) {
if (LD->LKind != LSet2LockData.LKind) {
PartialDiagnostic Warning =
- S.PDiag(diag::warn_lock_exclusive_and_shared) << LSet2Lock.getName();
+ S.PDiag(diag::warn_lock_exclusive_and_shared) << LSet2Mutex.getName();
PartialDiagnostic Note =
- S.PDiag(diag::note_lock_exclusive_and_shared) << LSet2Lock.getName();
+ S.PDiag(diag::note_lock_exclusive_and_shared) << LSet2Mutex.getName();
Warnings.push_back(DelayedDiag(LSet2LockData.AcquireLoc, Warning));
Warnings.push_back(DelayedDiag(LD->AcquireLoc, Note));
if (LD->LKind != LK_Exclusive)
- Intersection = Fact.add(Intersection, LSet2Lock, LSet2LockData);
+ Intersection = Fact.add(Intersection, LSet2Mutex, LSet2LockData);
}
} else {
PartialDiagnostic Warning =
- S.PDiag(diag::warn_lock_not_released_in_scope) << LSet2Lock.getName();
+ S.PDiag(diag::warn_lock_at_end_of_scope) << LSet2Mutex.getName();
Warnings.push_back(DelayedDiag(LSet2LockData.AcquireLoc, Warning));
}
}
@@ -1233,12 +1223,12 @@
for (Lockset::iterator I = LSet1.begin(), E = LSet1.end(); I != E; ++I) {
if (!LSet2.contains(I.getKey())) {
- const LockID &MissingLock = I.getKey();
- const LockData &MissingLockData = I.getData();
+ const MutexID &Mutex = I.getKey();
+ const LockData &MissingLock = I.getData();
PartialDiagnostic Warning =
- S.PDiag(diag::warn_lock_not_released_in_scope) << MissingLock.getName();
- Warnings.push_back(DelayedDiag(MissingLockData.AcquireLoc, Warning));
- Intersection = Fact.remove(Intersection, MissingLock);
+ S.PDiag(diag::warn_lock_at_end_of_scope) << Mutex.getName();
+ Warnings.push_back(DelayedDiag(MissingLock.AcquireLoc, Warning));
+ Intersection = Fact.remove(Intersection, Mutex);
}
}
@@ -1268,8 +1258,8 @@
/// we need to verify that the lockset before taking the backedge is the
/// same as the lockset before entering the loop.
///
-/// \param LoopEntrySet Locks held before starting the loop
-/// \param LoopReentrySet Locks held in the last CFG block of the loop
+/// \param LoopEntrySet Locks before starting the loop
+/// \param LoopReentrySet Locks in the last CFG block of the loop
static void warnBackEdgeUnequalLocksets(Sema &S, const Lockset LoopReentrySet,
const Lockset LoopEntrySet,
SourceLocation FirstLocInLoop,
@@ -1281,11 +1271,11 @@
for (Lockset::iterator I = LoopEntrySet.begin(), E = LoopEntrySet.end();
I != E; ++I) {
if (!LoopReentrySet.contains(I.getKey())) {
- const LockID &MissingLock = I.getKey();
+ const MutexID &Mutex = I.getKey();
// We report this error at the location of the first statement in a loop
PartialDiagnostic Warning =
S.PDiag(diag::warn_expecting_lock_held_on_loop)
- << MissingLock.getName() << LK_Shared;
+ << Mutex.getName() << LK_Shared;
Warnings.push_back(DelayedDiag(FirstLocInLoop, Warning));
}
}
@@ -1299,7 +1289,7 @@
/// \brief Check a function's CFG for thread-safety violations.
///
-/// We traverse the blocks in the CFG, compute the set of locks that are held
+/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
static void checkThreadSafety(Sema &S, AnalysisContext &AC) {
@@ -1339,7 +1329,7 @@
// FIXME: By keeping the intersection, we may output more errors in future
// for a lock which is not in the intersection, but was in the union. We
// may want to also keep the union in future. As an example, let's say
- // the intersection contains Lock L, and the union contains L and M.
+ // the intersection contains Mutex L, and the union contains L and M.
// Later we unlock M. At this point, we would output an error because we
// never locked M; although the real error is probably that we forgot to
// lock M on all code paths. Conversely, let's say that later we lock M.
@@ -1404,8 +1394,8 @@
DiagList Warnings;
for (Lockset::iterator I=FinalLockset.begin(), E=FinalLockset.end();
I != E; ++I) {
- const LockID &MissingLock = I.getKey();
- const LockData &MissingLockData = I.getData();
+ const MutexID &Mutex = I.getKey();
+ const LockData &MissingLock = I.getData();
std::string FunName = "<unknown>";
if (const NamedDecl *ContextDecl = dyn_cast<NamedDecl>(AC.getDecl())) {
@@ -1413,9 +1403,9 @@
}
PartialDiagnostic Warning =
- S.PDiag(diag::warn_locks_not_released)
- << MissingLock.getName() << FunName;
- Warnings.push_back(DelayedDiag(MissingLockData.AcquireLoc, Warning));
+ S.PDiag(diag::warn_no_unlock)
+ << Mutex.getName() << FunName;
+ Warnings.push_back(DelayedDiag(MissingLock.AcquireLoc, Warning));
}
EmitDiagnostics(S, Warnings);
}
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=139321&r1=139320&r2=139321&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Thu Sep 8 16:52:50 2011
@@ -123,33 +123,33 @@
void sls_fun_bad_1() {
sls_mu.Unlock(); // \
- // expected-warning{{unlocking 'sls_mu' that was not acquired}}
+ // expected-warning{{unlocking 'sls_mu' that was not locked}}
}
void sls_fun_bad_2() {
sls_mu.Lock();
sls_mu.Lock(); // \
- // expected-warning{{locking 'sls_mu' that is already acquired}}
+ // expected-warning{{locking 'sls_mu' that is already locked}}
sls_mu.Unlock();
}
void sls_fun_bad_3() {
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_3'}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of function 'sls_fun_bad_3'}}
}
void sls_fun_bad_4() {
if (getBool())
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of its scope}}
else
sls_mu2.Lock(); // \
- // expected-warning{{lock 'sls_mu2' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu2' is still held at the end of its scope}}
}
void sls_fun_bad_5() {
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of its scope}}
if (getBool())
sls_mu.Unlock();
}
@@ -157,7 +157,7 @@
void sls_fun_bad_6() {
if (getBool()) {
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of its scope}}
} else {
if (getBool()) {
getBool(); // EMPTY
@@ -166,13 +166,13 @@
}
}
sls_mu.Unlock(); // \
- // expected-warning{{unlocking 'sls_mu' that was not acquired}}
+ // expected-warning{{unlocking 'sls_mu' that was not locked}}
}
void sls_fun_bad_7() {
sls_mu.Lock();
while (getBool()) { // \
- // expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
+ // expected-warning{{expecting lock on 'sls_mu' to be held at start of each loop}}
sls_mu.Unlock();
if (getBool()) {
if (getBool()) {
@@ -180,7 +180,7 @@
}
}
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of its scope}}
}
sls_mu.Unlock();
}
@@ -189,23 +189,23 @@
sls_mu.Lock();
do {
sls_mu.Unlock(); // \
- // expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
+ // expected-warning{{expecting lock on 'sls_mu' to be held at start of each loop}}
} while (getBool());
}
void sls_fun_bad_9() {
do {
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of its scope}}
} while (getBool());
sls_mu.Unlock();
}
void sls_fun_bad_10() {
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of function 'sls_fun_bad_10'}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of function 'sls_fun_bad_10'}}
while(getBool()) { // \
- // expected-warning{{expecting lock 'sls_mu' to be held at start of each loop}}
+ // expected-warning{{expecting lock on 'sls_mu' to be held at start of each loop}}
sls_mu.Unlock();
}
}
@@ -213,10 +213,10 @@
void sls_fun_bad_11() {
while (getBool()) {
sls_mu.Lock(); // \
- // expected-warning{{lock 'sls_mu' is not released at the end of its scope}}
+ // expected-warning{{mutex 'sls_mu' is still held at the end of its scope}}
}
sls_mu.Unlock(); // \
- // expected-warning{{unlocking 'sls_mu' that was not acquired}}
+ // expected-warning{{unlocking 'sls_mu' that was not locked}}
}
//-----------------------------------------//
@@ -240,19 +240,19 @@
void aa_fun_bad_1() {
glock.globalUnlock(); // \
- // expected-warning{{unlocking 'aa_mu' that was not acquired}}
+ // expected-warning{{unlocking 'aa_mu' that was not locked}}
}
void aa_fun_bad_2() {
glock.globalLock();
glock.globalLock(); // \
- // expected-warning{{locking 'aa_mu' that is already acquired}}
+ // expected-warning{{locking 'aa_mu' that is already locked}}
glock.globalUnlock();
}
void aa_fun_bad_3() {
glock.globalLock(); // \
- // expected-warning{{lock 'aa_mu' is not released at the end of function 'aa_fun_bad_3'}}
+ // expected-warning{{mutex 'aa_mu' is still held at the end of function 'aa_fun_bad_3'}}
}
//--------------------------------------------------//
@@ -265,19 +265,19 @@
class WeirdMethods {
WeirdMethods() {
wmu.Lock(); // \
- // expected-warning {{lock 'wmu' is not released at the end of function 'WeirdMethods'}}
+ // expected-warning {{mutex 'wmu' is still held at the end of function 'WeirdMethods'}}
}
~WeirdMethods() {
wmu.Lock(); // \
- // expected-warning {{lock 'wmu' is not released at the end of function '~WeirdMethods'}}
+ // expected-warning {{mutex 'wmu' is still held at the end of function '~WeirdMethods'}}
}
void operator++() {
wmu.Lock(); // \
- // expected-warning {{lock 'wmu' is not released at the end of function 'operator++'}}
+ // expected-warning {{mutex 'wmu' is still held at the end of function 'operator++'}}
}
operator int*() {
wmu.Lock(); // \
- // expected-warning {{lock 'wmu' is not released at the end of function 'operator int *'}}
+ // expected-warning {{mutex 'wmu' is still held at the end of function 'operator int *'}}
return 0;
}
};
@@ -296,13 +296,13 @@
__attribute__((pt_guarded_by(sls_mu)));
void testFoo() {
pgb_field = &x; // \
- // expected-warning {{writing variable 'pgb_field' requires lock 'sls_mu2' to be held exclusively}}
- *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
- // expected-warning {{writing the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held exclusively}}
- x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
- // expected-warning {{reading the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held}}
- (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires lock 'sls_mu2' to be held}} \
- // expected-warning {{writing the value pointed to by 'pgb_field' requires lock 'sls_mu' to be held exclusively}}
+ // expected-warning {{writing variable 'pgb_field' requires lock on 'sls_mu2' to be held exclusively}}
+ *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires lock on 'sls_mu2' to be held}} \
+ // expected-warning {{writing the value pointed to by 'pgb_field' requires lock on 'sls_mu' to be held exclusively}}
+ x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires lock on 'sls_mu2' to be held}} \
+ // expected-warning {{reading the value pointed to by 'pgb_field' requires lock on 'sls_mu' to be held}}
+ (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires lock on 'sls_mu2' to be held}} \
+ // expected-warning {{writing the value pointed to by 'pgb_field' requires lock on 'sls_mu' to be held exclusively}}
}
};
@@ -312,7 +312,7 @@
void testFoo() {
gb_field = 0; // \
- // expected-warning {{writing variable 'gb_field' requires lock 'sls_mu' to be held exclusively}}
+ // expected-warning {{writing variable 'gb_field' requires lock on 'sls_mu' to be held exclusively}}
}
void testNoAnal() __attribute__((no_thread_safety_analysis)) {
@@ -355,12 +355,12 @@
void gb_bad_2() {
sls_guardby_var = 1; // \
- // expected-warning {{writing variable 'sls_guardby_var' requires lock 'sls_mu' to be held exclusively}}
+ // expected-warning {{writing variable 'sls_guardby_var' requires lock on 'sls_mu' to be held exclusively}}
}
void gb_bad_3() {
int x = sls_guardby_var; // \
- // expected-warning {{reading variable 'sls_guardby_var' requires lock 'sls_mu' to be held}}
+ // expected-warning {{reading variable 'sls_guardby_var' requires lock on 'sls_mu' to be held}}
}
void gb_bad_4() {
@@ -375,18 +375,18 @@
void gb_bad_6() {
*pgb_var = 1; // \
- // expected-warning {{writing the value pointed to by 'pgb_var' requires lock 'sls_mu' to be held exclusively}}
+ // expected-warning {{writing the value pointed to by 'pgb_var' requires lock on 'sls_mu' to be held exclusively}}
}
void gb_bad_7() {
int x = *pgb_var; // \
- // expected-warning {{reading the value pointed to by 'pgb_var' requires lock 'sls_mu' to be held}}
+ // expected-warning {{reading the value pointed to by 'pgb_var' requires lock on 'sls_mu' to be held}}
}
void gb_bad_8() {
GBFoo G;
G.gb_field = 0; // \
- // expected-warning {{writing variable 'gb_field' requires lock 'sls_mu'}}
+ // expected-warning {{writing variable 'gb_field' requires lock on 'sls_mu'}}
}
void gb_bad_9() {
@@ -413,11 +413,11 @@
void test() {
a = 0; // \
- // expected-warning{{writing variable 'a' requires lock 'mu' to be held exclusively}}
+ // expected-warning{{writing variable 'a' requires lock on 'mu' to be held exclusively}}
b = a; // \
- // expected-warning {{reading variable 'a' requires lock 'mu' to be held}}
+ // expected-warning {{reading variable 'a' requires lock on 'mu' to be held}}
c = 0; // \
- // expected-warning {{writing variable 'c' requires lock 'mu' to be held exclusively}}
+ // expected-warning {{writing variable 'c' requires lock on 'mu' to be held exclusively}}
}
int c __attribute__((guarded_by(mu)));
@@ -443,7 +443,7 @@
do {
sls_mu.Unlock();
sls_mu.Lock(); // \
- // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
+ // expected-warning {{lock 'sls_mu' is exclusive and shared in the same scope}}
} while (getBool());
sls_mu.Unlock();
}
@@ -469,10 +469,10 @@
void shared_fun_8() {
if (getBool())
sls_mu.Lock(); // \
- // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
+ // expected-warning {{lock 'sls_mu' is exclusive and shared in the same scope}}
else
sls_mu.ReaderLock(); // \
- // expected-note {{the other acquire of lock 'sls_mu' is here}}
+ // expected-note {{the other lock of mutex 'sls_mu' is here}}
sls_mu.Unlock();
}
@@ -481,7 +481,7 @@
do {
sls_mu.Unlock();
sls_mu.ReaderLock(); // \
- // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
+ // expected-warning {{lock 'sls_mu' is exclusive and shared in the same scope}}
} while (getBool());
sls_mu.Unlock();
}
@@ -489,10 +489,10 @@
void shared_bad_1() {
if (getBool())
sls_mu.Lock(); // \
- // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
+ // expected-warning {{lock 'sls_mu' is exclusive and shared in the same scope}}
else
sls_mu.ReaderLock(); // \
- // expected-note {{the other acquire of lock 'sls_mu' is here}}
+ // expected-note {{the other lock of mutex 'sls_mu' is here}}
*pgb_var = 1;
sls_mu.Unlock();
}
@@ -500,10 +500,10 @@
void shared_bad_2() {
if (getBool())
sls_mu.ReaderLock(); // \
- // expected-warning {{lock 'sls_mu' is held exclusively and shared in the same scope}}
+ // expected-warning {{lock 'sls_mu' is exclusive and shared in the same scope}}
else
sls_mu.Lock(); // \
- // expected-note {{the other acquire of lock 'sls_mu' is here}}
+ // expected-note {{the other lock of mutex 'sls_mu' is here}}
*pgb_var = 1;
sls_mu.Unlock();
}
@@ -582,48 +582,48 @@
void es_bad_0() {
Bar.aa_elr_fun(); // \
- // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock 'aa_mu'}}
+ // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
}
void es_bad_1() {
aa_mu.ReaderLock();
Bar.aa_elr_fun(); // \
- // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock 'aa_mu'}}
+ // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
aa_mu.Unlock();
}
void es_bad_2() {
Bar.aa_elr_fun_s(); // \
- // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock 'aa_mu'}}
+ // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
}
void es_bad_3() {
MyLRFoo.test(); // \
- // expected-warning {{calling function 'test' requires exclusive lock 'sls_mu'}}
+ // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
}
void es_bad_4() {
MyLRFoo.testShared(); // \
- // expected-warning {{calling function 'testShared' requires shared lock 'sls_mu2'}}
+ // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
}
void es_bad_5() {
sls_mu.ReaderLock();
MyLRFoo.test(); // \
- // expected-warning {{calling function 'test' requires exclusive lock 'sls_mu'}}
+ // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
sls_mu.Unlock();
}
void es_bad_6() {
sls_mu.Lock();
Bar.le_fun(); // \
- // expected-warning {{cannot call function 'le_fun' while holding lock 'sls_mu'}}
+ // expected-warning {{cannot call function 'le_fun' while holding mutex 'sls_mu'}}
sls_mu.Unlock();
}
void es_bad_7() {
sls_mu.ReaderLock();
Bar.le_fun(); // \
- // expected-warning {{cannot call function 'le_fun' while holding lock 'sls_mu'}}
+ // expected-warning {{cannot call function 'le_fun' while holding mutex 'sls_mu'}}
sls_mu.Unlock();
}
More information about the cfe-commits
mailing list