Reland "Thread Safety Analysis: fix assert_capability."
Delete the test that was broken by rL309725, and add it back in a follow up commit. Also, improve the tests a bit. Reviewers: delesley, aaron.ballman Differential Revision: https://reviews.llvm.org/D36237 llvm-svn: 310402
This commit is contained in:
parent
f1a425edb7
commit
ec1369ed6e
|
@ -2138,7 +2138,7 @@ def AssertCapability : InheritableAttr {
|
||||||
let TemplateDependent = 1;
|
let TemplateDependent = 1;
|
||||||
let ParseArgumentsAsUnevaluated = 1;
|
let ParseArgumentsAsUnevaluated = 1;
|
||||||
let DuplicatesAllowedWhileMerging = 1;
|
let DuplicatesAllowedWhileMerging = 1;
|
||||||
let Args = [ExprArgument<"Expr">];
|
let Args = [VariadicExprArgument<"Args">];
|
||||||
let Accessors = [Accessor<"isShared",
|
let Accessors = [Accessor<"isShared",
|
||||||
[GNU<"assert_shared_capability">,
|
[GNU<"assert_shared_capability">,
|
||||||
CXX11<"clang", "assert_shared_capability">]>];
|
CXX11<"clang", "assert_shared_capability">]>];
|
||||||
|
|
|
@ -1735,8 +1735,23 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
|
||||||
CapExprSet AssertLocks;
|
CapExprSet AssertLocks;
|
||||||
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
|
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
|
||||||
for (const auto &AssertLock : AssertLocks)
|
for (const auto &AssertLock : AssertLocks)
|
||||||
Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>(
|
Analyzer->addLock(FSet,
|
||||||
AssertLock, LK_Shared, Loc, false, true),
|
llvm::make_unique<LockableFactEntry>(
|
||||||
|
AssertLock, LK_Shared, Loc, false, true),
|
||||||
|
ClassifyDiagnostic(A));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case attr::AssertCapability: {
|
||||||
|
AssertCapabilityAttr *A = cast<AssertCapabilityAttr>(At);
|
||||||
|
CapExprSet AssertLocks;
|
||||||
|
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
|
||||||
|
for (const auto &AssertLock : AssertLocks)
|
||||||
|
Analyzer->addLock(FSet,
|
||||||
|
llvm::make_unique<LockableFactEntry>(
|
||||||
|
AssertLock,
|
||||||
|
A->isShared() ? LK_Shared : LK_Exclusive, Loc,
|
||||||
|
false, true),
|
||||||
ClassifyDiagnostic(A));
|
ClassifyDiagnostic(A));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5700,8 +5700,12 @@ static void handleCapabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||||
|
|
||||||
static void handleAssertCapabilityAttr(Sema &S, Decl *D,
|
static void handleAssertCapabilityAttr(Sema &S, Decl *D,
|
||||||
const AttributeList &Attr) {
|
const AttributeList &Attr) {
|
||||||
|
SmallVector<Expr*, 1> Args;
|
||||||
|
if (!checkLockFunAttrCommon(S, D, Attr, Args))
|
||||||
|
return;
|
||||||
|
|
||||||
D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
|
D->addAttr(::new (S.Context) AssertCapabilityAttr(Attr.getRange(), S.Context,
|
||||||
Attr.getArgAsExpr(0),
|
Args.data(), Args.size(),
|
||||||
Attr.getAttributeSpellingListIndex()));
|
Attr.getAttributeSpellingListIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,6 @@ void Func6(void) __attribute__((requires_shared_capability(BadCapability))) {}
|
||||||
void Func7(void) __attribute__((assert_capability(GUI))) {}
|
void Func7(void) __attribute__((assert_capability(GUI))) {}
|
||||||
void Func8(void) __attribute__((assert_shared_capability(GUI))) {}
|
void Func8(void) __attribute__((assert_shared_capability(GUI))) {}
|
||||||
|
|
||||||
void Func9(void) __attribute__((assert_capability())) {} // expected-error {{'assert_capability' attribute takes one argument}}
|
|
||||||
void Func10(void) __attribute__((assert_shared_capability())) {} // expected-error {{'assert_shared_capability' attribute takes one argument}}
|
|
||||||
|
|
||||||
void Func11(void) __attribute__((acquire_capability(GUI))) {}
|
void Func11(void) __attribute__((acquire_capability(GUI))) {}
|
||||||
void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}
|
void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions %s
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 %s
|
||||||
|
|
||||||
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
|
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
|
||||||
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
|
// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
|
||||||
|
@ -13,8 +14,15 @@
|
||||||
#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
|
#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
|
||||||
#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
|
#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
|
||||||
#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
|
#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
|
||||||
|
|
||||||
|
#if USE_ASSERT_CAPABILITY
|
||||||
|
#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__)))
|
||||||
|
#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
|
||||||
|
#else
|
||||||
#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
|
#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
|
||||||
#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
|
#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
|
#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
|
||||||
#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
|
#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
|
||||||
#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
|
#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
|
||||||
|
@ -3675,9 +3683,14 @@ class Foo {
|
||||||
SHARED_TRYLOCK_FUNCTION(true, mu2_);
|
SHARED_TRYLOCK_FUNCTION(true, mu2_);
|
||||||
void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
|
void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
|
||||||
ASSERT_EXCLUSIVE_LOCK(mu2_);
|
ASSERT_EXCLUSIVE_LOCK(mu2_);
|
||||||
|
|
||||||
|
void alsoAssertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_, mu2_);
|
||||||
|
|
||||||
void assertShared() ASSERT_SHARED_LOCK(mu1_)
|
void assertShared() ASSERT_SHARED_LOCK(mu1_)
|
||||||
ASSERT_SHARED_LOCK(mu2_);
|
ASSERT_SHARED_LOCK(mu2_);
|
||||||
|
|
||||||
|
void alsoAssertShared() ASSERT_SHARED_LOCK(mu1_, mu2_);
|
||||||
|
|
||||||
void test();
|
void test();
|
||||||
void testAssert();
|
void testAssert();
|
||||||
void testAssertShared();
|
void testAssertShared();
|
||||||
|
@ -3741,17 +3754,33 @@ void Foo::test() {
|
||||||
|
|
||||||
// Force duplication of attributes
|
// Force duplication of attributes
|
||||||
void Foo::assertBoth() { }
|
void Foo::assertBoth() { }
|
||||||
|
void Foo::alsoAssertBoth() { }
|
||||||
void Foo::assertShared() { }
|
void Foo::assertShared() { }
|
||||||
|
void Foo::alsoAssertShared() { }
|
||||||
|
|
||||||
void Foo::testAssert() {
|
void Foo::testAssert() {
|
||||||
assertBoth();
|
{
|
||||||
a = 0;
|
assertBoth();
|
||||||
b = 0;
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
alsoAssertBoth();
|
||||||
|
a = 0;
|
||||||
|
b = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Foo::testAssertShared() {
|
void Foo::testAssertShared() {
|
||||||
assertShared();
|
{
|
||||||
int zz = a + b;
|
assertShared();
|
||||||
|
int zz = a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
alsoAssertShared();
|
||||||
|
int zz = a + b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue