]> granicus.if.org Git - clang/commitdiff
Thread Safety: also look at ObjC methods
authorJF Bastien <jfbastien@apple.com>
Mon, 25 Mar 2019 20:06:32 +0000 (20:06 +0000)
committerJF Bastien <jfbastien@apple.com>
Mon, 25 Mar 2019 20:06:32 +0000 (20:06 +0000)
Summary:
SExprBuilder::translateDeclRefExpr was only looking at FunctionDecl and not also looking at ObjCMethodDecl. It should consider both because the attributes can be used on Objective-C as well.

<rdar://problem/48941331>

Reviewers: dexonsmith, erik.pilkington

Subscribers: jkorous, jdoerfert, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D59523

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356940 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ThreadSafetyCommon.cpp
test/SemaObjCXX/no-crash-thread-safety-analysis.mm [new file with mode: 0644]
test/SemaObjCXX/thread-safety-analysis.h [new file with mode: 0644]
test/SemaObjCXX/warn-thread-safety-analysis.mm

index e687d96455cde326e569db3c021500c54f44f78e..373dfc77fa9b90eb4266227f470742757da892ec 100644 (file)
@@ -276,18 +276,23 @@ til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
 
   // Function parameters require substitution and/or renaming.
   if (const auto *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
-    const auto *FD =
-        cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
     unsigned I = PV->getFunctionScopeIndex();
-
-    if (Ctx && Ctx->FunArgs && FD == Ctx->AttrDecl->getCanonicalDecl()) {
-      // Substitute call arguments for references to function parameters
-      assert(I < Ctx->NumArgs);
-      return translate(Ctx->FunArgs[I], Ctx->Prev);
+    const DeclContext *D = PV->getDeclContext();
+    if (Ctx && Ctx->FunArgs) {
+      const Decl *Canonical = Ctx->AttrDecl->getCanonicalDecl();
+      if (isa<FunctionDecl>(D)
+              ? (cast<FunctionDecl>(D)->getCanonicalDecl() == Canonical)
+              : (cast<ObjCMethodDecl>(D)->getCanonicalDecl() == Canonical)) {
+        // Substitute call arguments for references to function parameters
+        assert(I < Ctx->NumArgs);
+        return translate(Ctx->FunArgs[I], Ctx->Prev);
+      }
     }
     // Map the param back to the param of the original function declaration
     // for consistent comparisons.
-    VD = FD->getParamDecl(I);
+    VD = isa<FunctionDecl>(D)
+             ? cast<FunctionDecl>(D)->getCanonicalDecl()->getParamDecl(I)
+             : cast<ObjCMethodDecl>(D)->getCanonicalDecl()->getParamDecl(I);
   }
 
   // For non-local variables, treat it as a reference to a named object.
diff --git a/test/SemaObjCXX/no-crash-thread-safety-analysis.mm b/test/SemaObjCXX/no-crash-thread-safety-analysis.mm
new file mode 100644 (file)
index 0000000..6abd391
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -Wthread-safety -Wno-objc-root-class %s
+
+// Thread safety analysis used to crash when used with ObjC methods.
+
+#include "thread-safety-analysis.h"
+
+@interface MyInterface
+- (void)doIt:(class Lock *)myLock;
+@end
+
+@implementation MyInterface
+- (void)doIt:(class Lock *)myLock {
+  AutoLock lock(*myLock);
+}
+@end
diff --git a/test/SemaObjCXX/thread-safety-analysis.h b/test/SemaObjCXX/thread-safety-analysis.h
new file mode 100644 (file)
index 0000000..f657b7e
--- /dev/null
@@ -0,0 +1,17 @@
+class __attribute__((lockable)) Lock {
+public:
+  void Acquire() __attribute__((exclusive_lock_function())) {}
+  void Release() __attribute__((unlock_function())) {}
+};
+
+class __attribute__((scoped_lockable)) AutoLock {
+public:
+  AutoLock(Lock &lock) __attribute__((exclusive_lock_function(lock)))
+  : lock_(lock) {
+    lock.Acquire();
+  }
+  ~AutoLock() __attribute__((unlock_function())) { lock_.Release(); }
+
+private:
+  Lock &lock_;
+};
index 262ab7d108a2944cf6d74307f3b1b75a6c1014c1..a50c6f2ee131ce6d96c7f54eb101875112b6f726 100644 (file)
@@ -1,22 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -Wno-objc-root-class %s
 
-class __attribute__((lockable)) Lock {
-public:
-  void Acquire() __attribute__((exclusive_lock_function())) {}
-  void Release() __attribute__((unlock_function())) {}
-};
-
-class __attribute__((scoped_lockable)) AutoLock {
-public:
-  AutoLock(Lock &lock) __attribute__((exclusive_lock_function(lock)))
-  : lock_(lock) {
-    lock.Acquire();
-  }
-  ~AutoLock() __attribute__((unlock_function())) { lock_.Release(); }
-
-private:
-  Lock &lock_;
-};
+#include "thread-safety-analysis.h"
 
 @interface MyInterface {
 @private