]> granicus.if.org Git - clang/commitdiff
Thread Safety Analysis: allow capability attribute on unions.
authorDeLesley Hutchins <delesley@google.com>
Tue, 29 Sep 2015 16:24:18 +0000 (16:24 +0000)
committerDeLesley Hutchins <delesley@google.com>
Tue, 29 Sep 2015 16:24:18 +0000 (16:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@248805 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
lib/Sema/SemaDeclAttr.cpp
test/Sema/attr-capabilities.c
test/SemaCXX/warn-thread-safety-analysis.cpp

index 4b8a7b71f99562d915cd0398c33296bab7911842..a758a4c35e518f737c5aa6883c7349511fdcf60d 100644 (file)
@@ -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">,
index 9cc082152bb6d750c5482aab63999c2ac04813c8..8218c20696da1455334cdc8b1c4e67a82c7a7b3a 100644 (file)
@@ -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.
index 5bfbdacf508fac831604c7cb10c2434132484282..89967704865fe1e448b149b69b8f59cef78e99b7 100644 (file)
@@ -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}}
index 6daefd78d3df72894bb11affeb23194f17c5aeb2..01e16a488c9b49ae0d68c2774697f15ea79cb305 100644 (file)
@@ -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
+