Re: [PATCH] D102026: Thread safety analysis: Allow exlusive/shared joins for managed and asserted capabilities
> - The `assert_capability` attribute is also a bit of a backdoor. Instead > of statically propagating through the code that a mutex is held, we can > just get that fact "out of thin air". > Assert_capability is not a back door. It is supposed to be used only on a function which does a run-time check: if (!mu_.is_locked()) fail(). This sort of thing is very common in static analysis. There are places in the code where you cannot statically prove that a property holds at compile-time, so you insert a run-time check into the code, and then propagate that property to the static analysis on the branch where the check succeeds. Of course, you can use assert_capability to create a back door, by putting it on a function that doesn't actually check anything, just like you can declare random methods to be lock_functions, even if they don't lock anything. :-) -DeLesley -- DeLesley Hutchins | Software Engineer | deles...@google.com | 505-206-0315 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r248803 - Thread Safety Analysis: fix before/after checks so that they work on global
Author: delesley Date: Tue Sep 29 10:25:51 2015 New Revision: 248803 URL: http://llvm.org/viewvc/llvm-project?rev=248803&view=rev Log: Thread Safety Analysis: fix before/after checks so that they work on global variables as well member variables. Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp cfe/trunk/test/Sema/warn-thread-safety-analysis.c cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h?rev=248803&r1=248802&r2=248803&view=diff == --- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h (original) +++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h Tue Sep 29 10:25:51 2015 @@ -291,6 +291,8 @@ public: return nullptr; if (auto *P = dyn_cast(CapExpr)) return P->clangDecl(); +if (auto *P = dyn_cast(CapExpr)) + return P->clangDecl(); return nullptr; } Modified: cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp?rev=248803&r1=248802&r2=248803&view=diff == --- cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp (original) +++ cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp Tue Sep 29 10:25:51 2015 @@ -290,7 +290,7 @@ til::SExpr *SExprBuilder::translateDeclR VD = FD->getParamDecl(I); } - // For non-local variables, treat it as a referenced to a named object. + // For non-local variables, treat it as a reference to a named object. return new (Arena) til::LiteralPtr(VD); } Modified: cfe/trunk/test/Sema/warn-thread-safety-analysis.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-thread-safety-analysis.c?rev=248803&r1=248802&r2=248803&view=diff == --- cfe/trunk/test/Sema/warn-thread-safety-analysis.c (original) +++ cfe/trunk/test/Sema/warn-thread-safety-analysis.c Tue Sep 29 10:25:51 2015 @@ -81,7 +81,8 @@ int main() { mutex_shared_lock(&mu2); Foo_fun1(1); - mutex_shared_lock(&mu1); // expected-warning{{acquiring mutex 'mu1' that is already held}} + mutex_shared_lock(&mu1); // expected-warning{{acquiring mutex 'mu1' that is already held}} \ + expected-warning{{mutex 'mu1' must be acquired before 'mu2'}} mutex_unlock(&mu1); mutex_unlock(&mu2); mutex_shared_lock(&mu1); Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=248803&r1=248802&r2=248803&view=diff == --- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Tue Sep 29 10:25:51 2015 @@ -5145,4 +5145,17 @@ void test() { } // end namespace TestReferenceNoThreadSafetyAnalysis +namespace GlobalAcquiredBeforeAfterTest { + +Mutex mu1; +Mutex mu2 ACQUIRED_AFTER(mu1); + +void test3() { + mu2.Lock(); + mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}} + mu1.Unlock(); + mu2.Unlock(); +} + +} // end namespace GlobalAcquiredBeforeAfterTest ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r248805 - Thread Safety Analysis: allow capability attribute on unions.
Author: delesley Date: Tue Sep 29 11:24:18 2015 New Revision: 248805 URL: http://llvm.org/viewvc/llvm-project?rev=248805&view=rev Log: Thread Safety Analysis: allow capability attribute on unions. Modified: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/test/Sema/attr-capabilities.c cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Modified: cfe/trunk/include/clang/Basic/Attr.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=248805&r1=248804&r2=248805&view=diff == --- cfe/trunk/include/clang/Basic/Attr.td (original) +++ cfe/trunk/include/clang/Basic/Attr.td Tue Sep 29 11:24:18 2015 @@ -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">, Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=248805&r1=248804&r2=248805&view=diff == --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Sep 29 11:24:18 2015 @@ -628,13 +628,10 @@ static bool checkAcquireOrderAttrCommon( // Check that this attribute only applies to lockable types. QualType QT = cast(D)->getType(); - if (!QT->isDependentType()) { -const RecordType *RT = getRecordType(QT); -if (!RT || !RT->getDecl()->hasAttr()) { - 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. Modified: cfe/trunk/test/Sema/attr-capabilities.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-capabilities.c?rev=248805&r1=248804&r2=248805&view=diff == --- cfe/trunk/test/Sema/attr-capabilities.c (original) +++ cfe/trunk/test/Sema/attr-capabilities.c Tue Sep 29 11:24:18 2015 @@ -4,11 +4,15 @@ typedef int __attribute__((capability("r 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}} Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=248805&r1=248804&r2=248805&view=diff == --- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Tue Sep 29 11:24:18 2015 @@ -5159,3 +5159,26 @@ void test3() { } // end namespace GlobalAcquiredBeforeAfterTest + +namespace LockableUnions { + +union LOCKABLE MutexUnion { + int a; + char* b; + + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void
Re: [PATCH] D12144: Fix 4 typos in lib/Analysis/
delesley added a comment. Looks good for the thread safety stuff. http://reviews.llvm.org/D12144 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r246806 - Thread safety analysis: the NO_THREAD_SAFETY_ANALYSIS attribute will now
Author: delesley Date: Thu Sep 3 16:14:22 2015 New Revision: 246806 URL: http://llvm.org/viewvc/llvm-project?rev=246806&view=rev Log: Thread safety analysis: the NO_THREAD_SAFETY_ANALYSIS attribute will now disable checking of arguments to the function, which is done by -Wthread-safety-reference. Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=246806&r1=246805&r2=246806&view=diff == --- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original) +++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Thu Sep 3 16:14:22 2015 @@ -1926,34 +1926,42 @@ void BuildLockset::VisitCallExpr(CallExp } } - if (ExamineArgs) { if (FunctionDecl *FD = Exp->getDirectCallee()) { - unsigned Fn = FD->getNumParams(); - unsigned Cn = Exp->getNumArgs(); - unsigned Skip = 0; - unsigned i = 0; - if (OperatorFun) { -if (isa(FD)) { - // First arg in operator call is implicit self argument, - // and doesn't appear in the FunctionDecl. - Skip = 1; - Cn--; -} else { - // Ignore the first argument of operators; it's been checked above. - i = 1; + // NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it + // only turns off checking within the body of a function, but we also + // use it to turn off checking in arguments to the function. This + // could result in some false negatives, but the alternative is to + // create yet another attribute. + // + if (!FD->hasAttr()) { +unsigned Fn = FD->getNumParams(); +unsigned Cn = Exp->getNumArgs(); +unsigned Skip = 0; + +unsigned i = 0; +if (OperatorFun) { + if (isa(FD)) { +// First arg in operator call is implicit self argument, +// and doesn't appear in the FunctionDecl. +Skip = 1; +Cn--; + } else { +// Ignore the first argument of operators; it's been checked above. +i = 1; + } } - } - // Ignore default arguments - unsigned n = (Fn < Cn) ? Fn : Cn; +// Ignore default arguments +unsigned n = (Fn < Cn) ? Fn : Cn; - for (; i < n; ++i) { -ParmVarDecl* Pvd = FD->getParamDecl(i); -Expr* Arg = Exp->getArg(i+Skip); -QualType Qt = Pvd->getType(); -if (Qt->isReferenceType()) - checkAccess(Arg, AK_Read, POK_PassByRef); +for (; i < n; ++i) { + ParmVarDecl* Pvd = FD->getParamDecl(i); + Expr* Arg = Exp->getArg(i+Skip); + QualType Qt = Pvd->getType(); + if (Qt->isReferenceType()) +checkAccess(Arg, AK_Read, POK_PassByRef); +} } } } Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=246806&r1=246805&r2=246806&view=diff == --- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Thu Sep 3 16:14:22 2015 @@ -5091,3 +5091,58 @@ class Foo { } // end namespace ScopedAdoptTest + +namespace TestReferenceNoThreadSafetyAnalysis { + +#define TS_UNCHECKED_READ(x) ts_unchecked_read(x) + +// Takes a reference to a guarded data member, and returns an unguarded +// reference. +template +inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS { + return v; +} + +template +inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS { + return v; +} + + +class Foo { +public: + Foo(): a(0) { } + + int a; +}; + + +class Bar { +public: + Bar() : a(0) { } + + Mutex mu; + int a GUARDED_BY(mu); + Foo foo GUARDED_BY(mu); +}; + + +void test() { + Bar bar; + const Bar cbar; + + int a = TS_UNCHECKED_READ(bar.a); // nowarn + TS_UNCHECKED_READ(bar.a) = 1; // nowarn + + int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn + TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn + + int c = TS_UNCHECKED_READ(cbar.a); // nowarn +} + +#undef TS_UNCHECKED_READ + +} // end namespace TestReferenceNoThreadSafetyAnalysis + + + ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits