Thread safety: Adding basic support for locks required and excluded attributes
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139308 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index c155a9e..41b9f3b 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1055,11 +1055,13 @@
/// \brief When visiting CXXMemberCallExprs we need to examine the attributes on
/// the method that is being called and add, remove or check locks in the
/// lockset accordingly.
-///
+///
/// FIXME: For classes annotated with one of the guarded annotations, we need
/// to treat const method calls as reads and non-const method calls as writes,
/// and check that the appropriate locks are held. Non-const method calls with
/// the same signature as const method calls can be also treated as reads.
+///
+/// FIXME: We need to also visit CallExprs to catch/check global functions.
void BuildLockset::VisitCXXMemberCallExpr(CXXMemberCallExpr *Exp) {
NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
@@ -1096,11 +1098,58 @@
}
for (UnlockFunctionAttr::args_iterator I = UFAttr->args_begin(),
- E = UFAttr->args_end(); I != E; ++I)
+ E = UFAttr->args_end(); I != E; ++I)
removeLock(ExpLocation, *I);
break;
}
+ case attr::ExclusiveLocksRequired: {
+ // FIXME: Also use this attribute to add required locks to the initial
+ // lockset when processing a CFG for a function annotated with this
+ // attribute.
+ ExclusiveLocksRequiredAttr *ELRAttr =
+ cast<ExclusiveLocksRequiredAttr>(Attr);
+
+ for (ExclusiveLocksRequiredAttr::args_iterator
+ I = ELRAttr->args_begin(), E = ELRAttr->args_end(); I != E; ++I) {
+ LockID Lock(*I);
+ warnIfLockNotHeld(D, Exp, AK_Written, Lock,
+ diag::warn_fun_requires_lock);
+ }
+ break;
+ }
+
+ case attr::SharedLocksRequired: {
+ // FIXME: Also use this attribute to add required locks to the initial
+ // lockset when processing a CFG for a function annotated with this
+ // attribute.
+ SharedLocksRequiredAttr *SLRAttr = cast<SharedLocksRequiredAttr>(Attr);
+
+ for (SharedLocksRequiredAttr::args_iterator I = SLRAttr->args_begin(),
+ E = SLRAttr->args_end(); I != E; ++I) {
+ LockID Lock(*I);
+ warnIfLockNotHeld(D, Exp, AK_Read, Lock,
+ diag::warn_fun_requires_lock);
+ }
+ break;
+ }
+
+ case attr::LocksExcluded: {
+ 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();
+ }
+ break;
+ }
+
+ case attr::LockReturned:
+ // FIXME: Deal with this attribute.
+ break;
+
// Ignore other (non thread-safety) attributes
default:
break;