aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp13
-rw-r--r--clang/test/SemaCXX/warn-thread-safety-analysis.cpp7
-rw-r--r--clang/test/SemaCXX/warn-thread-safety-negative.cpp29
3 files changed, 44 insertions, 5 deletions
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 64e0da9..1d4aaba 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1266,13 +1266,22 @@ ClassifyDiagnostic(const AttrTy *A) {
}
bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
- if (!CurrentMethod)
+ const threadSafety::til::SExpr *SExp = CapE.sexpr();
+ assert(SExp && "Null expressions should be ignored");
+
+ // Global variables are always in scope.
+ if (isa<til::LiteralPtr>(SExp))
+ return true;
+
+ // Members are in scope from methods of the same class.
+ if (const auto *P = dyn_cast<til::Project>(SExp)) {
+ if (!CurrentMethod)
return false;
- if (const auto *P = dyn_cast_or_null<til::Project>(CapE.sexpr())) {
const auto *VD = P->clangDecl();
if (VD)
return VD->getDeclContext() == CurrentMethod->getDeclContext();
}
+
return false;
}
diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
index 91bd15d..d1520b1 100644
--- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -5036,7 +5036,8 @@ void spawn_fake_flight_control_thread(void) {
}
extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
-void logger_entry(void) __attribute__((requires_capability(Logger))) {
+void logger_entry(void) __attribute__((requires_capability(Logger)))
+ __attribute__((requires_capability(!FlightControl))) {
const char *msg;
while ((msg = deque_log_msg())) {
@@ -5044,13 +5045,13 @@ void logger_entry(void) __attribute__((requires_capability(Logger))) {
}
}
-void spawn_fake_logger_thread(void) {
+void spawn_fake_logger_thread(void) __attribute__((requires_capability(!FlightControl))) {
acquire(Logger);
logger_entry();
release(Logger);
}
-int main(void) {
+int main(void) __attribute__((requires_capability(!FlightControl))) {
spawn_fake_flight_control_thread();
spawn_fake_logger_thread();
diff --git a/clang/test/SemaCXX/warn-thread-safety-negative.cpp b/clang/test/SemaCXX/warn-thread-safety-negative.cpp
index 456fe16..68e30f4 100644
--- a/clang/test/SemaCXX/warn-thread-safety-negative.cpp
+++ b/clang/test/SemaCXX/warn-thread-safety-negative.cpp
@@ -81,6 +81,35 @@ public:
} // end namespace SimpleTest
+Mutex globalMutex;
+
+namespace ScopeTest {
+
+void f() EXCLUSIVE_LOCKS_REQUIRED(!globalMutex);
+void fq() EXCLUSIVE_LOCKS_REQUIRED(!::globalMutex);
+
+namespace ns {
+ Mutex globalMutex;
+ void f() EXCLUSIVE_LOCKS_REQUIRED(!globalMutex);
+ void fq() EXCLUSIVE_LOCKS_REQUIRED(!ns::globalMutex);
+}
+
+void testGlobals() EXCLUSIVE_LOCKS_REQUIRED(!ns::globalMutex) {
+ f(); // expected-warning {{calling function 'f' requires negative capability '!globalMutex'}}
+ fq(); // expected-warning {{calling function 'fq' requires negative capability '!globalMutex'}}
+ ns::f();
+ ns::fq();
+}
+
+void testNamespaceGlobals() EXCLUSIVE_LOCKS_REQUIRED(!globalMutex) {
+ f();
+ fq();
+ ns::f(); // expected-warning {{calling function 'f' requires negative capability '!globalMutex'}}
+ ns::fq(); // expected-warning {{calling function 'fq' requires negative capability '!globalMutex'}}
+}
+
+} // end namespace ScopeTest
+
namespace DoubleAttribute {
struct Foo {