[cfe-commits] r142267 - in /cfe/trunk: lib/Analysis/ThreadSafety.cpp test/SemaCXX/warn-thread-safety-analysis.cpp
DeLesley Hutchins
delesley at google.com
Mon Oct 17 14:38:02 PDT 2011
Author: delesley
Date: Mon Oct 17 16:38:02 2011
New Revision: 142267
URL: http://llvm.org/viewvc/llvm-project?rev=142267&view=rev
Log:
Substitute for arguments in method calls -- functionality
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=142267&r1=142266&r2=142267&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Mon Oct 17 16:38:02 2011
@@ -156,23 +156,31 @@
/// Build a Decl sequence representing the lock from the given expression.
/// Recursive function that bottoms out when the final DeclRefExpr is reached.
- // FIXME: Lock expressions that involve array indices or function calls.
- // FIXME: Deal with LockReturned attribute.
- void buildMutexID(Expr *Exp, Expr *Parent) {
+ void buildMutexID(Expr *Exp, Expr *Parent, int NumArgs,
+ const NamedDecl **FunArgDecls, Expr **FunArgs) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
+ if (FunArgDecls) {
+ // Substitute call arguments for references to function parameters
+ for (int i = 0; i < NumArgs; ++i) {
+ if (DRE->getDecl() == FunArgDecls[i]) {
+ buildMutexID(FunArgs[i], 0, 0, 0, 0);
+ return;
+ }
+ }
+ }
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);
- buildMutexID(ME->getBase(), Parent);
+ buildMutexID(ME->getBase(), Parent, NumArgs, FunArgDecls, FunArgs);
} else if (isa<CXXThisExpr>(Exp)) {
if (Parent)
- buildMutexID(Parent, 0);
+ buildMutexID(Parent, 0, 0, 0, 0);
else
return; // mutexID is still valid in this case
} else if (CastExpr *CE = dyn_cast<CastExpr>(Exp))
- buildMutexID(CE->getSubExpr(), Parent);
+ buildMutexID(CE->getSubExpr(), Parent, NumArgs, FunArgDecls, FunArgs);
else
DeclSeq.clear(); // Mark as invalid lock expression.
}
@@ -184,23 +192,36 @@
/// \param D The declaration to which the lock/unlock attribute is attached.
void buildMutexIDFromExp(Expr *MutexExp, Expr *DeclExp, const NamedDecl *D) {
Expr *Parent = 0;
+ unsigned NumArgs = 0;
+ Expr **FunArgs = 0;
+ SmallVector<const NamedDecl*, 8> FunArgDecls;
if (DeclExp == 0) {
- buildMutexID(MutexExp, 0);
+ buildMutexID(MutexExp, 0, 0, 0, 0);
return;
}
- if (MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp))
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
Parent = ME->getBase();
- else if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(DeclExp))
+ } else if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) {
Parent = CE->getImplicitObjectArgument();
+ NumArgs = CE->getNumArgs();
+ FunArgs = CE->getArgs();
+ }
// If the attribute has no arguments, then assume the argument is "this".
if (MutexExp == 0) {
- buildMutexID(Parent, 0);
+ buildMutexID(Parent, 0, 0, 0, 0);
return;
}
- buildMutexID(MutexExp, Parent);
+
+ // FIXME: handle default arguments
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ for (unsigned i = 0, ni = FD->getNumParams(); i < ni && i < NumArgs; ++i) {
+ FunArgDecls.push_back(FD->getParamDecl(i));
+ }
+ }
+ buildMutexID(MutexExp, Parent, NumArgs, &FunArgDecls.front(), FunArgs);
}
public:
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=142267&r1=142266&r2=142267&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Mon Oct 17 16:38:02 2011
@@ -740,6 +740,7 @@
sls_mu.Unlock();
}
+
//-----------------------------------------------//
// Unparseable lock expressions
// ----------------------------------------------//
@@ -1420,3 +1421,57 @@
} // end namespace thread_annot_lock_67_modified
+namespace substitution_test {
+ class MyData {
+ public:
+ Mutex mu;
+
+ void lockData() __attribute__((exclusive_lock_function(mu))) { }
+ void unlockData() __attribute__((unlock_function(mu))) { }
+
+ void doSomething() __attribute__((exclusive_locks_required(mu))) { }
+ };
+
+
+ class DataLocker {
+ public:
+ void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
+ void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
+ };
+
+
+ class Foo {
+ public:
+ void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
+
+ void bar1(MyData* d) {
+ d->lockData();
+ foo(d);
+ d->unlockData();
+ }
+
+ void bar2(MyData* d) {
+ DataLocker dlr;
+ dlr.lockData(d);
+ foo(d);
+ dlr.unlockData(d);
+ }
+
+ void bar3(MyData* d1, MyData* d2) {
+ DataLocker dlr;
+ dlr.lockData(d1); // \
+ // expected-warning {{mutex 'mu' is still locked at the end of function}}
+ dlr.unlockData(d2); // \
+ // expected-warning {{unlocking 'mu' that was not locked}}
+ }
+
+ void bar4(MyData* d1, MyData* d2) {
+ DataLocker dlr;
+ dlr.lockData(d1);
+ foo(d2); // \
+ // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
+ dlr.unlockData(d1);
+ }
+ };
+} // end namespace substituation_test
+
More information about the cfe-commits
mailing list