aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2011-10-21 20:51:27 +0000
committerDeLesley Hutchins <delesley@google.com>2011-10-21 20:51:27 +0000
commit6db51f707e93816364039a2a904d13d3968c7f05 (patch)
tree63ab532016002b16b4f2e00b5e4f9d5a36a7266b
parentf1ac63702143d84db778d32eb185a77fc97db5f5 (diff)
Added support for thread safety attributes on destructors.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142685 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/ThreadSafety.cpp29
-rw-r--r--test/SemaCXX/warn-thread-safety-analysis.cpp6
2 files changed, 29 insertions, 6 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 5b813ff2ea..7b9a693bb7 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -227,6 +227,9 @@ class MutexID {
Parent = 0; // FIXME -- get the parent from DeclStmt
NumArgs = CE->getNumArgs();
FunArgs = CE->getArgs();
+ } else if (D && isa<CXXDestructorDecl>(D)) {
+ // There's no such thing as a "destructor call" in the AST.
+ Parent = DeclExp;
}
// If the attribute has no arguments, then assume the argument is "this".
@@ -879,8 +882,30 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisContext &AC) {
BuildLockset LocksetBuilder(Handler, Entryset, LocksetFactory);
for (CFGBlock::const_iterator BI = CurrBlock->begin(),
BE = CurrBlock->end(); BI != BE; ++BI) {
- if (const CFGStmt *CfgStmt = dyn_cast<CFGStmt>(&*BI))
- LocksetBuilder.Visit(const_cast<Stmt*>(CfgStmt->getStmt()));
+ switch (BI->getKind()) {
+ case CFGElement::Statement: {
+ const CFGStmt *CS = cast<CFGStmt>(&*BI);
+ LocksetBuilder.Visit(const_cast<Stmt*>(CS->getStmt()));
+ break;
+ }
+ // Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
+ case CFGElement::AutomaticObjectDtor: {
+ const CFGAutomaticObjDtor *AD = cast<CFGAutomaticObjDtor>(&*BI);
+ CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
+ AD->getDestructorDecl(AC.getASTContext()));
+ if (!DD->hasAttrs())
+ break;
+
+ // Create a dummy expression,
+ VarDecl *VD = const_cast<VarDecl*>(AD->getVarDecl());
+ DeclRefExpr DRE(VD, VD->getType(), VK_LValue,
+ AD->getTriggerStmt()->getLocEnd());
+ LocksetBuilder.handleCall(&DRE, DD);
+ break;
+ }
+ default:
+ break;
+ }
}
Exitset = LocksetBuilder.getLockset();
diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp
index 14ef6d1c04..7adead763e 100644
--- a/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -1487,9 +1487,7 @@ namespace constructor_destructor_tests {
};
void fooTest() {
- // destructors not implemented yet...
- Foo foo; // \
- // expected-warning {{mutex 'fooMu' is still locked at the end of function}}
+ Foo foo;
myVar = 0;
}
}
@@ -1500,7 +1498,7 @@ namespace invalid_lock_expression_test {
class LOCKABLE MyLockable {
public:
MyLockable() __attribute__((exclusive_lock_function)) { }
- ~MyLockable() __attribute__((unlock_function)) { }
+ ~MyLockable() { }
};
// create an empty lock expression