<div dir="ltr">Sorry for the breakage, I'm reverting the patch that caused this now.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 11, 2017 at 12:36 AM, NAKAMURA Takumi <span dir="ltr"><<a href="mailto:geek4civic@gmail.com" target="_blank">geek4civic@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">It causes failure in check-libcxx with just-built clang.<div><br></div><div><a href="http://bb.pgr.jp/builders/bootstrap-clang-libcxx-lld-i686-linux/builds/758" target="_blank">http://bb.pgr.jp/builders/<wbr>bootstrap-clang-libcxx-lld-<wbr>i686-linux/builds/758</a><div><div class="h5"><br><br><div class="gmail_quote"><div dir="ltr">On Wed, Aug 9, 2017 at 4:45 AM Josh Gao via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jmgao<br>
Date: Tue Aug  8 12:44:35 2017<br>
New Revision: 310403<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=310403&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=310403&view=rev</a><br>
Log:<br>
Thread Safety Analysis: warn on nonsensical attributes.<br>
<br>
Add warnings in cases where an implicit `this` argument is expected to<br>
attributes because either `this` doesn't exist because the attribute is<br>
on a free function, or because `this` is on a type that doesn't have a<br>
corresponding capability/lockable/scoped_<wbr>lockable attribute.<br>
<br>
Reviewers: delesley, aaron.ballman<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D36237" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D36237</a><br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp<br>
    cfe/trunk/test/Sema/attr-<wbr>capabilities.c<br>
    cfe/trunk/test/SemaCXX/warn-<wbr>thread-safety-parsing.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=310403&r1=310402&r2=310403&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticSemaKinds.td?rev=<wbr>310403&r1=310402&r2=310403&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Tue Aug  8 12:44:35 2017<br>
@@ -2932,6 +2932,16 @@ def warn_thread_attribute_decl_<wbr>not_locka<br>
   "%0 attribute can only be applied in a context annotated "<br>
   "with 'capability(\"mutex\")' attribute">,<br>
   InGroup<<wbr>ThreadSafetyAttributes>, DefaultIgnore;<br>
+def warn_thread_attribute_noargs_<wbr>not_lockable : Warning<<br>
+  "%0 attribute requires type annotated with 'capability' attribute; "<br>
+  "type here is %1">,<br>
+  InGroup<<wbr>ThreadSafetyAttributes>, DefaultIgnore;<br>
+def warn_thread_attribute_noargs_<wbr>not_method : Warning<<br>
+  "%0 attribute without arguments can only be applied to a method of a class">,<br>
+  InGroup<<wbr>ThreadSafetyAttributes>, DefaultIgnore;<br>
+def warn_thread_attribute_noargs_<wbr>static_method : Warning<<br>
+  "%0 attribute without arguments cannot be applied to a static method">,<br>
+  InGroup<<wbr>ThreadSafetyAttributes>, DefaultIgnore;<br>
 def warn_thread_attribute_decl_<wbr>not_pointer : Warning<<br>
   "%0 only applies to pointer types; type here is %1">,<br>
   InGroup<<wbr>ThreadSafetyAttributes>, DefaultIgnore;<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=310403&r1=310402&r2=310403&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp?rev=310403&<wbr>r1=310402&r2=310403&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp Tue Aug  8 12:44:35 2017<br>
@@ -480,7 +480,7 @@ static const RecordType *getRecordType(Q<br>
   return nullptr;<br>
 }<br>
<br>
-static bool checkRecordTypeForCapability(<wbr>Sema &S, QualType Ty) {<br>
+template <typename T> static bool checkRecordTypeForAttr(Sema &S, QualType Ty) {<br>
   const RecordType *RT = getRecordType(Ty);<br>
<br>
   if (!RT)<br>
@@ -497,7 +497,7 @@ static bool checkRecordTypeForCapability<br>
<br>
   // Check if the record itself has a capability.<br>
   RecordDecl *RD = RT->getDecl();<br>
-  if (RD->hasAttr<CapabilityAttr>()<wbr>)<br>
+  if (RD->hasAttr<T>())<br>
     return true;<br>
<br>
   // Else check if any base classes have a capability.<br>
@@ -505,14 +505,14 @@ static bool checkRecordTypeForCapability<br>
     CXXBasePaths BPaths(false, false);<br>
     if (CRD->lookupInBases([](const CXXBaseSpecifier *BS, CXXBasePath &) {<br>
           const auto *Type = BS->getType()->getAs<<wbr>RecordType>();<br>
-          return Type->getDecl()->hasAttr<<wbr>CapabilityAttr>();<br>
+          return Type->getDecl()->hasAttr<T>();<br>
         }, BPaths))<br>
       return true;<br>
   }<br>
   return false;<br>
 }<br>
<br>
-static bool checkTypedefTypeForCapability(<wbr>QualType Ty) {<br>
+template <typename T> static bool checkTypedefTypeForAttr(<wbr>QualType Ty) {<br>
   const auto *TD = Ty->getAs<TypedefType>();<br>
   if (!TD)<br>
     return false;<br>
@@ -521,19 +521,27 @@ static bool checkTypedefTypeForCapabilit<br>
   if (!TN)<br>
     return false;<br>
<br>
-  return TN->hasAttr<CapabilityAttr>();<br>
+  return TN->hasAttr<T>();<br>
 }<br>
<br>
-static bool typeHasCapability(Sema &S, QualType Ty) {<br>
-  if (<wbr>checkTypedefTypeForCapability(<wbr>Ty))<br>
+template <typename T> static bool typeHasAttr(Sema &S, QualType Ty) {<br>
+  if (checkTypedefTypeForAttr<T>(<wbr>Ty))<br>
     return true;<br>
<br>
-  if (checkRecordTypeForCapability(<wbr>S, Ty))<br>
+  if (checkRecordTypeForAttr<T>(S, Ty))<br>
     return true;<br>
<br>
   return false;<br>
 }<br>
<br>
+static bool typeHasCapability(Sema &S, QualType Ty) {<br>
+  return typeHasAttr<CapabilityAttr>(S, Ty);<br>
+}<br>
+<br>
+static bool typeHasScopedLockable(Sema &S, QualType Ty) {<br>
+  return typeHasAttr<<wbr>ScopedLockableAttr>(S, Ty);<br>
+}<br>
+<br>
 static bool isCapabilityExpr(Sema &S, const Expr *Ex) {<br>
   // Capability expressions are simple expressions involving the boolean logic<br>
   // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once<br>
@@ -570,6 +578,8 @@ static void checkAttrArgsAreCapabilityOb<br>
                                            SmallVectorImpl<Expr *> &Args,<br>
                                            int Sidx = 0,<br>
                                            bool ParamIdxOk = false) {<br>
+  bool TriedParam = false;<br>
+<br>
   for (unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {<br>
     Expr *ArgExp = Attr.getArgAsExpr(Idx);<br>
<br>
@@ -610,15 +620,18 @@ static void checkAttrArgsAreCapabilityOb<br>
     const RecordType *RT = getRecordType(ArgTy);<br>
<br>
     // Now check if we index into a record type function param.<br>
-    if(!RT && ParamIdxOk) {<br>
+    if (!RT && ParamIdxOk) {<br>
       FunctionDecl *FD = dyn_cast<FunctionDecl>(D);<br>
       IntegerLiteral *IL = dyn_cast<IntegerLiteral>(<wbr>ArgExp);<br>
-      if(FD && IL) {<br>
+      if (FD && IL) {<br>
+        // Don't emit free function warnings if an index was given.<br>
+        TriedParam = true;<br>
+<br>
         unsigned int NumParams = FD->getNumParams();<br>
         llvm::APInt ArgValue = IL->getValue();<br>
         uint64_t ParamIdxFromOne = ArgValue.getZExtValue();<br>
         uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;<br>
-        if(!ArgValue.<wbr>isStrictlyPositive() || ParamIdxFromOne > NumParams) {<br>
+        if (!ArgValue.isStrictlyPositive(<wbr>) || ParamIdxFromOne > NumParams) {<br>
           S.Diag(Attr.getLoc(), diag::err_attribute_argument_<wbr>out_of_range)<br>
             << Attr.getName() << Idx + 1 << NumParams;<br>
           continue;<br>
@@ -637,6 +650,28 @@ static void checkAttrArgsAreCapabilityOb<br>
<br>
     Args.push_back(ArgExp);<br>
   }<br>
+<br>
+  // If we don't have any lockable arguments, verify that we're an instance<br>
+  // method on a lockable type.<br>
+  if (Args.empty() && !TriedParam) {<br>
+    if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {<br>
+      if (MD->isStatic()) {<br>
+        S.Diag(Attr.getLoc(), diag::warn_thread_attribute_<wbr>noargs_static_method)<br>
+            << Attr.getName();<br>
+        return;<br>
+      }<br>
+<br>
+      QualType ThisType = MD->getThisType(MD-><wbr>getASTContext());<br>
+      if (!typeHasCapability(S, ThisType) &&<br>
+          !typeHasScopedLockable(S, ThisType)) {<br>
+        S.Diag(Attr.getLoc(), diag::warn_thread_attribute_<wbr>noargs_not_lockable)<br>
+            << Attr.getName() << ThisType;<br>
+      }<br>
+    } else {<br>
+      S.Diag(Attr.getLoc(), diag::warn_thread_attribute_<wbr>noargs_not_method)<br>
+          << Attr.getName();<br>
+    }<br>
+  }<br>
 }<br>
<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
Modified: cfe/trunk/test/Sema/attr-<wbr>capabilities.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-capabilities.c?rev=310403&r1=310402&r2=310403&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>attr-capabilities.c?rev=<wbr>310403&r1=310402&r2=310403&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Sema/attr-<wbr>capabilities.c (original)<br>
+++ cfe/trunk/test/Sema/attr-<wbr>capabilities.c Tue Aug  8 12:44:35 2017<br>
@@ -37,15 +37,25 @@ void Func6(void) __attribute__((requires<br>
 void Func7(void) __attribute__((assert_<wbr>capability(GUI))) {}<br>
 void Func8(void) __attribute__((assert_shared_<wbr>capability(GUI))) {}<br>
<br>
+void Func9(void) __attribute__((assert_<wbr>capability())) {} // expected-warning {{'assert_capability' attribute without arguments can only be applied to a method of a class}}<br>
+void Func10(void) __attribute__((assert_shared_<wbr>capability())) {} // expected-warning {{'assert_shared_capability' attribute without arguments can only be applied to a method of a class}}<br>
+<br>
 void Func11(void) __attribute__((acquire_<wbr>capability(GUI))) {}<br>
 void Func12(void) __attribute__((acquire_shared_<wbr>capability(GUI))) {}<br>
<br>
+void Func13(void) __attribute__((acquire_<wbr>capability())) {} // expected-warning {{'acquire_capability' attribute without arguments can only be applied to a method of a class}}<br>
+void Func14(void) __attribute__((acquire_shared_<wbr>capability())) {} // expected-warning {{'acquire_shared_capability' attribute without arguments can only be applied to a method of a class}}<br>
+<br>
 void Func15(void) __attribute__((release_<wbr>capability(GUI))) {}<br>
 void Func16(void) __attribute__((release_shared_<wbr>capability(GUI))) {}<br>
 void Func17(void) __attribute__((release_<wbr>generic_capability(GUI))) {}<br>
<br>
-void Func21(void) __attribute__((try_acquire_<wbr>capability(1))) {}<br>
-void Func22(void) __attribute__((try_acquire_<wbr>shared_capability(1))) {}<br>
+void Func18(void) __attribute__((release_<wbr>capability())) {} // expected-warning {{'release_capability' attribute without arguments can only be applied to a method of a class}}<br>
+void Func19(void) __attribute__((release_shared_<wbr>capability())) {} // expected-warning {{'release_shared_capability' attribute without arguments can only be applied to a method of a class}}<br>
+void Func20(void) __attribute__((release_<wbr>generic_capability())) {} // expected-warning {{'release_generic_capability' attribute without arguments can only be applied to a method of a class}}<br>
+<br>
+void Func21(void) __attribute__((try_acquire_<wbr>capability(1))) {} // expected-warning {{'try_acquire_capability' attribute without arguments can only be applied to a method of a class}}<br>
+void Func22(void) __attribute__((try_acquire_<wbr>shared_capability(1))) {} // expected-warning {{'try_acquire_shared_<wbr>capability' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 void Func23(void) __attribute__((try_acquire_<wbr>capability(1, GUI))) {}<br>
 void Func24(void) __attribute__((try_acquire_<wbr>shared_capability(1, GUI))) {}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/warn-<wbr>thread-safety-parsing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-parsing.cpp?rev=310403&r1=310402&r2=310403&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/warn-thread-safety-<wbr>parsing.cpp?rev=310403&r1=<wbr>310402&r2=310403&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/warn-<wbr>thread-safety-parsing.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/warn-<wbr>thread-safety-parsing.cpp Tue Aug  8 12:44:35 2017<br>
@@ -571,11 +571,11 @@ UnlockableMu ab_var_arg_bad_5 ACQUIRED_B<br>
<br>
 // takes zero or more arguments, all locks (vars/fields)<br>
<br>
-void elf_function() EXCLUSIVE_LOCK_FUNCTION();<br>
+void elf_function() EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 void elf_function_args() EXCLUSIVE_LOCK_FUNCTION(mu1, mu2);<br>
<br>
-int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION();<br>
+int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 int elf_testfn(int y) {<br>
   int x EXCLUSIVE_LOCK_FUNCTION() = y; // \<br>
@@ -590,7 +590,7 @@ class ElfFoo {<br>
  private:<br>
   int test_field EXCLUSIVE_LOCK_FUNCTION(); // \<br>
     // expected-warning {{'exclusive_lock_function' attribute only applies to functions}}<br>
-  void test_method() EXCLUSIVE_LOCK_FUNCTION();<br>
+  void test_method() EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute requires type annotated with 'capability' attribute; type here is 'ElfFoo *'}}<br>
 };<br>
<br>
 class EXCLUSIVE_LOCK_FUNCTION() ElfTestClass { // \<br>
@@ -643,11 +643,11 @@ int elf_function_bad_7() EXCLUSIVE_LOCK_<br>
<br>
 // takes zero or more arguments, all locks (vars/fields)<br>
<br>
-void slf_function() SHARED_LOCK_FUNCTION();<br>
+void slf_function() SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 void slf_function_args() SHARED_LOCK_FUNCTION(mu1, mu2);<br>
<br>
-int slf_testfn(int y) SHARED_LOCK_FUNCTION();<br>
+int slf_testfn(int y) SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 int slf_testfn(int y) {<br>
   int x SHARED_LOCK_FUNCTION() = y; // \<br>
@@ -665,7 +665,8 @@ class SlfFoo {<br>
  private:<br>
   int test_field SHARED_LOCK_FUNCTION(); // \<br>
     // expected-warning {{'shared_lock_function' attribute only applies to functions}}<br>
-  void test_method() SHARED_LOCK_FUNCTION();<br>
+  void test_method() SHARED_LOCK_FUNCTION(); // \<br>
+    // expected-warning {{'shared_lock_function' attribute requires type annotated with 'capability' attribute; type here is 'SlfFoo *'}}<br>
 };<br>
<br>
 class SHARED_LOCK_FUNCTION() SlfTestClass { // \<br>
@@ -716,14 +717,16 @@ int slf_function_bad_7() SHARED_LOCK_FUN<br>
 // takes a mandatory boolean or integer argument specifying the retval<br>
 // plus an optional list of locks (vars/fields)<br>
<br>
-void etf_function() __attribute__((exclusive_<wbr>trylock_function));  // \<br>
-  // expected-error {{'exclusive_trylock_function' attribute takes at least 1 argument}}<br>
+void etf_function() __attribute__((exclusive_<wbr>trylock_function)); // \<br>
+  // expected-error {{'exclusive_trylock_function' attribute takes at least 1 argument}} \<br>
<br>
 void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2);<br>
<br>
-void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1);<br>
+void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \<br>
+  // expected-warning {{'exclusive_trylock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
-int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1);<br>
+int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); // \<br>
+  // expected-warning {{'exclusive_trylock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 int etf_testfn(int y) {<br>
   int x EXCLUSIVE_TRYLOCK_FUNCTION(1) = y; // \<br>
@@ -732,13 +735,14 @@ int etf_testfn(int y) {<br>
 };<br>
<br>
 int etf_test_var EXCLUSIVE_TRYLOCK_FUNCTION(1); // \<br>
-  // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}}<br>
+  // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} \<br>
<br>
 class EtfFoo {<br>
  private:<br>
   int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \<br>
     // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}}<br>
-  void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1);<br>
+  void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \<br>
+    // expected-warning {{'exclusive_trylock_function' attribute requires type annotated with 'capability' attribute; type here is 'EtfFoo *'}}<br>
 };<br>
<br>
 class EXCLUSIVE_TRYLOCK_FUNCTION(1) EtfTestClass { // \<br>
@@ -759,7 +763,8 @@ int etf_function_5() EXCLUSIVE_TRYLOCK_F<br>
 int etf_function_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, muRef);<br>
 int etf_function_7() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()-><wbr>getMu());<br>
 int etf_functetfn_8() EXCLUSIVE_TRYLOCK_FUNCTION(1, muPointer);<br>
-int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(<wbr>true);<br>
+int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(<wbr>true); // \<br>
+  // expected-warning {{'exclusive_trylock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
<br>
 // illegal attribute arguments<br>
@@ -794,9 +799,11 @@ void stf_function() __attribute__((share<br>
<br>
 void stf_function_args() SHARED_TRYLOCK_FUNCTION(1, mu2);<br>
<br>
-void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1);<br>
+void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); // \<br>
+  // expected-warning {{'shared_trylock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
-int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1);<br>
+int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); // \<br>
+  // expected-warning {{'shared_trylock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 int stf_testfn(int y) {<br>
   int x SHARED_TRYLOCK_FUNCTION(1) = y; // \<br>
@@ -815,7 +822,8 @@ class StfFoo {<br>
  private:<br>
   int test_field SHARED_TRYLOCK_FUNCTION(1); // \<br>
     // expected-warning {{'shared_trylock_function' attribute only applies to functions}}<br>
-  void test_method() SHARED_TRYLOCK_FUNCTION(1);<br>
+  void test_method() SHARED_TRYLOCK_FUNCTION(1); // \<br>
+    // expected-warning {{'shared_trylock_function' attribute requires type annotated with 'capability' attribute; type here is 'StfFoo *'}}<br>
 };<br>
<br>
 class SHARED_TRYLOCK_FUNCTION(1) StfTestClass { // \<br>
@@ -833,7 +841,8 @@ int stf_function_5() SHARED_TRYLOCK_FUNC<br>
 int stf_function_6() SHARED_TRYLOCK_FUNCTION(1, muRef);<br>
 int stf_function_7() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()-><wbr>getMu());<br>
 int stf_function_8() SHARED_TRYLOCK_FUNCTION(1, muPointer);<br>
-int stf_function_9() SHARED_TRYLOCK_FUNCTION(true);<br>
+int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); // \<br>
+  // expected-warning {{'shared_trylock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
<br>
 // illegal attribute arguments<br>
@@ -862,11 +871,14 @@ int stf_function_bad_6() SHARED_TRYLOCK_<br>
<br>
 // takes zero or more arguments, all locks (vars/fields)<br>
<br>
-void uf_function() UNLOCK_FUNCTION();<br>
+void uf_function() UNLOCK_FUNCTION(); // \<br>
+  // expected-warning {{'unlock_function' attribute without arguments can only be applied to a method of a class}}<br>
+<br>
<br>
 void uf_function_args() UNLOCK_FUNCTION(mu1, mu2);<br>
<br>
-int uf_testfn(int y) UNLOCK_FUNCTION();<br>
+int uf_testfn(int y) UNLOCK_FUNCTION(); //\<br>
+  // expected-warning {{'unlock_function' attribute without arguments can only be applied to a method of a class}}<br>
<br>
 int uf_testfn(int y) {<br>
   int x UNLOCK_FUNCTION() = y; // \<br>
@@ -881,7 +893,8 @@ class UfFoo {<br>
  private:<br>
   int test_field UNLOCK_FUNCTION(); // \<br>
     // expected-warning {{'unlock_function' attribute only applies to functions}}<br>
-  void test_method() UNLOCK_FUNCTION();<br>
+  void test_method() UNLOCK_FUNCTION(); // \<br>
+    // expected-warning {{'unlock_function' attribute requires type annotated with 'capability' attribute; type here is 'UfFoo *'}}<br>
 };<br>
<br>
 class NO_THREAD_SAFETY_ANALYSIS UfTestClass { // \<br>
@@ -1524,4 +1537,4 @@ namespace CRASH_POST_R301735 {<br>
      Mutex mu_;<br>
    };<br>
 }<br>
-#endif<br>
\ No newline at end of file<br>
+#endif<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div></div></div>
</blockquote></div><br></div>