let Spellings = [GNU<"acquire_capability">,
CXX11<"clang", "acquire_capability">,
GNU<"acquire_shared_capability">,
- CXX11<"clang", "acquire_shared_capability">];
- let Subjects = SubjectList<[Function, FunctionTemplate],
- ErrorDiag>;
+ CXX11<"clang", "acquire_shared_capability">,
+ GNU<"exclusive_lock_function">,
+ GNU<"shared_lock_function">];
+ let Subjects = SubjectList<[Function, FunctionTemplate]>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let Args = [VariadicExprArgument<"Args">];
let Accessors = [Accessor<"isShared",
[GNU<"acquire_shared_capability">,
- CXX11<"clang", "acquire_shared_capability">]>];
+ CXX11<"clang", "acquire_shared_capability">,
+ GNU<"shared_lock_function">]>];
let Documentation = [AcquireCapabilityDocs];
}
GNU<"release_shared_capability">,
CXX11<"clang", "release_shared_capability">,
GNU<"release_generic_capability">,
- CXX11<"clang", "release_generic_capability">];
- let Subjects = SubjectList<[Function, FunctionTemplate],
- ErrorDiag>;
+ CXX11<"clang", "release_generic_capability">,
+ GNU<"unlock_function">];
+ let Subjects = SubjectList<[Function, FunctionTemplate]>;
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let Documentation = [Undocumented];
}
-def ExclusiveLockFunction : InheritableAttr {
- let Spellings = [GNU<"exclusive_lock_function">];
- let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;
- let TemplateDependent = 1;
- let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
- let Documentation = [Undocumented];
-}
-
-def SharedLockFunction : InheritableAttr {
- let Spellings = [GNU<"shared_lock_function">];
- let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;
- let TemplateDependent = 1;
- let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
- let Documentation = [Undocumented];
-}
-
def AssertExclusiveLock : InheritableAttr {
let Spellings = [GNU<"assert_exclusive_lock">];
let Args = [VariadicExprArgument<"Args">];
let Documentation = [Undocumented];
}
-def UnlockFunction : InheritableAttr {
- let Spellings = [GNU<"unlock_function">];
- let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;
- let TemplateDependent = 1;
- let ParseArgumentsAsUnevaluated = 1;
- let DuplicatesAllowedWhileMerging = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
- let Documentation = [Undocumented];
-}
-
def LockReturned : InheritableAttr {
let Spellings = [GNU<"lock_returned">];
let Args = [ExprArgument<"Arg">];
for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
Attr *At = const_cast<Attr*>(ArgAttrs[i]);
switch (At->getKind()) {
- // When we encounter an exclusive lock function, we need to add the lock
- // to our lockset with kind exclusive.
- case attr::ExclusiveLockFunction: {
- ExclusiveLockFunctionAttr *A = cast<ExclusiveLockFunctionAttr>(At);
- Analyzer->getMutexIDs(ExclusiveLocksToAdd, A, Exp, D, VD);
- break;
- }
-
- // When we encounter a shared lock function, we need to add the lock
- // to our lockset with kind shared.
- case attr::SharedLockFunction: {
- SharedLockFunctionAttr *A = cast<SharedLockFunctionAttr>(At);
- Analyzer->getMutexIDs(SharedLocksToAdd, A, Exp, D, VD);
+ // When we encounter a lock function, we need to add the lock to our
+ // lockset.
+ case attr::AcquireCapability: {
+ auto *A = cast<AcquireCapabilityAttr>(At);
+ Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd
+ : ExclusiveLocksToAdd,
+ A, Exp, D, VD);
break;
}
// When we encounter an unlock function, we need to remove unlocked
// mutexes from the lockset, and flag a warning if they are not there.
- case attr::UnlockFunction: {
- UnlockFunctionAttr *A = cast<UnlockFunctionAttr>(At);
+ case attr::ReleaseCapability: {
+ auto *A = cast<ReleaseCapabilityAttr>(At);
Analyzer->getMutexIDs(LocksToRemove, A, Exp, D, VD);
break;
}
if (RequiresCapabilityAttr *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
0, D);
- } else if (UnlockFunctionAttr *A = dyn_cast<UnlockFunctionAttr>(Attr)) {
+ } else if (auto *A = dyn_cast<ReleaseCapabilityAttr>(Attr)) {
// UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
// We must ignore such methods.
if (A->args_size() == 0)
// FIXME -- deal with exclusive vs. shared unlock functions?
getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
getMutexIDs(LocksReleased, A, (Expr*) 0, D);
- } else if (ExclusiveLockFunctionAttr *A
- = dyn_cast<ExclusiveLockFunctionAttr>(Attr)) {
- if (A->args_size() == 0)
- return;
- getMutexIDs(ExclusiveLocksAcquired, A, (Expr*) 0, D);
- } else if (SharedLockFunctionAttr *A
- = dyn_cast<SharedLockFunctionAttr>(Attr)) {
+ } else if (auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
if (A->args_size() == 0)
return;
- getMutexIDs(SharedLocksAcquired, A, (Expr*) 0, D);
+ getMutexIDs(A->isShared() ? SharedLocksAcquired
+ : ExclusiveLocksAcquired,
+ A, nullptr, D);
} else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
// Don't try to check trylock functions for now
return;
return true;
}
-static void handleSharedLockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
- return;
-
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context)
- SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
-static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkLockFunAttrCommon(S, D, Attr, Args))
- return;
-
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
- D->addAttr(::new (S.Context)
- ExclusiveLockFunctionAttr(Attr.getRange(), S.Context,
- StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleAssertSharedLockAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
SmallVector<Expr*, 1> Args;
Attr.getAttributeSpellingListIndex()));
}
-static void handleUnlockFunAttr(Sema &S, Decl *D,
- const AttributeList &Attr) {
- // zero or more arguments ok
- // check that all arguments are lockable objects
- SmallVector<Expr*, 1> Args;
- checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
- unsigned Size = Args.size();
- Expr **StartArg = Size == 0 ? 0 : &Args[0];
-
- D->addAttr(::new (S.Context)
- UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleLockReturnedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
// check that the argument is lockable object
static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
SmallVector<Expr*, 1> Args;
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
- return;
-
- // Check that all arguments are lockable objects.
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
- if (Args.empty())
+ if (!checkLockFunAttrCommon(S, D, Attr, Args))
return;
D->addAttr(::new (S.Context) AcquireCapabilityAttr(Attr.getRange(),
static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- SmallVector<Expr*, 1> Args;
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
- return;
-
// Check that all arguments are lockable objects.
- checkAttrArgsAreLockableObjs(S, D, Attr, Args);
- if (Args.empty())
- return;
+ SmallVector<Expr *, 1> Args;
+ checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, true);
- D->addAttr(::new (S.Context) ReleaseCapabilityAttr(Attr.getRange(),
- S.Context,
- Args.data(), Args.size(),
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context) ReleaseCapabilityAttr(
+ Attr.getRange(), S.Context, Args.data(), Args.size(),
+ Attr.getAttributeSpellingListIndex()));
}
static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
case AttributeList::AT_PtGuardedBy:
handlePtGuardedByAttr(S, D, Attr);
break;
- case AttributeList::AT_ExclusiveLockFunction:
- handleExclusiveLockFunctionAttr(S, D, Attr);
- break;
case AttributeList::AT_ExclusiveTrylockFunction:
handleExclusiveTrylockFunctionAttr(S, D, Attr);
break;
case AttributeList::AT_LocksExcluded:
handleLocksExcludedAttr(S, D, Attr);
break;
- case AttributeList::AT_SharedLockFunction:
- handleSharedLockFunctionAttr(S, D, Attr);
- break;
case AttributeList::AT_SharedTrylockFunction:
handleSharedTrylockFunctionAttr(S, D, Attr);
break;
- case AttributeList::AT_UnlockFunction:
- handleUnlockFunAttr(S, D, Attr);
- break;
case AttributeList::AT_AcquiredBefore:
handleAcquiredBeforeAttr(S, D, Attr);
break;
Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
- else if (const auto *ELF = dyn_cast<ExclusiveLockFunctionAttr>(A))
- Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
- else if (const auto *SLF = dyn_cast<SharedLockFunctionAttr>(A))
- Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
Arg = ETLF->getSuccessValue();
Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
} else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
Arg = STLF->getSuccessValue();
Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
- } else if (const auto *UF = dyn_cast<UnlockFunctionAttr>(A))
- Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
- else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
+ } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
Arg = LR->getArg();
else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
\r
int Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs}}\r
int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs}}\r
-int Test3 __attribute__((acquire_capability("test3"))); // expected-error {{'acquire_capability' attribute only applies to functions}}\r
+int Test3 __attribute__((acquire_capability("test3"))); // expected-warning {{'acquire_capability' attribute only applies to functions}}\r
int Test4 __attribute__((try_acquire_capability("test4"))); // expected-error {{'try_acquire_capability' attribute only applies to functions}}\r
-int Test5 __attribute__((release_capability("test5"))); // expected-error {{'release_capability' attribute only applies to functions}}\r
+int Test5 __attribute__((release_capability("test5"))); // expected-warning {{'release_capability' attribute only applies to functions}}\r
\r
struct __attribute__((capability(12))) Test3 {}; // expected-error {{'capability' attribute requires a string}}\r
struct __attribute__((shared_capability(Test2))) Test4 {}; // expected-error {{'shared_capability' attribute requires a string}}\r
void Func11(void) __attribute__((acquire_capability(GUI))) {}\r
void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}\r
\r
-void Func13(void) __attribute__((acquire_capability())) {} // expected-error {{'acquire_capability' attribute takes at least 1 argument}}\r
-void Func14(void) __attribute__((acquire_shared_capability())) {} // expected-error {{'acquire_shared_capability' attribute takes at least 1 argument}}\r
-\r
void Func15(void) __attribute__((release_capability(GUI))) {}\r
void Func16(void) __attribute__((release_shared_capability(GUI))) {}\r
void Func17(void) __attribute__((release_generic_capability(GUI))) {}\r
\r
-void Func18(void) __attribute__((release_capability())) {} // expected-error {{'release_capability' attribute takes at least 1 argument}}\r
-void Func19(void) __attribute__((release_shared_capability())) {} // expected-error {{'release_shared_capability' attribute takes at least 1 argument}}\r
-void Func20(void) __attribute__((release_generic_capability())) {} // expected-error {{'release_generic_capability' attribute takes at least 1 argument}}\r
-\r
void Func21(void) __attribute__((try_acquire_capability(1))) {}\r
void Func22(void) __attribute__((try_acquire_shared_capability(1))) {}\r
\r