summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeLesley Hutchins <delesley@google.com>2015-09-29 16:24:18 +0000
committerDeLesley Hutchins <delesley@google.com>2015-09-29 16:24:18 +0000
commit2b504dce14ef817a6a3f83cedee9f6f20066a93d (patch)
tree9bfaa0593852ff43fd66631913c4bdb7189570d1
parent32d4d37e614f005e981f61ad278808f6da213bca (diff)
downloadbcm5719-llvm-2b504dce14ef817a6a3f83cedee9f6f20066a93d.tar.gz
bcm5719-llvm-2b504dce14ef817a6a3f83cedee9f6f20066a93d.zip
Thread Safety Analysis: allow capability attribute on unions.
llvm-svn: 248805
-rw-r--r--clang/include/clang/Basic/Attr.td4
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp11
-rw-r--r--clang/test/Sema/attr-capabilities.c8
-rw-r--r--clang/test/SemaCXX/warn-thread-safety-analysis.cpp23
4 files changed, 35 insertions, 11 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 4b8a7b71f99..a758a4c35e5 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1543,8 +1543,8 @@ def Capability : InheritableAttr {
let Spellings = [GNU<"capability">, CXX11<"clang", "capability">,
GNU<"shared_capability">,
CXX11<"clang", "shared_capability">];
- let Subjects = SubjectList<[Struct, TypedefName], ErrorDiag,
- "ExpectedStructOrTypedef">;
+ let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
+ "ExpectedStructOrUnionOrTypedef">;
let Args = [StringArgument<"Name">];
let Accessors = [Accessor<"isShared",
[GNU<"shared_capability">,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 9cc082152bb..8218c20696d 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -628,13 +628,10 @@ static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,
// Check that this attribute only applies to lockable types.
QualType QT = cast<ValueDecl>(D)->getType();
- if (!QT->isDependentType()) {
- const RecordType *RT = getRecordType(QT);
- if (!RT || !RT->getDecl()->hasAttr<CapabilityAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
- << Attr.getName();
- return false;
- }
+ if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
+ S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable)
+ << Attr.getName();
+ return false;
}
// Check that all arguments are lockable objects.
diff --git a/clang/test/Sema/attr-capabilities.c b/clang/test/Sema/attr-capabilities.c
index 5bfbdacf508..89967704865 100644
--- a/clang/test/Sema/attr-capabilities.c
+++ b/clang/test/Sema/attr-capabilities.c
@@ -4,11 +4,15 @@ typedef int __attribute__((capability("role"))) ThreadRole;
struct __attribute__((shared_capability("mutex"))) Mutex {};
struct NotACapability {};
+// Put capability attributes on unions
+union __attribute__((capability("mutex"))) MutexUnion { int a; char* b; };
+typedef union { int a; char* b; } __attribute__((capability("mutex"))) MutexUnion2;
+
// Test an invalid capability name
struct __attribute__((capability("wrong"))) IncorrectName {}; // expected-warning {{invalid capability name 'wrong'; capability name must be 'mutex' or 'role'}}
-int Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs and typedefs}}
-int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs and typedefs}}
+int Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs, unions, and typedefs}}
+int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs, unions, and typedefs}}
int Test3 __attribute__((acquire_capability("test3"))); // expected-warning {{'acquire_capability' attribute only applies to functions}}
int Test4 __attribute__((try_acquire_capability("test4"))); // expected-error {{'try_acquire_capability' attribute only applies to functions}}
int Test5 __attribute__((release_capability("test5"))); // expected-warning {{'release_capability' attribute only applies to functions}}
diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
index 6daefd78d3d..01e16a488c9 100644
--- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -5159,3 +5159,26 @@ void test3() {
} // end namespace GlobalAcquiredBeforeAfterTest
+
+namespace LockableUnions {
+
+union LOCKABLE MutexUnion {
+ int a;
+ char* b;
+
+ void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void Unlock() UNLOCK_FUNCTION();
+};
+
+MutexUnion muun2;
+MutexUnion muun1 ACQUIRED_BEFORE(muun2);
+
+void test() {
+ muun2.Lock();
+ muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}
+ muun1.Unlock();
+ muun2.Unlock();
+}
+
+} // end namespace LockableUnions
+
OpenPOWER on IntegriCloud