summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-03-20 16:02:49 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-03-20 16:02:49 +0000
commit18d85aed3974564dc636b2fba6215ade85a00370 (patch)
tree0897aa1798f0fbee51ca45fd5c0f90001266357b /clang
parent202113ff5bee7c893fa6b338db6abfedc0d5ff6f (diff)
downloadbcm5719-llvm-18d85aed3974564dc636b2fba6215ade85a00370.tar.gz
bcm5719-llvm-18d85aed3974564dc636b2fba6215ade85a00370.zip
Replacing the exclusive_lock_function, shared_lock_function and unlock_function attributes with the acquire_capability and release_capability attributes. The old spellings will continue to work, but the underlying semantic attributes have been replaced.
Downgraded the capability diagnostics from error to warning to match the desired behavior, and updated the existing test cases. llvm-svn: 204350
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