From e8799f8d23ee863feb2557942321e5d466fc8f95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Matos?= <ripzonetriton@gmail.com>
Date: Sat, 25 Aug 2012 20:41:44 +0100
Subject: [PATCH] Added support for MSVC 2012 type traits used in standard
 library.

---
 include/clang/Basic/TokenKinds.def |  3 ++
 include/clang/Basic/TypeTraits.h   |  3 ++
 lib/AST/StmtPrinter.cpp            |  3 ++
 lib/Parse/ParseExpr.cpp            |  3 ++
 lib/Parse/ParseExprCXX.cpp         |  4 +++
 lib/Sema/SemaExprCXX.cpp           | 59 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 75 insertions(+)

diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index fc03191..c5623ff 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -350,11 +350,14 @@ KEYWORD(L__FUNCTION__               , KEYMS)
 
 // GNU and MS Type Traits
 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)
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index 0a5a864..9f27fa0 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -20,11 +20,14 @@ namespace clang {
   /// \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,
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 9a31416..badb46e 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1510,9 +1510,12 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
 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_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";
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 8df08b8..728a3d5 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1171,10 +1171,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
   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_trivial_move_assign:
   case tok::kw___has_trivial_destructor:
   case tok::kw___has_nothrow_assign:
+  case tok::kw___has_nothrow_move_assign:
   case tok::kw___has_nothrow_copy:
   case tok::kw___has_nothrow_constructor:
   case tok::kw___has_virtual_destructor:
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index e02cb7a..93cc182 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -2435,11 +2435,15 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
   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;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4fc9abd..9501af8 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2945,10 +2945,13 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
     // 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:
@@ -3092,6 +3095,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
           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.
+    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
@@ -3123,6 +3135,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
     if (const RecordType *RT = T->getAs<RecordType>())
       return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
     return false;
+  case UTT_HasTrivialMoveAssign:
+    // This trait is implemented by MSVC 2012 and needed to parse the
+    // standard library headers.
+    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_HasTrivialDestructor:
     // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
     //   If __is_pod (type) is true or type is a reference type
@@ -3190,6 +3211,44 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
       return FoundAssign;
     }
     return false;
+  case UTT_HasNothrowMoveAssign:
+    // This trait is implemented by MSVC 2012 and needed to parse the
+    // standard library headers.
+    if (T.isPODType(Self.Context))
+      return true;
+    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
+      CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialMoveAssignment())
+        return true;
+      
+      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
-- 
1.7.11

