From 43399fb0e79687043b7904195e95a23e44bd6ca1 Mon Sep 17 00:00:00 2001 From: DeLesley Hutchins Date: Tue, 5 Nov 2013 23:09:56 +0000 Subject: [PATCH] Thread safety analysis: check pt_guarded_by attribute when calling -> and * on smart pointers. -Wthread-safety-beta only. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194103 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ThreadSafety.cpp | 8 ++ test/SemaCXX/warn-thread-safety-analysis.cpp | 84 ++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index e5e5f18b51..607526db3e 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -2134,6 +2134,14 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) { checkAccess(Source, AK_Read); break; } + case OO_Star: + case OO_Arrow: { + if (Analyzer->Handler.issueBetaWarnings()) { + const Expr *Target = OE->getArg(0); + checkPtAccess(Target, AK_Read); + } + break; + } default: { const Expr *Source = OE->getArg(0); checkAccess(Source, AK_Read); diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 08c6f8582a..8ea411325f 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -4142,3 +4142,87 @@ public: } // end namespace LogicalConditionalTryLock + + +namespace PtGuardedByTest { + +void doSomething(); + +class Cell { + public: + int a; +}; + + +// This mainly duplicates earlier tests, but just to make sure... +class PtGuardedBySanityTest { + Mutex mu1; + Mutex mu2; + int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2); + + void test1() { + mu1.Lock(); + if (a == 0) doSomething(); // OK, we don't dereference. + a = 0; + c = 0; + mu1.Unlock(); + } + + void test2() { + mu1.ReaderLock(); + if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires locking 'mu2'}} + *a = 0; // expected-warning {{writing the value pointed to by 'a' requires locking 'mu2' exclusively}} + + if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} + c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + + if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires locking 'mu2'}} + (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires locking 'mu2' exclusively}} + mu1.Unlock(); + } + + void test3() { + mu2.Lock(); + if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires locking 'mu1'}} + *a = 0; // expected-warning {{reading variable 'a' requires locking 'mu1'}} + + if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} + c->a = 0; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + + if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires locking 'mu1'}} + (*c).a = 0; // expected-warning {{reading variable 'c' requires locking 'mu1'}} + mu2.Unlock(); + } + + void test4() { + mu1.ReaderLock(); // OK -- correct use. + mu2.Lock(); + if (*a == 0) doSomething(); + *a = 0; + + if (c->a == 0) doSomething(); + c->a = 0; + + if ((*c).a == 0) doSomething(); + (*c).a = 0; + mu2.Unlock(); + mu1.Unlock(); + } +}; + + +class SmartPtr_PtGuardedBy_Test { + Mutex mu2; + SmartPtr sp PT_GUARDED_BY(mu2); + SmartPtr sq PT_GUARDED_BY(mu2); + + void test() { + sp.get(); // OK -- no GUARDED_BY + *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires locking 'mu2'}} + sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires locking 'mu2'}} + } +}; + +} // end namespace PtGuardedByTest + -- 2.40.0