summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/Attr.td49
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp38
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp73
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp8
-rw-r--r--clang/test/Sema/attr-capabilities.c11
5 files changed, 32 insertions, 147 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index f24d335df3f..c567cf29ebe 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1335,9 +1335,10 @@ def AcquireCapability : InheritableAttr {
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;
@@ -1345,7 +1346,8 @@ def AcquireCapability : InheritableAttr {
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];
}
@@ -1373,9 +1375,9 @@ def ReleaseCapability : InheritableAttr {
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;
@@ -1463,28 +1465,6 @@ def AcquiredBefore : InheritableAttr {
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">];
@@ -1533,17 +1513,6 @@ def SharedTrylockFunction : InheritableAttr {
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">];
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index 51f5e030691..cde19b531e0 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -1933,19 +1933,13 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
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;
}
@@ -1977,8 +1971,8 @@ void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
// 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;
}
@@ -2351,7 +2345,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
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)
@@ -2359,16 +2353,12 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
// 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;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 26d7ae96671..29aca3370dc 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -599,33 +599,6 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D,
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;
@@ -698,20 +671,6 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
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
@@ -3912,12 +3871,7 @@ static void handleAssertCapabilityAttr(Sema &S, Decl *D,
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(),
@@ -3942,19 +3896,13 @@ static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
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,
@@ -4417,9 +4365,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, 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;
@@ -4429,15 +4374,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
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;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index fc37727344c..5abaab8883a 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12597,19 +12597,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
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());
diff --git a/clang/test/Sema/attr-capabilities.c b/clang/test/Sema/attr-capabilities.c
index 6ce84dceabf..7a8cb35b0e3 100644
--- a/clang/test/Sema/attr-capabilities.c
+++ b/clang/test/Sema/attr-capabilities.c
@@ -9,9 +9,9 @@ struct __attribute__((capability("wrong"))) IncorrectName {}; // expected-warnin
int Test1 __attribute__((capability("test1"))); // expected-error {{'capability' attribute only applies to structs}}
int Test2 __attribute__((shared_capability("test2"))); // expected-error {{'shared_capability' attribute only applies to structs}}
-int Test3 __attribute__((acquire_capability("test3"))); // expected-error {{'acquire_capability' attribute only applies to functions}}
+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-error {{'release_capability' attribute only applies to functions}}
+int Test5 __attribute__((release_capability("test5"))); // expected-warning {{'release_capability' attribute only applies to functions}}
struct __attribute__((capability(12))) Test3 {}; // expected-error {{'capability' attribute requires a string}}
struct __attribute__((shared_capability(Test2))) Test4 {}; // expected-error {{'shared_capability' attribute requires a string}}
@@ -39,17 +39,10 @@ void Func10(void) __attribute__((assert_shared_capability())) {} // expected-err
void Func11(void) __attribute__((acquire_capability(GUI))) {}
void Func12(void) __attribute__((acquire_shared_capability(GUI))) {}
-void Func13(void) __attribute__((acquire_capability())) {} // expected-error {{'acquire_capability' attribute takes at least 1 argument}}
-void Func14(void) __attribute__((acquire_shared_capability())) {} // expected-error {{'acquire_shared_capability' attribute takes at least 1 argument}}
-
void Func15(void) __attribute__((release_capability(GUI))) {}
void Func16(void) __attribute__((release_shared_capability(GUI))) {}
void Func17(void) __attribute__((release_generic_capability(GUI))) {}
-void Func18(void) __attribute__((release_capability())) {} // expected-error {{'release_capability' attribute takes at least 1 argument}}
-void Func19(void) __attribute__((release_shared_capability())) {} // expected-error {{'release_shared_capability' attribute takes at least 1 argument}}
-void Func20(void) __attribute__((release_generic_capability())) {} // expected-error {{'release_generic_capability' attribute takes at least 1 argument}}
-
void Func21(void) __attribute__((try_acquire_capability(1))) {}
void Func22(void) __attribute__((try_acquire_shared_capability(1))) {}
OpenPOWER on IntegriCloud