diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 0bb64e8dd2dc6c8bc70fb9aae8ef1a394925e92a..5003d9cad86c28efa6bb8270dc3eb05e551745bb 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -1164,12 +1164,12 @@ specify that the pointer must be dereferenced while holding some lock.</p>
 <h4 id="ts_guardedby">guarded_by(l)</h4>
 
 <p>Use <tt>__attribute__((guarded_by(l)))</tt> on a variable declaration to 
-specify that the variable must be accessed while holding lock l.</p>
+specify that the variable must be accessed while holding lock <tt>l</tt>.</p>
 
 <h4 id="ts_ptguardedby">pt_guarded_by(l)</h4>
 
 <p>Use <tt>__attribute__((pt_guarded_by(l)))</tt> on a pointer declaration to 
-specify that the pointer must be dereferenced while holding lock l.</p>
+specify that the pointer must be dereferenced while holding lock <tt>l</tt>.</p>
 
 <h4 id="ts_acquiredbefore">acquired_before(...)</h4>
 
@@ -1189,67 +1189,62 @@ least one argument.</p>
 
 <p>Use <tt>__attribute__((exclusive_lock_function(...)))</tt> on a function 
 declaration to specify that the function acquires all listed locks 
-exclusively. This attribute takes zero or more 
-arguments: either of lockable type or integers indexing into 
-function parameters of lockable type. If no arguments are given, the acquired 
-lock is implicitly <tt>this</tt> of the enclosing object.</p>
+exclusively. This attribute takes zero or more arguments: either of lockable 
+type or integers indexing into function parameters of lockable type. If no 
+arguments are given, the acquired lock is implicitly <tt>this</tt> of the 
+enclosing object.</p>
 
 <h4 id="ts_slf">shared_lock_function(...)</h4>
 
 <p>Use <tt>__attribute__((shared_lock_function(...)))</tt> on a function 
 declaration to specify that the function acquires all listed locks, although
- the locks may be shared (e.g. read locks). 
-This attribute takes zero or more 
-arguments: either of lockable type or integers indexing into 
-function parameters of lockable type. If no arguments are given, the acquired 
-lock is implicitly <tt>this</tt> of the enclosing object.</p>
+ the locks may be shared (e.g. read locks). This attribute takes zero or more 
+arguments: either of lockable type or integers indexing into function 
+parameters of lockable type. If no arguments are given, the acquired lock is 
+implicitly <tt>this</tt> of the enclosing object.</p>
 
 <h4 id="ts_etf">exclusive_trylock_function(...)</h4>
 
 <p>Use <tt>__attribute__((exclusive_lock_function(...)))</tt> on a function 
 declaration to specify that the function will try (without blocking) to acquire
-all listed locks exclusively. This attribute takes one or more 
-arguments. The first argument is an integer or boolean value specifying the 
-return value of a successful lock acquisition. The remaining arugments are 
-either of lockable type or integers indexing into 
-function parameters of lockable type. If only one argument is given, the 
-acquired lock is implicitly <tt>this</tt> of the enclosing object.</p>
+all listed locks exclusively. This attribute takes one or more arguments. The 
+first argument is an integer or boolean value specifying the return value of a 
+successful lock acquisition. The remaining arugments are either of lockable type 
+or integers indexing into function parameters of lockable type. If only one 
+argument is given, the acquired lock is implicitly <tt>this</tt> of the 
+enclosing object.</p>
 
 <h4 id="ts_stf">shared_trylock_function(...)</h4>
 
 <p>Use <tt>__attribute__((shared_lock_function(...)))</tt> on a function 
 declaration to specify that the function will try (without blocking) to acquire
-all listed locks, although
- the locks may be shared (e.g. read locks). 
-This attribute takes one or more 
-arguments. The first argument is an integer or boolean value specifying the 
-return value of a successful lock acquisition. The remaining arugments are 
-either of lockable type or integers indexing into 
+all listed locks, although the locks may be shared (e.g. read locks). This 
+attribute takes one or more arguments. The first argument is an integer or 
+boolean value specifying the return value of a successful lock acquisition. The 
+remaining arugments are either of lockable type or integers indexing into 
 function parameters of lockable type. If only one argument is given, the 
 acquired lock is implicitly <tt>this</tt> of the enclosing object.</p>
 
 <h4 id="ts_uf">unlock_function(...)</h4>
 
 <p>Use <tt>__attribute__((unlock_function(...)))</tt> on a function 
-declaration to specify that the function release all listed locks.
- This attribute takes zero or more 
-arguments: either of lockable type or integers indexing into 
-function parameters of lockable type. If no arguments are given, the acquired 
-lock is implicitly <tt>this</tt> of the enclosing object.</p>
+declaration to specify that the function release all listed locks. This 
+attribute takes zero or more arguments: either of lockable type or integers 
+indexing into function parameters of lockable type. If no arguments are given, 
+the acquired lock is implicitly <tt>this</tt> of the enclosing object.</p>
 
 <h4 id="ts_lr">lock_returned(l)</h4>
 
 <p>Use <tt>__attribute__((lock_returned(l)))</tt> on a function 
-declaration to specify that the function returns lock l (l must be of lockable 
-type). This annotation is used
-to aid in resolving lock expressions.</p>
+declaration to specify that the function returns lock <tt>l</tt> (<tt>l</tt> 
+must be of lockable type). This annotation is used to aid in resolving lock 
+expressions.</p>
 
 <h4 id="ts_le">locks_excluded(...)</h4>
 
 <p>Use <tt>__attribute__((locks_excluded(...)))</tt> on a function declaration 
-to specify that the function must not be called with the listed locks. 
-Arguments must be lockable type, and there must be at 
-least one argument.</p>
+to specify that the function must not be called with the listed locks. Arguments 
+must be lockable type, and there must be at least one argument.</p>
 
 <h4 id="ts_elr">exclusive_locks_required(...)</h4>
 
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index a300764733725000c2518cdfa21c65a2a2b95660..7c5c217ce392dbd22804958b437896b0ecc4da58 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -274,6 +274,9 @@ def Most : DiagGroup<"most", [
     OverloadedVirtual
  ]>;
 
+// Thread Safety warnings 
+def : DiagGroup<"thread-safety">;
+
 // -Wall is -Wmost -Wparentheses
 def : DiagGroup<"all", [Most, Parentheses]>;
 
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 38db5b3ec683c8e2238c7216e69131ea1afbb6de..37409d090035ded8197db6dc08e5a6e38147c3c9 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1142,6 +1142,10 @@ def err_attribute_bad_neon_vector_size : Error<
   "Neon vector size must be 64 or 128 bits">;
 def err_attribute_argument_not_int : Error<
   "'%0' attribute requires integer constant">;
+def err_attribute_argument_not_class : Error<
+  "%0 attribute requires arguments that are class type or point to class type">;
+def err_attribute_first_argument_not_int_or_bool : Error<
+  "%0 attribute first argument must be of int or bool type">;
 def err_attribute_argument_outof_range : Error<
   "init_priority attribute requires integer constant between "
   "101 and 65535 inclusive">;
@@ -1300,6 +1304,21 @@ def warn_availability_version_ordering : Warning<
   "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version "
   "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; "
   "attribute ignored">;
+  
+// Thread Safety Attributes
+// Errors when parsing the attributes
+def err_attribute_argument_out_of_range : Error<
+  "%0 attribute parameter %1 is out of bounds: "
+  "%plural{0:no parameters to index into|"
+  "1:can only be 1, since there is one parameter|"
+  ":must be between 1 and %2}2">;
+def err_attribute_argument_not_lockable : Error<
+  "%0 attribute requires arguments whose type is annotated "
+  "with 'lockable' attribute">;
+def err_attribute_decl_not_lockable : Error<
+  "%0 attribute can only be applied in a context annotated "
+  "with 'lockable' attribute">;
+
 
 def warn_impcast_vector_scalar : Warning<
   "implicit conversion turns vector to scalar: %0 to %1">,
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index af3f40ec40bdaf9376d5d72eccc60770e815082e..fc5d11cb6a22b3bcee3490cd5b42a7b6633e9dc2 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1691,6 +1691,13 @@ bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
                                   ParsedAttributes &attrs,
                                   SourceLocation *endLoc);
 
+  bool IsThreadSafetyAttribute(llvm::StringRef AttrName);
+  void ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
+                                  SourceLocation AttrNameLoc,
+                                  ParsedAttributes &Attrs,
+                                  SourceLocation *EndLoc);
+
+
   void ParseTypeofSpecifier(DeclSpec &DS);
   void ParseDecltypeSpecifier(DeclSpec &DS);
   void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 1e318fe66e2aebc27f00913c69a2a6a8eee59569..2a95ecc7c7234d268e35f51f746056acc3cace43 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -19,6 +19,7 @@
 #include "clang/Sema/PrettyDeclStackTrace.h"
 #include "RAIIObjectsForParser.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringSwitch.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -121,6 +122,10 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
       // Availability attributes have their own grammar.
       if (AttrName->isStr("availability"))
         ParseAvailabilityAttribute(*AttrName, AttrNameLoc, attrs, endLoc);
+      // Thread safety attributes fit into the FIXME case above, so we
+      // just parse the arguments as a list of expressions
+      else if (IsThreadSafetyAttribute(AttrName->getName()))
+        ParseThreadSafetyAttribute(*AttrName, AttrNameLoc, attrs, endLoc);
       // check if we have a "parameterized" attribute
       else if (Tok.is(tok::l_paren)) {
         ConsumeParen(); // ignore the left paren loc for now
@@ -650,6 +655,81 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
                UnavailableLoc, false, false);
 }
 
+/// \brief Wrapper around a case statement checking if AttrName is
+/// one of the thread safety attributes
+bool Parser::IsThreadSafetyAttribute(llvm::StringRef AttrName){
+  return llvm::StringSwitch<bool>(AttrName)
+      .Case("guarded_by", true)
+      .Case("guarded_var", true)
+      .Case("pt_guarded_by", true)
+      .Case("pt_guarded_var", true)
+      .Case("lockable", true)
+      .Case("scoped_lockable", true)
+      .Case("no_thread_safety_analysis", true)
+      .Case("acquired_after", true)
+      .Case("acquired_before", true)
+      .Case("exclusive_lock_function", true)
+      .Case("shared_lock_function", true)
+      .Case("exclusive_trylock_function", true)
+      .Case("shared_trylock_function", true)
+      .Case("unlock_function", true)
+      .Case("lock_returned", true)
+      .Case("locks_excluded", true)
+      .Case("exclusive_locks_required", true)
+      .Case("shared_locks_required", true)
+      .Default(false);
+}
+
+/// \brief Parse the contents of thread safety attributes. These
+/// should always be parsed as an expression list.
+///
+/// We need to special case the parsing due to the fact that if the first token
+/// of the first argument is an identifier, the main parse loop will store
+/// that token as a "parameter" and the rest of
+/// the arguments will be added to a list of "arguments". However,
+/// subsequent tokens in the first argument are lost. We instead parse each
+/// argument as an expression and add all arguments to the list of "arguments".
+/// In future, we will take advantage of this special case to also
+/// deal with some argument scoping issues here (for example, referring to a
+/// function parameter in the attribute on that function).
+void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
+                                        SourceLocation AttrNameLoc,
+                                        ParsedAttributes &Attrs,
+                                        SourceLocation *EndLoc) {
+
+  if (Tok.is(tok::l_paren)) {
+    SourceLocation LeftParenLoc = Tok.getLocation();
+    ConsumeParen(); // ignore the left paren loc for now
+
+    ExprVector ArgExprs(Actions);
+    bool ArgExprsOk = true;
+
+    // now parse the list of expressions
+    while (1) {
+      ExprResult ArgExpr(ParseAssignmentExpression());
+      if (ArgExpr.isInvalid()) {
+        ArgExprsOk = false;
+        MatchRHSPunctuation(tok::r_paren, LeftParenLoc);
+        break;
+      } else {
+        ArgExprs.push_back(ArgExpr.release());
+      }
+      if (Tok.isNot(tok::comma))
+        break;
+      ConsumeToken(); // Eat the comma, move to the next argument
+    }
+    // Match the ')'.
+    if (ArgExprsOk && Tok.is(tok::r_paren)) {
+      ConsumeParen(); // ignore the right paren loc for now
+      Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
+                   ArgExprs.take(), ArgExprs.size());
+    }
+  } else {
+    Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc,
+                 0, SourceLocation(), 0, 0);
+  }
+}
+
 void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
   Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed)
     << attrs.Range;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 9fbd73f4b63b948137ba2f2e07fd5a8d3a21ea89..0644103b44e118996dcabbe4320b506be55a6847 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -15,6 +15,7 @@
 #include "TargetAttributesSema.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/SourceManager.h"
@@ -27,7 +28,7 @@ using namespace sema;
 
 /// These constants match the enumerated choices of
 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
-enum AttributeDeclType {
+enum AttributeDeclKind {
   ExpectedFunction,
   ExpectedUnion,
   ExpectedVariableOrFunction,
@@ -195,6 +196,8 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
   return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
 }
 
+/// \brief Check if the attribute has exactly as many args as Num. May
+/// output an error.
 static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
                                   unsigned int Num) {
   if (Attr.getNumArgs() != Num) {
@@ -205,31 +208,16 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,
   return true;
 }
 
-///
-/// \brief Check the total number of argumenation, whether parsed by clang
-/// as arguments or parameters. Outputs a warning.
-/// \return false if the number of argumenation units does not match expectation
-///
-static bool checkAttributeNumArgsPlusParams(Sema &S, const AttributeList &Attr,
-                                             unsigned int Num,
-                                             bool moreok = false) {
-  unsigned int numArgsPlusParams = 0;
-
-  if (Attr.getParameterName())
-    numArgsPlusParams++;
 
-  numArgsPlusParams += Attr.getNumArgs();
-
-  if (moreok && numArgsPlusParams < Num) {
+/// \brief Check if the attribute has at least as many args as Num. May
+/// output an error.
+static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr,
+                                  unsigned int Num) {
+  if (Attr.getNumArgs() < Num) {
     S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num;
     return false;
   }
 
-  if (!moreok && numArgsPlusParams != Num) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num;
-    return false;
-  }
-
   return true;
 }
 
@@ -246,6 +234,12 @@ static bool mayBeSharedVariable(const Decl *D) {
   return false;
 }
 
+/// \brief Check if the passed-in expression is of type int or bool.
+static bool isIntOrBool(Expr *Exp) {
+  QualType QT = Exp->getType();
+  return QT->isBooleanType() || QT->isIntegerType();
+}
+
 ///
 /// \brief Check if passed in Decl is a pointer type.
 /// Note that this function may produce an error message.
@@ -265,6 +259,71 @@ static bool checkIsPointer(Sema &S, const Decl *D, const AttributeList &Attr) {
   return false;
 }
 
+/// \brief Checks that the passed in QualType either is of RecordType or points
+/// to RecordType. Returns the relevant RecordType, null if it does not exit.
+const RecordType *getRecordType(QualType QT) {
+    const RecordType *RT = QT->getAs<RecordType>();
+    // now check if we point to record type
+    if(!RT && QT->isPointerType()){
+        QualType PT = QT->getAs<PointerType>()->getPointeeType();
+        RT = PT->getAs<RecordType>();
+    }
+    return RT;
+}
+
+/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting
+/// from Sidx, resolve to a lockable object. May flag an error.
+static bool checkAttrArgsAreLockableObjs(Sema & S, Decl *D,
+                                         const AttributeList & Attr,
+                                         int Sidx = 0,
+                                         bool ParamIdxOk = false) {
+  for(unsigned int Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
+    Expr *ArgExp = Attr.getArg(Idx);
+    if (ArgExp->isTypeDependent())
+      continue;
+
+    QualType Arg_QT = ArgExp->getType();
+
+    // Get record type.
+    // first see if we can just cast to record type, or point to record type
+    const RecordType *RT = getRecordType(Arg_QT);
+
+    // now check if we idx into a record type function param
+    if (!RT && ParamIdxOk) {
+      FunctionDecl *FD = dyn_cast <FunctionDecl>(D);
+      IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp);
+      if(FD && IL) {
+        unsigned int NumParams = FD->getNumParams();
+        llvm::APInt ArgValue = IL->getValue();
+        uint64_t ParamIdx_from1 = ArgValue.getZExtValue();
+        uint64_t ParamIdx_from0 = ParamIdx_from1 - 1;
+        if(!ArgValue.isStrictlyPositive() || ParamIdx_from1 > NumParams) {
+          S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range)
+            << Attr.getName() << Idx + 1 << NumParams;
+          return false;
+        }
+        Arg_QT = FD->getParamDecl(ParamIdx_from0)->getType();
+        RT = getRecordType(Arg_QT);
+      }
+    }
+
+    //  Flag error if could not get record type for this argument
+    if (!RT) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_class)
+        << Attr.getName();
+      return false;
+    }
+
+    // Flag error if the type is not lockable
+    if (!RT->getDecl()->getAttr<LockableAttr>()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_lockable)
+        << Attr.getName();
+      return false;
+    }
+  }
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 // Attribute Implementations
 //===----------------------------------------------------------------------===//
@@ -283,7 +342,7 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr,
   // D must be either a member field or global (potentially shared) variable.
   if (!mayBeSharedVariable(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-      << Attr.getName() << 15; /*fields and global vars*/;
+      << Attr.getName() << ExpectedFieldOrGlobalVar;
     return;
   }
 
@@ -297,22 +356,26 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr,
 }
 
 static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr,
-                                 bool pointer = false) {
+                                bool pointer = false) {
   assert(!Attr.isInvalid());
 
-  if (!checkAttributeNumArgsPlusParams(S, Attr, 1))
+  if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
   // D must be either a member field or global (potentially shared) variable.
   if (!mayBeSharedVariable(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-      << Attr.getName() << 15; /*fields and global vars*/;
+      << Attr.getName() << ExpectedFieldOrGlobalVar;
     return;
   }
 
   if (pointer && !checkIsPointer(S, D, Attr))
     return;
 
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr))
+    return;
+
   if (pointer)
     D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getLoc(), S.Context));
   else
@@ -346,7 +409,7 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D,
   if (!checkAttributeNumArgs(S, Attr, 0))
     return;
 
-  if (!isFunction(D)) {
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
@@ -360,16 +423,32 @@ static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr,
                                    bool before) {
   assert(!Attr.isInvalid());
 
-  if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true))
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
     return;
 
   // D must be either a member field or global (potentially shared) variable.
-  if (!mayBeSharedVariable(D)) {
+  ValueDecl *VD = dyn_cast<ValueDecl>(D);
+  if (!VD || !mayBeSharedVariable(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
-      << Attr.getName() << 15; /*fields and global vars*/;
+      << Attr.getName() << ExpectedFieldOrGlobalVar;
     return;
   }
 
+  // Check that this attribute only applies to lockable types
+  QualType QT = VD->getType();
+  if (!QT->isDependentType()) {
+    const RecordType *RT = getRecordType(QT);
+    if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_decl_not_lockable)
+              << Attr.getName();
+      return;
+    }
+  }
+
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr))
+    return;
+
   if (before)
     D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getLoc(), S.Context));
   else
@@ -377,17 +456,22 @@ static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr,
 }
 
 static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
-                                   bool exclusive = false) {
+                              bool exclusive = false) {
   assert(!Attr.isInvalid());
 
   // zero or more arguments ok
 
-  if (!isFunction(D)) {
+  // check that the attribute is applied to a function
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
   }
 
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, 0, /*ParamIdxOk=*/true))
+    return;
+
   if (exclusive)
     D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getLoc(),
                                                            S.Context));
@@ -397,93 +481,118 @@ static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
 }
 
 static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr,
-                                      bool exclusive = false) {
+                                 bool exclusive = false) {
   assert(!Attr.isInvalid());
 
-  if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true))
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
     return;
 
-  if (!isFunction(D)) {
+
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
   }
 
+  if (!isIntOrBool(Attr.getArg(0))) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool)
+        << Attr.getName();
+    return;
+  }
+
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, 1))
+    return;
+
   if (exclusive)
     D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getLoc(),
-                                                           S.Context));
+                                                              S.Context));
   else
     D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getLoc(),
-                                                        S.Context));
-
+                                                           S.Context));
 }
 
 static void handleLocksRequiredAttr(Sema &S, Decl *D, const AttributeList &Attr,
-                                   bool exclusive = false) {
+                                    bool exclusive = false) {
   assert(!Attr.isInvalid());
 
-  if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true))
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
     return;
 
-  if (!isFunction(D)) {
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
   }
 
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr))
+    return;
+
   if (exclusive)
     D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getLoc(),
-                                                           S.Context));
+                                                            S.Context));
   else
     D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getLoc(),
-                                                        S.Context));
+                                                         S.Context));
 }
 
-
 static void handleUnlockFunAttr(Sema &S, Decl *D,
-                                     const AttributeList &Attr) {
+                                const AttributeList &Attr) {
   assert(!Attr.isInvalid());
 
   // zero or more arguments ok
 
-  if (!isFunction(D)) {
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
   }
 
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr, 0, /*ParamIdxOk=*/true))
+    return;
+
   D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getLoc(), S.Context));
 }
 
 static void handleLockReturnedAttr(Sema &S, Decl *D,
-                                     const AttributeList &Attr) {
+                                   const AttributeList &Attr) {
   assert(!Attr.isInvalid());
 
-  if (!checkAttributeNumArgsPlusParams(S, Attr, 1))
+  if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
-  if (!isFunction(D)) {
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
   }
 
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr))
+    return;
+
   D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getLoc(), S.Context));
 }
 
 static void handleLocksExcludedAttr(Sema &S, Decl *D,
-                                     const AttributeList &Attr) {
+                                    const AttributeList &Attr) {
   assert(!Attr.isInvalid());
 
-  if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true))
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
     return;
 
-  if (!isFunction(D)) {
+  if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
       << Attr.getName() << ExpectedFunctionOrMethod;
     return;
   }
 
+  // check that all arguments are lockable objects
+  if (!checkAttrArgsAreLockableObjs(S, D, Attr))
+    return;
+
   D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getLoc(), S.Context));
 }
 
diff --git a/test/SemaCXX/warn-thread-safety.cpp b/test/SemaCXX/warn-thread-safety.cpp
index 4958d2ed0fa0205f6d31dcb75dd571fa312ba9b5..c5523e2a1315fc50ca04c2dcb672002a2adadc99 100644
--- a/test/SemaCXX/warn-thread-safety.cpp
+++ b/test/SemaCXX/warn-thread-safety.cpp
@@ -1,19 +1,48 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
 
 
-/**
- *  Helper fields
- */
+//-----------------------------------------//
+//  Helper fields
+//-----------------------------------------//
 
 class __attribute__((lockable)) Mu {
 };
 
+class UnlockableMu{
+};
+
+class MuWrapper {
+  public:
+  Mu mu;
+  Mu getMu() {
+    return mu;
+  }
+  Mu * getMuPointer() {
+    return &mu;
+  }
+};
+
+
+class MuDoubleWrapper {
+  public:
+  MuWrapper* muWrapper;
+  MuWrapper* getWrapper() {
+    return muWrapper;
+  }
+};
+
 Mu mu1;
+UnlockableMu umu;
 Mu mu2;
+MuWrapper muWrapper;
+MuDoubleWrapper muDoubleWrapper;
+Mu* muPointer;
+Mu ** muDoublePointer = & muPointer;
+Mu& muRef = mu1;
 
-/***********************************
- *  No Thread Safety Analysis (noanal)
- ***********************************/
+//-----------------------------------------//
+//   No Thread Safety Analysis (noanal)    //
+//-----------------------------------------//
 
 // FIXME: Right now we cannot parse attributes put on function definitions
 // We would like to patch this at some point.
@@ -53,9 +82,9 @@ void noanal_fun_params(int lvar __attribute__((no_thread_safety_analysis))); //
   expected-warning {{'no_thread_safety_analysis' attribute only applies to functions and methods}}
 
 
-/***********************************
- *  Guarded Var Attribute (gv)
- ***********************************/
+//-----------------------------------------//
+//  Guarded Var Attribute (gv)
+//-----------------------------------------//
 
 #if !__has_attribute(guarded_var)
 #error "Should support guarded_var attribute"
@@ -89,9 +118,9 @@ int gv_testfn(int y){
   return x;
 }
 
-/***********************************
- *  Pt Guarded Var Attribute (pgv)
- ***********************************/
+//-----------------------------------------//
+//   Pt Guarded Var Attribute (pgv)
+//-----------------------------------------//
 
 //FIXME: add support for boost::scoped_ptr<int> fancyptr  and references
 
@@ -133,9 +162,9 @@ void pgv_testfn(int y){
   delete x;
 }
 
-/***********************************
- *  Lockable Attribute (l)
- ***********************************/
+//-----------------------------------------//
+//  Lockable Attribute (l)
+//-----------------------------------------//
 
 //FIXME: In future we may want to add support for structs, ObjC classes, etc.
 
@@ -175,9 +204,9 @@ void l_function_params(int lvar __attribute__((lockable))); // \
   expected-warning {{'lockable' attribute only applies to classes}}
 
 
-/***********************************
- *  Scoped Lockable Attribute (sl)
- ***********************************/
+//-----------------------------------------//
+//  Scoped Lockable Attribute (sl)
+//-----------------------------------------//
 
 #if !__has_attribute(scoped_lockable)
 #error "Should support scoped_lockable attribute"
@@ -215,11 +244,11 @@ void sl_function_params(int lvar __attribute__((scoped_lockable))); // \
   expected-warning {{'scoped_lockable' attribute only applies to classes}}
 
 
-/***********************************
- *  Guarded By Attribute (gb)
- ***********************************/
+//-----------------------------------------//
+//  Guarded By Attribute (gb)
+//-----------------------------------------//
 
-// FIXME: Would we like this attribute to take more than 1 arg?
+// FIXME: Eventually, would we like this attribute to take more than 1 arg?
 
 #if !__has_attribute(guarded_by)
 #error "Should support guarded_by attribute"
@@ -258,24 +287,36 @@ int gb_testfn(int y){
   return x;
 }
 
-//2.Deal with argument parsing:
-// grab token stream parsing from C++0x branch
-// possibly create new, more permissive category for gcc attributes
-
-//foo
-//foo.bar
-//foo.bar->baz
-//foo.bar()->baz()->a
-//&foo
-//*foo
+//2. Check argument parsing.
+
+// legal attribute arguments
+int gb_var_arg_1 __attribute__((guarded_by(muWrapper.mu)));
+int gb_var_arg_2 __attribute__((guarded_by(muDoubleWrapper.muWrapper->mu)));
+int gb_var_arg_3 __attribute__((guarded_by(muWrapper.getMu())));
+int gb_var_arg_4 __attribute__((guarded_by(*muWrapper.getMuPointer())));
+int gb_var_arg_5 __attribute__((guarded_by(&mu1)));
+int gb_var_arg_6 __attribute__((guarded_by(muRef)));
+int gb_var_arg_7 __attribute__((guarded_by(muDoubleWrapper.getWrapper()->getMu())));
+int gb_var_arg_8 __attribute__((guarded_by(muPointer)));
+
+
+// illegal attribute arguments
+int gb_var_arg_bad_1 __attribute__((guarded_by(1))); // \
+  expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
+int gb_var_arg_bad_2 __attribute__((guarded_by("mu"))); // \
+  expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
+int gb_var_arg_bad_3 __attribute__((guarded_by(muDoublePointer))); // \
+  expected-error {{'guarded_by' attribute requires arguments that are class type or point to class type}}
+int gb_var_arg_bad_4 __attribute__((guarded_by(umu))); // \
+  expected-error {{'guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
 
 //3.
 // Thread Safety analysis tests
 
 
-/***********************************
- *  Pt Guarded By Attribute (pgb)
- ***********************************/
+//-----------------------------------------//
+//  Pt Guarded By Attribute (pgb)
+//-----------------------------------------//
 
 #if !__has_attribute(pt_guarded_by)
 #error "Should support pt_guarded_by attribute"
@@ -317,12 +358,35 @@ void pgb_testfn(int y){
   delete x;
 }
 
-/***********************************
- *  Acquired After (aa)
- ***********************************/
+//2. Check argument parsing.
+
+// legal attribute arguments
+int * pgb_var_arg_1 __attribute__((pt_guarded_by(muWrapper.mu)));
+int * pgb_var_arg_2 __attribute__((pt_guarded_by(muDoubleWrapper.muWrapper->mu)));
+int * pgb_var_arg_3 __attribute__((pt_guarded_by(muWrapper.getMu())));
+int * pgb_var_arg_4 __attribute__((pt_guarded_by(*muWrapper.getMuPointer())));
+int * pgb_var_arg_5 __attribute__((pt_guarded_by(&mu1)));
+int * pgb_var_arg_6 __attribute__((pt_guarded_by(muRef)));
+int * pgb_var_arg_7 __attribute__((pt_guarded_by(muDoubleWrapper.getWrapper()->getMu())));
+int * pgb_var_arg_8 __attribute__((pt_guarded_by(muPointer)));
+
+
+// illegal attribute arguments
+int * pgb_var_arg_bad_1 __attribute__((pt_guarded_by(1))); // \
+  expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
+int * pgb_var_arg_bad_2 __attribute__((pt_guarded_by("mu"))); // \
+  expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
+int * pgb_var_arg_bad_3 __attribute__((pt_guarded_by(muDoublePointer))); // \
+  expected-error {{'pt_guarded_by' attribute requires arguments that are class type or point to class type}}
+int * pgb_var_arg_bad_4 __attribute__((pt_guarded_by(umu))); // \
+  expected-error {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+
+//-----------------------------------------//
+//  Acquired After (aa)
+//-----------------------------------------//
 
 // FIXME: Would we like this attribute to take more than 1 arg?
-// FIXME: What about pointers to locks?
 
 #if !__has_attribute(acquired_after)
 #error "Should support acquired_after attribute"
@@ -355,13 +419,34 @@ void aa_testfn(int y){
       expected-warning {{'acquired_after' attribute only applies to fields and global variables}}
 }
 
-// Note: illegal int aa_int __attribute__((acquired_after(mu1))) will
-// be taken care of by warnings that aa__int is not lockable.
-
-
-/***********************************
- *  Acquired Before (ab)
- ***********************************/
+//Check argument parsing.
+
+// legal attribute arguments
+Mu aa_var_arg_1 __attribute__((acquired_after(muWrapper.mu)));
+Mu aa_var_arg_2 __attribute__((acquired_after(muDoubleWrapper.muWrapper->mu)));
+Mu aa_var_arg_3 __attribute__((acquired_after(muWrapper.getMu())));
+Mu aa_var_arg_4 __attribute__((acquired_after(*muWrapper.getMuPointer())));
+Mu aa_var_arg_5 __attribute__((acquired_after(&mu1)));
+Mu aa_var_arg_6 __attribute__((acquired_after(muRef)));
+Mu aa_var_arg_7 __attribute__((acquired_after(muDoubleWrapper.getWrapper()->getMu())));
+Mu aa_var_arg_8 __attribute__((acquired_after(muPointer)));
+
+
+// illegal attribute arguments
+Mu aa_var_arg_bad_1 __attribute__((acquired_after(1))); // \
+  expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}}
+Mu aa_var_arg_bad_2 __attribute__((acquired_after("mu"))); // \
+  expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}}
+Mu aa_var_arg_bad_3 __attribute__((acquired_after(muDoublePointer))); // \
+  expected-error {{'acquired_after' attribute requires arguments that are class type or point to class type}}
+Mu aa_var_arg_bad_4 __attribute__((acquired_after(umu))); // \
+  expected-error {{'acquired_after' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+UnlockableMu aa_var_arg_bad_5 __attribute__((acquired_after(mu_aa))); // \
+  expected-error {{'acquired_after' attribute can only be applied in a context annotated with 'lockable' attribute}}
+
+//-----------------------------------------//
+//  Acquired Before (ab)
+//-----------------------------------------//
 
 #if !__has_attribute(acquired_before)
 #error "Should support acquired_before attribute"
@@ -397,9 +482,35 @@ void ab_testfn(int y){
 // Note: illegal int ab_int __attribute__((acquired_before(mu1))) will
 // be taken care of by warnings that ab__int is not lockable.
 
-/***********************************
- *  Exclusive Lock Function (elf)
- ***********************************/
+//Check argument parsing.
+
+// legal attribute arguments
+Mu ab_var_arg_1 __attribute__((acquired_before(muWrapper.mu)));
+Mu ab_var_arg_2 __attribute__((acquired_before(muDoubleWrapper.muWrapper->mu)));
+Mu ab_var_arg_3 __attribute__((acquired_before(muWrapper.getMu())));
+Mu ab_var_arg_4 __attribute__((acquired_before(*muWrapper.getMuPointer())));
+Mu ab_var_arg_5 __attribute__((acquired_before(&mu1)));
+Mu ab_var_arg_6 __attribute__((acquired_before(muRef)));
+Mu ab_var_arg_7 __attribute__((acquired_before(muDoubleWrapper.getWrapper()->getMu())));
+Mu ab_var_arg_8 __attribute__((acquired_before(muPointer)));
+
+
+// illegal attribute arguments
+Mu ab_var_arg_bad_1 __attribute__((acquired_before(1))); // \
+  expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}}
+Mu ab_var_arg_bad_2 __attribute__((acquired_before("mu"))); // \
+  expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}}
+Mu ab_var_arg_bad_3 __attribute__((acquired_before(muDoublePointer))); // \
+  expected-error {{'acquired_before' attribute requires arguments that are class type or point to class type}}
+Mu ab_var_arg_bad_4 __attribute__((acquired_before(umu))); // \
+  expected-error {{'acquired_before' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+UnlockableMu ab_var_arg_bad_5 __attribute__((acquired_before(mu_ab))); // \
+  expected-error {{'acquired_before' attribute can only be applied in a context annotated with 'lockable' attribute}}
+
+
+//-----------------------------------------//
+//  Exclusive Lock Function (elf)
+//-----------------------------------------//
 
 #if !__has_attribute(exclusive_lock_function)
 #error "Should support exclusive_lock_function attribute"
@@ -436,11 +547,42 @@ class __attribute__((exclusive_lock_function)) ElfTestClass { // \
 void elf_fun_params(int lvar __attribute__((exclusive_lock_function))); // \
   expected-warning {{'exclusive_lock_function' attribute only applies to functions and methods}}
 
-
-
-/***********************************
- *  Shared Lock Function (slf)
- ***********************************/
+// Check argument parsing.
+
+// legal attribute arguments
+int elf_function_1() __attribute__((exclusive_lock_function(muWrapper.mu)));
+int elf_function_2() __attribute__((exclusive_lock_function(muDoubleWrapper.muWrapper->mu)));
+int elf_function_3() __attribute__((exclusive_lock_function(muWrapper.getMu())));
+int elf_function_4() __attribute__((exclusive_lock_function(*muWrapper.getMuPointer())));
+int elf_function_5() __attribute__((exclusive_lock_function(&mu1)));
+int elf_function_6() __attribute__((exclusive_lock_function(muRef)));
+int elf_function_7() __attribute__((exclusive_lock_function(muDoubleWrapper.getWrapper()->getMu())));
+int elf_function_8() __attribute__((exclusive_lock_function(muPointer)));
+int elf_function_9(Mu x) __attribute__((exclusive_lock_function(1)));
+int elf_function_9(Mu x, Mu y) __attribute__((exclusive_lock_function(1,2)));
+
+
+// illegal attribute arguments
+int elf_function_bad_2() __attribute__((exclusive_lock_function("mu"))); // \
+  expected-error {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
+int elf_function_bad_3() __attribute__((exclusive_lock_function(muDoublePointer))); // \
+  expected-error {{'exclusive_lock_function' attribute requires arguments that are class type or point to class type}}
+int elf_function_bad_4() __attribute__((exclusive_lock_function(umu))); // \
+  expected-error {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+int elf_function_bad_1() __attribute__((exclusive_lock_function(1))); // \
+  expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
+int elf_function_bad_5(Mu x) __attribute__((exclusive_lock_function(0))); // \
+  expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}}
+int elf_function_bad_6(Mu x, Mu y) __attribute__((exclusive_lock_function(0))); // \
+  expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}}
+int elf_function_bad_7() __attribute__((exclusive_lock_function(0))); // \
+  expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
+
+
+//-----------------------------------------//
+//  Shared Lock Function (slf)
+//-----------------------------------------//
 
 #if !__has_attribute(shared_lock_function)
 #error "Should support shared_lock_function attribute"
@@ -477,10 +619,42 @@ class __attribute__((shared_lock_function)) SlfTestClass { // \
     expected-warning {{'shared_lock_function' attribute only applies to functions and methods}}
 };
 
-
-/***********************************
- *  Exclusive TryLock Function (etf)
- ***********************************/
+// Check argument parsing.
+
+// legal attribute arguments
+int slf_function_1() __attribute__((shared_lock_function(muWrapper.mu)));
+int slf_function_2() __attribute__((shared_lock_function(muDoubleWrapper.muWrapper->mu)));
+int slf_function_3() __attribute__((shared_lock_function(muWrapper.getMu())));
+int slf_function_4() __attribute__((shared_lock_function(*muWrapper.getMuPointer())));
+int slf_function_5() __attribute__((shared_lock_function(&mu1)));
+int slf_function_6() __attribute__((shared_lock_function(muRef)));
+int slf_function_7() __attribute__((shared_lock_function(muDoubleWrapper.getWrapper()->getMu())));
+int slf_function_8() __attribute__((shared_lock_function(muPointer)));
+int slf_function_9(Mu x) __attribute__((shared_lock_function(1)));
+int slf_function_9(Mu x, Mu y) __attribute__((shared_lock_function(1,2)));
+
+
+// illegal attribute arguments
+int slf_function_bad_2() __attribute__((shared_lock_function("mu"))); // \
+  expected-error {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
+int slf_function_bad_3() __attribute__((shared_lock_function(muDoublePointer))); // \
+  expected-error {{'shared_lock_function' attribute requires arguments that are class type or point to class type}}
+int slf_function_bad_4() __attribute__((shared_lock_function(umu))); // \
+  expected-error {{'shared_lock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+int slf_function_bad_1() __attribute__((shared_lock_function(1))); // \
+  expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
+int slf_function_bad_5(Mu x) __attribute__((shared_lock_function(0))); // \
+  expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}}
+int slf_function_bad_6(Mu x, Mu y) __attribute__((shared_lock_function(0))); // \
+  expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}}
+int slf_function_bad_7() __attribute__((shared_lock_function(0))); // \
+  expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
+
+
+//-----------------------------------------//
+//  Exclusive TryLock Function (etf)
+//-----------------------------------------//
 
 #if !__has_attribute(exclusive_trylock_function)
 #error "Should support exclusive_trylock_function attribute"
@@ -521,11 +695,39 @@ class __attribute__((exclusive_trylock_function(1))) EtfTestClass { // \
 void etf_fun_params(int lvar __attribute__((exclusive_trylock_function(1)))); // \
   expected-warning {{'exclusive_trylock_function' attribute only applies to functions and methods}}
 
+// Check argument parsing.
+
+// legal attribute arguments
+int etf_function_1() __attribute__((exclusive_trylock_function(1, muWrapper.mu)));
+int etf_function_2() __attribute__((exclusive_trylock_function(1, muDoubleWrapper.muWrapper->mu)));
+int etf_function_3() __attribute__((exclusive_trylock_function(1, muWrapper.getMu())));
+int etf_function_4() __attribute__((exclusive_trylock_function(1, *muWrapper.getMuPointer())));
+int etf_function_5() __attribute__((exclusive_trylock_function(1, &mu1)));
+int etf_function_6() __attribute__((exclusive_trylock_function(1, muRef)));
+int etf_function_7() __attribute__((exclusive_trylock_function(1, muDoubleWrapper.getWrapper()->getMu())));
+int etf_functetfn_8() __attribute__((exclusive_trylock_function(1, muPointer)));
+int etf_function_9() __attribute__((exclusive_trylock_function(true)));
+
+
+// illegal attribute arguments
+int etf_function_bad_1() __attribute__((exclusive_trylock_function(mu1))); // \
+  expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
+int etf_function_bad_2() __attribute__((exclusive_trylock_function("mu"))); // \
+  expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
+int etf_function_bad_3() __attribute__((exclusive_trylock_function(muDoublePointer))); // \
+  expected-error {{'exclusive_trylock_function' attribute first argument must be of int or bool type}}
 
+int etf_function_bad_4() __attribute__((exclusive_trylock_function(1, "mu"))); // \
+  expected-error {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
+int etf_function_bad_5() __attribute__((exclusive_trylock_function(1, muDoublePointer))); // \
+  expected-error {{'exclusive_trylock_function' attribute requires arguments that are class type or point to class type}}
+int etf_function_bad_6() __attribute__((exclusive_trylock_function(1, umu))); // \
+  expected-error {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
 
-/***********************************
- *  Shared TryLock Function (stf)
- ***********************************/
+
+//-----------------------------------------//
+//  Shared TryLock Function (stf)
+//-----------------------------------------//
 
 #if !__has_attribute(shared_trylock_function)
 #error "Should support shared_trylock_function attribute"
@@ -567,10 +769,39 @@ class __attribute__((shared_trylock_function(1))) StfTestClass { // \
     expected-warning {{'shared_trylock_function' attribute only applies to functions and methods}}
 };
 
+// Check argument parsing.
+
+// legal attribute arguments
+int stf_function_1() __attribute__((shared_trylock_function(1, muWrapper.mu)));
+int stf_function_2() __attribute__((shared_trylock_function(1, muDoubleWrapper.muWrapper->mu)));
+int stf_function_3() __attribute__((shared_trylock_function(1, muWrapper.getMu())));
+int stf_function_4() __attribute__((shared_trylock_function(1, *muWrapper.getMuPointer())));
+int stf_function_5() __attribute__((shared_trylock_function(1, &mu1)));
+int stf_function_6() __attribute__((shared_trylock_function(1, muRef)));
+int stf_function_7() __attribute__((shared_trylock_function(1, muDoubleWrapper.getWrapper()->getMu())));
+int stf_function_8() __attribute__((shared_trylock_function(1, muPointer)));
+int stf_function_9() __attribute__((shared_trylock_function(true)));
+
+
+// illegal attribute arguments
+int stf_function_bad_1() __attribute__((shared_trylock_function(mu1))); // \
+  expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
+int stf_function_bad_2() __attribute__((shared_trylock_function("mu"))); // \
+  expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
+int stf_function_bad_3() __attribute__((shared_trylock_function(muDoublePointer))); // \
+  expected-error {{'shared_trylock_function' attribute first argument must be of int or bool type}}
 
-/***********************************
- *  Unlock Function (uf)
- ***********************************/
+int stf_function_bad_4() __attribute__((shared_trylock_function(1, "mu"))); // \
+  expected-error {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
+int stf_function_bad_5() __attribute__((shared_trylock_function(1, muDoublePointer))); // \
+  expected-error {{'shared_trylock_function' attribute requires arguments that are class type or point to class type}}
+int stf_function_bad_6() __attribute__((shared_trylock_function(1, umu))); // \
+  expected-error {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+
+//-----------------------------------------//
+//  Unlock Function (uf)
+//-----------------------------------------//
 
 #if !__has_attribute(unlock_function)
 #error "Should support unlock_function attribute"
@@ -607,10 +838,42 @@ class __attribute__((no_thread_safety_analysis)) UfTestClass { // \
 void uf_fun_params(int lvar __attribute__((unlock_function))); // \
   expected-warning {{'unlock_function' attribute only applies to functions and methods}}
 
-
-/***********************************
- *  Lock Returned (lr)
- ***********************************/
+// Check argument parsing.
+
+// legal attribute arguments
+int uf_function_1() __attribute__((unlock_function(muWrapper.mu)));
+int uf_function_2() __attribute__((unlock_function(muDoubleWrapper.muWrapper->mu)));
+int uf_function_3() __attribute__((unlock_function(muWrapper.getMu())));
+int uf_function_4() __attribute__((unlock_function(*muWrapper.getMuPointer())));
+int uf_function_5() __attribute__((unlock_function(&mu1)));
+int uf_function_6() __attribute__((unlock_function(muRef)));
+int uf_function_7() __attribute__((unlock_function(muDoubleWrapper.getWrapper()->getMu())));
+int uf_function_8() __attribute__((unlock_function(muPointer)));
+int uf_function_9(Mu x) __attribute__((unlock_function(1)));
+int uf_function_9(Mu x, Mu y) __attribute__((unlock_function(1,2)));
+
+
+// illegal attribute arguments
+int uf_function_bad_2() __attribute__((unlock_function("mu"))); // \
+  expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}}
+int uf_function_bad_3() __attribute__((unlock_function(muDoublePointer))); // \
+expected-error {{'unlock_function' attribute requires arguments that are class type or point to class type}}
+int uf_function_bad_4() __attribute__((unlock_function(umu))); // \
+  expected-error {{'unlock_function' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+int uf_function_bad_1() __attribute__((unlock_function(1))); // \
+  expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
+int uf_function_bad_5(Mu x) __attribute__((unlock_function(0))); // \
+  expected-error {{'unlock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}}
+int uf_function_bad_6(Mu x, Mu y) __attribute__((unlock_function(0))); // \
+  expected-error {{'unlock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}}
+int uf_function_bad_7() __attribute__((unlock_function(0))); // \
+  expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}}
+
+
+//-----------------------------------------//
+//  Lock Returned (lr)
+//-----------------------------------------//
 
 #if !__has_attribute(lock_returned)
 #error "Should support lock_returned attribute"
@@ -651,9 +914,34 @@ class __attribute__((lock_returned(mu1))) LrTestClass { // \
     expected-warning {{'lock_returned' attribute only applies to functions and methods}}
 };
 
-/***********************************
- *  Locks Excluded (le)
- ***********************************/
+// Check argument parsing.
+
+// legal attribute arguments
+int lr_function_1() __attribute__((lock_returned(muWrapper.mu)));
+int lr_function_2() __attribute__((lock_returned(muDoubleWrapper.muWrapper->mu)));
+int lr_function_3() __attribute__((lock_returned(muWrapper.getMu())));
+int lr_function_4() __attribute__((lock_returned(*muWrapper.getMuPointer())));
+int lr_function_5() __attribute__((lock_returned(&mu1)));
+int lr_function_6() __attribute__((lock_returned(muRef)));
+int lr_function_7() __attribute__((lock_returned(muDoubleWrapper.getWrapper()->getMu())));
+int lr_function_8() __attribute__((lock_returned(muPointer)));
+
+
+// illegal attribute arguments
+int lr_function_bad_1() __attribute__((lock_returned(1))); // \
+  expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
+int lr_function_bad_2() __attribute__((lock_returned("mu"))); // \
+  expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
+int lr_function_bad_3() __attribute__((lock_returned(muDoublePointer))); // \
+  expected-error {{'lock_returned' attribute requires arguments that are class type or point to class type}}
+int lr_function_bad_4() __attribute__((lock_returned(umu))); // \
+  expected-error {{'lock_returned' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+
+
+//-----------------------------------------//
+//  Locks Excluded (le)
+//-----------------------------------------//
 
 #if !__has_attribute(locks_excluded)
 #error "Should support locks_excluded attribute"
@@ -693,10 +981,34 @@ class __attribute__((locks_excluded(mu1))) LeTestClass { // \
     expected-warning {{'locks_excluded' attribute only applies to functions and methods}}
 };
 
+// Check argument parsing.
+
+// legal attribute arguments
+int le_function_1() __attribute__((locks_excluded(muWrapper.mu)));
+int le_function_2() __attribute__((locks_excluded(muDoubleWrapper.muWrapper->mu)));
+int le_function_3() __attribute__((locks_excluded(muWrapper.getMu())));
+int le_function_4() __attribute__((locks_excluded(*muWrapper.getMuPointer())));
+int le_function_5() __attribute__((locks_excluded(&mu1)));
+int le_function_6() __attribute__((locks_excluded(muRef)));
+int le_function_7() __attribute__((locks_excluded(muDoubleWrapper.getWrapper()->getMu())));
+int le_function_8() __attribute__((locks_excluded(muPointer)));
 
-/***********************************
- *  Exclusive Locks Required (elr)
- ***********************************/
+
+// illegal attribute arguments
+int le_function_bad_1() __attribute__((locks_excluded(1))); // \
+  expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
+int le_function_bad_2() __attribute__((locks_excluded("mu"))); // \
+  expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
+int le_function_bad_3() __attribute__((locks_excluded(muDoublePointer))); // \
+  expected-error {{'locks_excluded' attribute requires arguments that are class type or point to class type}}
+int le_function_bad_4() __attribute__((locks_excluded(umu))); // \
+  expected-error {{'locks_excluded' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+
+
+//-----------------------------------------//
+//  Exclusive Locks Required (elr)
+//-----------------------------------------//
 
 #if !__has_attribute(exclusive_locks_required)
 #error "Should support exclusive_locks_required attribute"
@@ -736,9 +1048,35 @@ class __attribute__((exclusive_locks_required(mu1))) ElrTestClass { // \
     expected-warning {{'exclusive_locks_required' attribute only applies to functions and methods}}
 };
 
-/***********************************
- *  Shared Locks Required (slr)
- ***********************************/
+// Check argument parsing.
+
+// legal attribute arguments
+int elr_function_1() __attribute__((exclusive_locks_required(muWrapper.mu)));
+int elr_function_2() __attribute__((exclusive_locks_required(muDoubleWrapper.muWrapper->mu)));
+int elr_function_3() __attribute__((exclusive_locks_required(muWrapper.getMu())));
+int elr_function_4() __attribute__((exclusive_locks_required(*muWrapper.getMuPointer())));
+int elr_function_5() __attribute__((exclusive_locks_required(&mu1)));
+int elr_function_6() __attribute__((exclusive_locks_required(muRef)));
+int elr_function_7() __attribute__((exclusive_locks_required(muDoubleWrapper.getWrapper()->getMu())));
+int elr_function_8() __attribute__((exclusive_locks_required(muPointer)));
+
+
+// illegal attribute arguments
+int elr_function_bad_1() __attribute__((exclusive_locks_required(1))); // \
+  expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
+int elr_function_bad_2() __attribute__((exclusive_locks_required("mu"))); // \
+  expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
+int elr_function_bad_3() __attribute__((exclusive_locks_required(muDoublePointer))); // \
+  expected-error {{'exclusive_locks_required' attribute requires arguments that are class type or point to class type}}
+int elr_function_bad_4() __attribute__((exclusive_locks_required(umu))); // \
+  expected-error {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+
+
+
+
+//-----------------------------------------//
+//  Shared Locks Required (slr)
+//-----------------------------------------//
 
 #if !__has_attribute(shared_locks_required)
 #error "Should support shared_locks_required attribute"
@@ -777,3 +1115,27 @@ class SlrFoo {
 class __attribute__((shared_locks_required(mu1))) SlrTestClass { // \
     expected-warning {{'shared_locks_required' attribute only applies to functions and methods}}
 };
+
+// Check argument parsing.
+
+// legal attribute arguments
+int slr_function_1() __attribute__((shared_locks_required(muWrapper.mu)));
+int slr_function_2() __attribute__((shared_locks_required(muDoubleWrapper.muWrapper->mu)));
+int slr_function_3() __attribute__((shared_locks_required(muWrapper.getMu())));
+int slr_function_4() __attribute__((shared_locks_required(*muWrapper.getMuPointer())));
+int slr_function_5() __attribute__((shared_locks_required(&mu1)));
+int slr_function_6() __attribute__((shared_locks_required(muRef)));
+int slr_function_7() __attribute__((shared_locks_required(muDoubleWrapper.getWrapper()->getMu())));
+int slr_function_8() __attribute__((shared_locks_required(muPointer)));
+
+
+// illegal attribute arguments
+int slr_function_bad_1() __attribute__((shared_locks_required(1))); // \
+  expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
+int slr_function_bad_2() __attribute__((shared_locks_required("mu"))); // \
+  expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
+int slr_function_bad_3() __attribute__((shared_locks_required(muDoublePointer))); // \
+  expected-error {{'shared_locks_required' attribute requires arguments that are class type or point to class type}}
+int slr_function_bad_4() __attribute__((shared_locks_required(umu))); // \
+  expected-error {{'shared_locks_required' attribute requires arguments whose type is annotated with 'lockable' attribute}}
+