tbaeder updated this revision to Diff 530175.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D152504/new/
https://reviews.llvm.org/D152504
Files:
clang/lib/Analysis/CFG.cpp
clang/test/Sema/warn-thread-safety-analysis.c
Index: clang/test/Sema/warn-thread-safety-analysis.c
===================================================================
--- clang/test/Sema/warn-thread-safety-analysis.c
+++ clang/test/Sema/warn-thread-safety-analysis.c
@@ -22,6 +22,7 @@
#define SHARED_LOCKS_REQUIRED(...) \
__attribute__ ((shared_locks_required(__VA_ARGS__)))
#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
+#define CLEANUP(A) __attribute__ ((cleanup(A)))
// Define the mutex struct.
// Simplified only for test purpose.
@@ -72,6 +73,11 @@
return *p;
}
+void cleanup_int(int *unused) __attribute__((release_capability(mu1))) {
+ (void)unused;
+ mutex_exclusive_unlock(&mu1);
+}
+
int main(void) {
Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \
@@ -127,6 +133,15 @@
// expected-note@-1{{mutex released here}}
mutex_shared_unlock(&mu1); // expected-warning {{releasing mutex 'mu1' that was not held}}
+
+ {
+ mutex_exclusive_lock(&mu1);
+ int CLEANUP(cleanup_int) i;
+
+ Bar_fun1(3);
+ }
+ Bar_fun1(4); // expected-warning {{calling function 'Bar_fun1' requires holding mutex 'mu1' exclusively}}
+
return 0;
}
Index: clang/lib/Analysis/CFG.cpp
===================================================================
--- clang/lib/Analysis/CFG.cpp
+++ clang/lib/Analysis/CFG.cpp
@@ -1907,7 +1907,8 @@
Decls.push_back(*I);
for (VarDecl *VD : llvm::reverse(Decls)) {
- if (hasTrivialDestructor(VD)) {
+ bool HasCleanupAttr = VD->hasAttr<CleanupAttr>();
+ if (hasTrivialDestructor(VD) && !HasCleanupAttr) {
// If AddScopes is enabled and *I is a first variable in a scope, add a
// ScopeEnd marker in a Block.
if (BuildOpts.AddScopes && DeclsWithEndedScope.count(VD)) {
@@ -1925,7 +1926,8 @@
}
Ty = Context->getBaseElementType(Ty);
- if (Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
+ bool IsCXXRecordType = Ty->getAsCXXRecordDecl() != nullptr;
+ if (IsCXXRecordType && Ty->getAsCXXRecordDecl()->isAnyDestructorNoReturn())
Block = createNoReturnBlock();
else
autoCreateBlock();
@@ -1933,7 +1935,27 @@
// Add ScopeEnd just after automatic obj destructor.
if (BuildOpts.AddScopes && DeclsWithEndedScope.count(VD))
appendScopeEnd(Block, VD, S);
- appendAutomaticObjDtor(Block, VD, S);
+
+ if (HasCleanupAttr) {
+ // Create a fake CallExpr for the cleanup function.
+ const CleanupAttr *CA = VD->getAttr<CleanupAttr>();
+ FunctionDecl *FD = CA->getFunctionDecl();
+ SourceLocation Loc = VD->getLocation();
+ assert(FD);
+ auto *InstanceRef = DeclRefExpr::Create(*Context, {}, {}, VD, false, Loc,
+ VD->getType(), VK_PRValue);
+
+ auto *FuncRef = DeclRefExpr::Create(*Context, {}, {}, FD, false, Loc,
+ FD->getType(), VK_LValue);
+
+ SmallVector<Expr *> Args{InstanceRef};
+ auto *CE = CallExpr::Create(*Context, FuncRef, Args, FD->getType(),
+ VK_PRValue, Loc, FPOptionsOverride());
+ appendCall(Block, CE);
+ }
+
+ if (IsCXXRecordType)
+ appendAutomaticObjDtor(Block, VD, S);
}
}
@@ -2090,7 +2112,8 @@
return Scope;
if (BuildOpts.AddImplicitDtors) {
- if (!hasTrivialDestructor(VD) || BuildOpts.AddScopes) {
+ if (!hasTrivialDestructor(VD) || VD->hasAttr<CleanupAttr>() ||
+ BuildOpts.AddScopes) {
// Add the variable to scope
Scope = createOrReuseLocalScope(Scope);
Scope->addVar(VD);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits