[cfe-commits] r148599 - in /cfe/trunk: lib/Analysis/ThreadSafety.cpp test/SemaCXX/warn-thread-safety-analysis.cpp

DeLesley Hutchins delesley at google.com
Fri Jan 20 15:24:42 PST 2012


Author: delesley
Date: Fri Jan 20 17:24:41 2012
New Revision: 148599

URL: http://llvm.org/viewvc/llvm-project?rev=148599&view=rev
Log:
Handle thread safety attributes on functions with separate definitions and declarations.

Modified:
    cfe/trunk/lib/Analysis/ThreadSafety.cpp
    cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp

Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=148599&r1=148598&r2=148599&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Fri Jan 20 17:24:41 2012
@@ -88,38 +88,46 @@
   /// Recursive function that terminates on DeclRefExpr.
   /// Note: this function merely creates a MutexID; it does not check to
   /// ensure that the original expression is a valid mutex expression.
-  void buildMutexID(Expr *Exp, Expr *Parent, int NumArgs,
-                    const NamedDecl **FunArgDecls, Expr **FunArgs) {
+  void buildMutexID(Expr *Exp, const NamedDecl *D, Expr *Parent,
+                    unsigned NumArgs, Expr **FunArgs) {
     if (!Exp) {
       DeclSeq.clear();
       return;
     }
 
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
-      if (FunArgDecls) {
-        // Substitute call arguments for references to function parameters
-        for (int i = 0; i < NumArgs; ++i) {
-          if (DRE->getDecl() == FunArgDecls[i]) {
-            buildMutexID(FunArgs[i], 0, 0, 0, 0);
-            return;
-          }
+      NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
+      ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(ND);
+      if (PV) {
+        FunctionDecl *FD =
+          cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
+        unsigned i = PV->getFunctionScopeIndex();
+
+        if (FunArgs && FD == D->getCanonicalDecl()) {
+          // Substitute call arguments for references to function parameters
+          assert(i < NumArgs);
+          buildMutexID(FunArgs[i], D, 0, 0, 0);
+          return;
         }
+        // Map the param back to the param of the original function declaration.
+        DeclSeq.push_back(FD->getParamDecl(i));
+        return;
       }
-      NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
+      // Not a function parameter -- just store the reference.
       DeclSeq.push_back(ND);
     } else if (MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
       NamedDecl *ND = ME->getMemberDecl();
       DeclSeq.push_back(ND);
-      buildMutexID(ME->getBase(), Parent, NumArgs, FunArgDecls, FunArgs);
+      buildMutexID(ME->getBase(), D, Parent, NumArgs, FunArgs);
     } else if (isa<CXXThisExpr>(Exp)) {
       if (Parent)
-        buildMutexID(Parent, 0, 0, 0, 0);
+        buildMutexID(Parent, D, 0, 0, 0);
       else
         return;  // mutexID is still valid in this case
     } else if (UnaryOperator *UOE = dyn_cast<UnaryOperator>(Exp))
-      buildMutexID(UOE->getSubExpr(), Parent, NumArgs, FunArgDecls, FunArgs);
+      buildMutexID(UOE->getSubExpr(), D, Parent, NumArgs, FunArgs);
     else if (CastExpr *CE = dyn_cast<CastExpr>(Exp))
-      buildMutexID(CE->getSubExpr(), Parent, NumArgs, FunArgDecls, FunArgs);
+      buildMutexID(CE->getSubExpr(), D, Parent, NumArgs, FunArgs);
     else
       DeclSeq.clear(); // Mark as invalid lock expression.
   }
@@ -133,11 +141,10 @@
     Expr *Parent = 0;
     unsigned NumArgs = 0;
     Expr **FunArgs = 0;
-    SmallVector<const NamedDecl*, 8> FunArgDecls;
 
     // If we are processing a raw attribute expression, with no substitutions.
     if (DeclExp == 0) {
-      buildMutexID(MutexExp, 0, 0, 0, 0);
+      buildMutexID(MutexExp, D, 0, 0, 0);
       return;
     }
 
@@ -163,17 +170,11 @@
 
     // If the attribute has no arguments, then assume the argument is "this".
     if (MutexExp == 0) {
-      buildMutexID(Parent, 0, 0, 0, 0);
+      buildMutexID(Parent, D, 0, 0, 0);
       return;
     }
 
-    // FIXME: handle default arguments
-    if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
-      for (unsigned i = 0, ni = FD->getNumParams(); i < ni && i < NumArgs; ++i) {
-        FunArgDecls.push_back(FD->getParamDecl(i));
-      }
-    }
-    buildMutexID(MutexExp, Parent, NumArgs, &FunArgDecls.front(), FunArgs);
+    buildMutexID(MutexExp, D, Parent, NumArgs, FunArgs);
   }
 
 public:

Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=148599&r1=148598&r2=148599&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Fri Jan 20 17:24:41 2012
@@ -1875,3 +1875,29 @@
 };  // end namespace TestTemplateAttributeInstantiation
 
 
+namespace FunctionDeclDefTest {
+
+class Foo {
+public:
+  Mutex mu_;
+  int a GUARDED_BY(mu_);
+
+  virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
+};
+
+// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
+void Foo::foo1(Foo *f_defined) {
+  f_defined->a = 0;
+};
+
+void test() {
+  Foo myfoo;
+  myfoo.foo1(&myfoo);  // \
+    // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
+  myfoo.mu_.Lock();
+  myfoo.foo1(&myfoo);
+  myfoo.mu_.Unlock();
+}
+
+};
+





More information about the cfe-commits mailing list