Index: test/SemaCXX/type-traits.cpp
===================================================================
--- test/SemaCXX/type-traits.cpp	(revision 167523)
+++ test/SemaCXX/type-traits.cpp	(working copy)
@@ -39,6 +39,20 @@
 struct HasCons { HasCons(int); };
 struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); };
 struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); };
+struct HasNoThrowMoveAssign { HasNoThrowMoveAssign& operator =(const HasNoThrowMoveAssign&&) throw(); };
+struct HasNoExceptNoThrowMoveAssign { HasNoExceptNoThrowMoveAssign& operator =(const HasNoExceptNoThrowMoveAssign&&) noexcept; };
+struct HasThrowMoveAssign { HasThrowMoveAssign& operator =(const HasThrowMoveAssign&&) throw(POD); };
+struct HasNoExceptFalseMoveAssign { HasNoExceptFalseMoveAssign& operator =(const HasNoExceptFalseMoveAssign&&) noexcept(false); };
+struct HasMoveCtor { HasMoveCtor(const HasMoveCtor&&); };
+struct HasMemberMoveCtor { HasMoveCtor member; };
+struct HasMemberMoveAssign { HasMoveAssign member; };
+struct HasStaticMemberMoveCtor { static HasMoveCtor member; };
+struct HasStaticMemberMoveAssign { static HasMoveAssign member; };
+struct HasMemberThrowMoveAssign { HasThrowMoveAssign member; };
+struct HasMemberNoExceptFalseMoveAssign { HasNoExceptFalseMoveAssign member; };
+struct HasMemberNoThrowMoveAssign { HasNoThrowMoveAssign member; };
+struct HasMemberNoExceptNoThrowMoveAssign { HasNoExceptNoThrowMoveAssign member; };
+
 struct HasDefaultTrivialCopyAssign { 
   HasDefaultTrivialCopyAssign &operator =(const HasDefaultTrivialCopyAssign&)
     = default; 
@@ -69,6 +83,7 @@
 struct DerivesHasProt : HasProt {};
 struct DerivesHasRef : HasRef {};
 struct DerivesHasVirt : HasVirt {};
+struct DerivesHasMoveCtor : HasMoveCtor {};
 
 struct HasNoThrowCopyAssign {
   void operator =(const HasNoThrowCopyAssign&) throw();
@@ -165,7 +180,7 @@
 struct Bit0 { int : 0; };
 struct Bit0Cons { int : 0; Bit0Cons(); };
 struct BitOnly { int x : 3; };
-//struct DerivesVirt : virtual POD {};
+struct DerivesVirt : virtual POD {};
 
 void is_empty()
 {
@@ -1203,6 +1218,27 @@
   { int arr[F(__has_trivial_constructor(ExtDefaulted))]; }
 }
 
+void has_trivial_move_constructor() {
+  // n3376 12.8 [class.copy]/12
+  // A copy/move constructor for class X is trivial if it is not user-provided, its declared parameter type is the
+  // same as if it had been implicitly declared, and if
+  //   — class X has no virtual functions (10.3) and no virtual base classes (10.1), and
+  //   — the constructor selected to copy/move each direct base class subobject is trivial, and
+  //   — for each non-static data member of X that is of class type (or array thereof), the constructor selected
+  //     to copy/move that member is trivial;
+  // otherwise the copy/move constructor is non-trivial.
+  { int arr[T(__has_trivial_move_constructor(POD))]; }
+  { int arr[T(__has_trivial_move_constructor(Union))]; }
+  { int arr[T(__has_trivial_move_constructor(HasCons))]; }
+  { int arr[T(__has_trivial_move_constructor(HasStaticMemberMoveCtor))]; }
+  
+  { int arr[F(__has_trivial_move_constructor(HasVirt))]; }
+  { int arr[F(__has_trivial_move_constructor(DerivesVirt))]; }
+  { int arr[F(__has_trivial_move_constructor(HasMoveCtor))]; }
+  { int arr[F(__has_trivial_move_constructor(DerivesHasMoveCtor))]; }
+  { int arr[F(__has_trivial_move_constructor(HasMemberMoveCtor))]; }
+}
+
 void has_trivial_copy_constructor() {
   { int arr[T(__has_trivial_copy(Int))]; }
   { int arr[T(__has_trivial_copy(IntAr))]; }
@@ -1352,6 +1388,43 @@
   { int arr[F(__has_nothrow_assign(PR11110))]; }
 }
 
+void has_nothrow_move_assign() {
+  { int arr[T(__has_nothrow_move_assign(Int))]; }
+  { int arr[T(__has_nothrow_move_assign(Enum))]; }
+  { int arr[T(__has_nothrow_move_assign(Int*))]; }
+  { int arr[T(__has_nothrow_move_assign(Enum POD::*))]; }
+  { int arr[T(__has_nothrow_move_assign(POD))]; }
+  { int arr[T(__has_nothrow_move_assign(HasPriv))]; }
+  { int arr[T(__has_nothrow_move_assign(HasNoThrowMoveAssign))]; }
+  { int arr[T(__has_nothrow_move_assign(HasNoExceptNoThrowMoveAssign))]; }
+  { int arr[T(__has_nothrow_move_assign(HasMemberNoThrowMoveAssign))]; }
+  { int arr[T(__has_nothrow_move_assign(HasMemberNoExceptNoThrowMoveAssign))]; }
+  
+  { int arr[F(__has_nothrow_move_assign(HasThrowMoveAssign))]; }
+  { int arr[F(__has_nothrow_move_assign(HasNoExceptFalseMoveAssign))]; }
+  { int arr[F(__has_nothrow_move_assign(HasMemberThrowMoveAssign))]; }
+  { int arr[F(__has_nothrow_move_assign(HasMemberNoExceptFalseMoveAssign))]; }
+}
+
+void has_trivial_move_assign() {
+  // n3376 12.8 [class.copy]/25
+  // A copy/move assignment operator for class X is trivial if it is not user-provided, its declared parameter type
+  // is the same as if it had been implicitly declared, and if:
+  //  — class X has no virtual functions (10.3) and no virtual base classes (10.1), and
+  //  — the assignment operator selected to copy/move each direct base class subobject is trivial, and
+  //  — for each non-static data member of X that is of class type (or array thereof), the assignment operator
+  //    selected to copy/move that member is trivial;
+  { int arr[T(__has_trivial_move_assign(Int))]; }
+  { int arr[T(__has_trivial_move_assign(HasCopyAssign))]; }
+  { int arr[T(__has_trivial_move_assign(HasStaticMemberMoveAssign))]; }
+
+  { int arr[F(__has_trivial_move_assign(HasVirt))]; }
+  { int arr[F(__has_trivial_move_assign(DerivesVirt))]; }
+  { int arr[F(__has_trivial_move_assign(HasMoveAssign))]; }
+  { int arr[F(__has_trivial_move_assign(DerivesHasMoveAssign))]; }
+  { int arr[F(__has_trivial_move_assign(HasMemberMoveAssign))]; }
+}
+
 void has_nothrow_copy() {
   { int arr[T(__has_nothrow_copy(Int))]; }
   { int arr[T(__has_nothrow_copy(IntAr))]; }
Index: include/clang/Basic/TypeTraits.h
===================================================================
--- include/clang/Basic/TypeTraits.h	(revision 167523)
+++ include/clang/Basic/TypeTraits.h	(working copy)
@@ -20,11 +20,14 @@
   /// \brief Names for the unary type traits.
   enum UnaryTypeTrait {
     UTT_HasNothrowAssign,
+    UTT_HasNothrowMoveAssign,
     UTT_HasNothrowCopy,
     UTT_HasNothrowConstructor,
     UTT_HasTrivialAssign,
+    UTT_HasTrivialMoveAssign,
     UTT_HasTrivialCopy,
     UTT_HasTrivialDefaultConstructor,
+    UTT_HasTrivialMoveConstructor,
     UTT_HasTrivialDestructor,
     UTT_HasVirtualDestructor,
     UTT_IsAbstract,
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def	(revision 167523)
+++ include/clang/Basic/TokenKinds.def	(working copy)
@@ -350,31 +350,34 @@
 KEYWORD(L__FUNCTION__               , KEYMS)
 
 // GNU and MS Type Traits
-KEYWORD(__has_nothrow_assign        , KEYCXX)
-KEYWORD(__has_nothrow_copy          , KEYCXX)
-KEYWORD(__has_nothrow_constructor   , KEYCXX)
-KEYWORD(__has_trivial_assign        , KEYCXX)
-KEYWORD(__has_trivial_copy          , KEYCXX)
-KEYWORD(__has_trivial_constructor   , KEYCXX)
-KEYWORD(__has_trivial_destructor    , KEYCXX)
-KEYWORD(__has_virtual_destructor    , KEYCXX)
-KEYWORD(__is_abstract               , KEYCXX)
-KEYWORD(__is_base_of                , KEYCXX)
-KEYWORD(__is_class                  , KEYCXX)
-KEYWORD(__is_convertible_to         , KEYCXX)
-KEYWORD(__is_empty                  , KEYCXX)
-KEYWORD(__is_enum                   , KEYCXX)
-KEYWORD(__is_final                  , KEYCXX)
-KEYWORD(__is_interface_class        , KEYCXX)
+KEYWORD(__has_nothrow_assign          , KEYCXX)
+KEYWORD(__has_nothrow_move_assign     , KEYCXX)
+KEYWORD(__has_nothrow_copy            , KEYCXX)
+KEYWORD(__has_nothrow_constructor     , KEYCXX)
+KEYWORD(__has_trivial_assign          , KEYCXX)
+KEYWORD(__has_trivial_move_assign     , KEYCXX)
+KEYWORD(__has_trivial_copy            , KEYCXX)
+KEYWORD(__has_trivial_constructor     , KEYCXX)
+KEYWORD(__has_trivial_move_constructor, KEYCXX)
+KEYWORD(__has_trivial_destructor      , KEYCXX)
+KEYWORD(__has_virtual_destructor      , KEYCXX)
+KEYWORD(__is_abstract                 , KEYCXX)
+KEYWORD(__is_base_of                  , KEYCXX)
+KEYWORD(__is_class                    , KEYCXX)
+KEYWORD(__is_convertible_to           , KEYCXX)
+KEYWORD(__is_empty                    , KEYCXX)
+KEYWORD(__is_enum                     , KEYCXX)
+KEYWORD(__is_final                    , KEYCXX)
+KEYWORD(__is_interface_class          , KEYCXX)
 // Tentative name - there's no implementation of std::is_literal_type yet.
-KEYWORD(__is_literal                , KEYCXX)
+KEYWORD(__is_literal                  , KEYCXX)
 // Name for GCC 4.6 compatibility - people have already written libraries using
 // this name unfortunately.
-KEYWORD(__is_literal_type           , KEYCXX)
-KEYWORD(__is_pod                    , KEYCXX)
-KEYWORD(__is_polymorphic            , KEYCXX)
-KEYWORD(__is_trivial                , KEYCXX)
-KEYWORD(__is_union                  , KEYCXX)
+KEYWORD(__is_literal_type             , KEYCXX)
+KEYWORD(__is_pod                      , KEYCXX)
+KEYWORD(__is_polymorphic              , KEYCXX)
+KEYWORD(__is_trivial                  , KEYCXX)
+KEYWORD(__is_union                    , KEYCXX)
 
 // Clang-only C++ Type Traits
 KEYWORD(__is_trivially_constructible, KEYCXX)
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 167523)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -2920,10 +2920,13 @@
     // type due to the overarching C++0x type predicates being implemented
     // requiring the complete type.
   case UTT_HasNothrowAssign:
+  case UTT_HasNothrowMoveAssign:
   case UTT_HasNothrowConstructor:
   case UTT_HasNothrowCopy:
   case UTT_HasTrivialAssign:
+  case UTT_HasTrivialMoveAssign:
   case UTT_HasTrivialDefaultConstructor:
+  case UTT_HasTrivialMoveConstructor:
   case UTT_HasTrivialCopy:
   case UTT_HasTrivialDestructor:
   case UTT_HasVirtualDestructor:
@@ -3071,6 +3074,16 @@
           C.getBaseElementType(T)->getAs<RecordType>())
       return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
     return false;
+  case UTT_HasTrivialMoveConstructor:
+    //  This trait is implemented by MSVC 2012 and needed to parse the
+    //  standard library headers. Specifically this is used as the logic
+    //  behind std::has_trivial_move_constructor (20.9.4.3).
+    if (T.isPODType(Self.Context))
+      return true;
+    if (const RecordType *RT =
+          C.getBaseElementType(T)->getAs<RecordType>())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialMoveConstructor();
+    return false;
   case UTT_HasTrivialCopy:
     // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
     //   If __is_pod (type) is true or type is a reference type then
@@ -3082,6 +3095,15 @@
     if (const RecordType *RT = T->getAs<RecordType>())
       return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
     return false;
+  case UTT_HasTrivialMoveAssign:
+    //  This trait is implemented by MSVC 2012 and needed to parse the
+    //  standard library headers. Specifically it is used as the logic
+    //  behind std::is_trivially_move_assignable (20.9.4.3)
+    if (T.isPODType(Self.Context))
+      return true;
+    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
+      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialMoveAssignment();
+    return false;
   case UTT_HasTrivialAssign:
     // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
     //   If type is const qualified or is a reference type then the
@@ -3169,6 +3191,40 @@
       return FoundAssign;
     }
     return false;
+  case UTT_HasNothrowMoveAssign:
+    //  This trait is implemented by MSVC 2012 and needed to parse the
+    //  standard library headers. Specifically this is used as the logic
+    //  behind std::is_nothrow_move_assignable (20.9.4.3).
+    if (T.isPODType(Self.Context))
+      return true;
+    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
+      CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+
+      bool FoundAssign = false;
+      DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+      LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc), Sema::LookupOrdinaryName);
+      if (Self.LookupQualifiedName(Res, RD)) {
+        Res.suppressDiagnostics();
+        for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); Op != OpEnd; ++Op) {
+          if (isa<FunctionTemplateDecl>(*Op))
+            continue;
+              
+          CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+          if (Operator->isMoveAssignmentOperator()) {
+            FoundAssign = true;
+            const FunctionProtoType *CPT = Operator->getType()->getAs<FunctionProtoType>();
+            CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+            if (!CPT)
+                return false;
+            if (!CPT->isNothrow(Self.Context))
+                return false;
+          }
+        }
+      }
+
+      return FoundAssign;
+    }
+    return false;
   case UTT_HasNothrowCopy:
     // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
     //   If __has_trivial_copy (type) is true then the trait is true, else
@@ -3599,7 +3655,7 @@
     if (Self.getLangOpts().ObjCAutoRefCount &&
         hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
       return false;
-
+        
     return !Result.get()->hasNonTrivialCall(Self.Context);
   }
   }
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp	(revision 167523)
+++ lib/AST/StmtPrinter.cpp	(working copy)
@@ -1549,10 +1549,13 @@
 static const char *getTypeTraitName(UnaryTypeTrait UTT) {
   switch (UTT) {
   case UTT_HasNothrowAssign:      return "__has_nothrow_assign";
+  case UTT_HasNothrowMoveAssign:  return "__has_nothrow_move_assign";
   case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
   case UTT_HasNothrowCopy:          return "__has_nothrow_copy";
   case UTT_HasTrivialAssign:      return "__has_trivial_assign";
-  case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor";
+  case UTT_HasTrivialMoveAssign:      return "__has_trivial_move_assign";
+  case UTT_HasTrivialMoveConstructor: return "__has_trivial_move_constructor";
+  case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor";  
   case UTT_HasTrivialCopy:          return "__has_trivial_copy";
   case UTT_HasTrivialDestructor:  return "__has_trivial_destructor";
   case UTT_HasVirtualDestructor:  return "__has_virtual_destructor";
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 167523)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -1241,8 +1241,11 @@
   case tok::kw___is_union:
   case tok::kw___is_final:
   case tok::kw___has_trivial_constructor:
+  case tok::kw___has_trivial_move_constructor:
   case tok::kw___has_trivial_copy:
   case tok::kw___has_trivial_assign:
+  case tok::kw___has_nothrow_move_assign:
+  case tok::kw___has_trivial_move_assign:
   case tok::kw___has_trivial_destructor:
   case tok::kw___has_nothrow_assign:
   case tok::kw___has_nothrow_copy:
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 167523)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -2493,11 +2493,15 @@
   switch(kind) {
   default: llvm_unreachable("Not a known unary type trait.");
   case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
+  case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign;
   case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
   case tok::kw___has_nothrow_copy:           return UTT_HasNothrowCopy;
   case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign;
+  case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign;
   case tok::kw___has_trivial_constructor:
                                     return UTT_HasTrivialDefaultConstructor;
+  case tok::kw___has_trivial_move_constructor:
+                                    return UTT_HasTrivialMoveConstructor;
   case tok::kw___has_trivial_copy:           return UTT_HasTrivialCopy;
   case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor;
   case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor;
