[cfe-commits] r130076 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/SemaCXX/type-traits.cpp

Chandler Carruth chandlerc at gmail.com
Sat Apr 23 16:10:33 PDT 2011


Author: chandlerc
Date: Sat Apr 23 18:10:33 2011
New Revision: 130076

URL: http://llvm.org/viewvc/llvm-project?rev=130076&view=rev
Log:
Begin tracking trivialness of move constructors and move assignment
operators in C++ record declarations.

This patch starts off by updating a bunch of the standard citations to
refer to the draft 0x standard so that the semantics intended for move
varianst is clear. Where necessary these are duplicated so they'll be
available in doxygen.

It adds bit fields to keep track of the state for the move constructs,
and updates all the code necessary to track this state (I think) as
members are declared for a class. It also wires the state into the
various trait-like accessors in the AST's API, and tests that the type
trait expressions now behave correctly in the presence of move
constructors and move assignment operators.

This isn't complete yet due to these glaring FIXMEs:
1) No synthesis of implicit move constructors or assignment operators.
2) I don't think we correctly enforce the new logic for both copy and
   move trivial checks: that the *selected* copy/move
   constructor/operator is trivial. Currently this requires *all* of them
   to be trivial.
3) Some of the trait logic needs to be folded into the fine-grained
   trivial bits to more closely match the wording of the standard. For
   example, many of the places we currently set a bit to track POD-ness
   could be removed by querying other more fine grained traits on
   demand.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=130076&r1=130075&r2=130076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sat Apr 23 18:10:33 2011
@@ -319,28 +319,63 @@
     /// HasTrivialCopyConstructor - True when this class has a trivial copy
     /// constructor.
     ///
-    /// C++ [class.copy]p6.  A copy constructor for class X is trivial
-    /// if it is implicitly declared and if
-    /// * class X has no virtual functions and no virtual base classes, and
-    /// * each direct base class of X has a trivial copy constructor, and
-    /// * for all the nonstatic data members of X that are of class type (or
-    ///   array thereof), each such class type has a trivial copy constructor;
-    /// otherwise the copy constructor is non-trivial.
+    /// C++0x [class.copy]p13:
+    ///   A copy/move constructor for class X is trivial if it is neither
+    ///   user-provided nor deleted and if
+    ///    -- class X has no virtual functions and no virtual base classes, 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 an
+    ///       array thereof), the constructor selected to copy/move that member
+    ///       is trivial;
+    ///   otherwise the copy/move constructor is non-trivial.
     bool HasTrivialCopyConstructor : 1;
 
+    /// HasTrivialMoveConstructor - True when this class has a trivial move
+    /// constructor.
+    ///
+    /// C++0x [class.copy]p13:
+    ///   A copy/move constructor for class X is trivial if it is neither
+    ///   user-provided nor deleted and if
+    ///    -- class X has no virtual functions and no virtual base classes, 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 an
+    ///       array thereof), the constructor selected to copy/move that member
+    ///       is trivial;
+    ///   otherwise the copy/move constructor is non-trivial.
+    bool HasTrivialMoveConstructor : 1;
+
     /// HasTrivialCopyAssignment - True when this class has a trivial copy
     /// assignment operator.
     ///
-    /// C++ [class.copy]p11.  A copy assignment operator for class X is
-    /// trivial if it is implicitly declared and if
-    /// * class X has no virtual functions and no virtual base classes, and
-    /// * each direct base class of X has a trivial copy assignment operator, and
-    /// * for all the nonstatic data members of X that are of class type (or
-    ///   array thereof), each such class type has a trivial copy assignment
-    ///   operator;
-    /// otherwise the copy assignment operator is non-trivial.
+    /// C++0x [class.copy]p27:
+    ///   A copy/move assignment operator for class X is trivial if it is
+    ///   neither user-provided nor deleted and if
+    ///    -- class X has no virtual functions and no virtual base classes, 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 an
+    ///       array thereof), the assignment operator selected to copy/move
+    ///       that member is trivial;
+    ///   otherwise the copy/move assignment operator is non-trivial.
     bool HasTrivialCopyAssignment : 1;
 
+    /// HasTrivialMoveAssignment - True when this class has a trivial move
+    /// assignment operator.
+    ///
+    /// C++0x [class.copy]p27:
+    ///   A copy/move assignment operator for class X is trivial if it is
+    ///   neither user-provided nor deleted and if
+    ///    -- class X has no virtual functions and no virtual base classes, 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 an
+    ///       array thereof), the assignment operator selected to copy/move
+    ///       that member is trivial;
+    ///   otherwise the copy/move assignment operator is non-trivial.
+    bool HasTrivialMoveAssignment : 1;
+
     /// HasTrivialDestructor - True when this class has a trivial destructor.
     ///
     /// C++ [class.dtor]p3.  A destructor is trivial if it is an
@@ -726,17 +761,29 @@
   bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
 
   // hasTrivialCopyConstructor - Whether this class has a trivial copy
-  // constructor (C++ [class.copy]p6)
+  // constructor (C++ [class.copy]p6, C++0x [class.copy]p13)
   bool hasTrivialCopyConstructor() const {
     return data().HasTrivialCopyConstructor;
   }
 
+  // hasTrivialMoveConstructor - Whether this class has a trivial move
+  // constructor (C++0x [class.copy]p13)
+  bool hasTrivialMoveConstructor() const {
+    return data().HasTrivialMoveConstructor;
+  }
+
   // hasTrivialCopyAssignment - Whether this class has a trivial copy
-  // assignment operator (C++ [class.copy]p11)
+  // assignment operator (C++ [class.copy]p11, C++0x [class.copy]p27)
   bool hasTrivialCopyAssignment() const {
     return data().HasTrivialCopyAssignment;
   }
 
+  // hasTrivialMoveAssignment - Whether this class has a trivial move
+  // assignment operator (C++0x [class.copy]p27)
+  bool hasTrivialMoveAssignment() const {
+    return data().HasTrivialMoveAssignment;
+  }
+
   // hasTrivialDestructor - Whether this class has a trivial destructor
   // (C++ [class.dtor]p3)
   bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
@@ -1541,8 +1588,11 @@
 
   /// \brief Determine whether this constructor is a move constructor
   /// (C++0x [class.copy]p3), which can be used to move values of the class.
-  bool isMoveConstructor() const;
-  
+  bool isMoveConstructor() const {
+    unsigned TypeQuals = 0;
+    return isMoveConstructor(TypeQuals);
+  }
+
   /// \brief Determine whether this is a copy or move constructor.
   ///
   /// \param TypeQuals Will be set to the type qualifiers on the reference

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=130076&r1=130075&r2=130076&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sat Apr 23 18:10:33 2011
@@ -32,7 +32,8 @@
     UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
     Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
     Abstract(false), HasTrivialConstructor(true),
-    HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
+    HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true),
+    HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true),
     HasTrivialDestructor(true), ComputedVisibleConversions(false),
     DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), 
     DeclaredCopyAssignment(false), DeclaredDestructor(false),
@@ -139,16 +140,20 @@
       // C++ [class.ctor]p5:
       //   A constructor is trivial if its class has no virtual base classes.
       data().HasTrivialConstructor = false;
-      
-      // C++ [class.copy]p6:
-      //   A copy constructor is trivial if its class has no virtual base 
-      //   classes.
+
+      // C++0x [class.copy]p13:
+      //   A copy/move constructor for class X is trivial if it is neither
+      //   user-provided nor deleted and if
+      //    -- class X has no virtual functions and no virtual base classes, and
       data().HasTrivialCopyConstructor = false;
-      
-      // C++ [class.copy]p11:
-      //   A copy assignment operator is trivial if its class has no virtual
-      //   base classes.
+      data().HasTrivialMoveConstructor = false;
+
+      // C++0x [class.copy]p27:
+      //   A copy/move assignment operator for class X is trivial if it is
+      //   neither user-provided nor deleted and if
+      //    -- class X has no virtual functions and no virtual base classes, and
       data().HasTrivialCopyAssignment = false;
+      data().HasTrivialMoveAssignment = false;
     } else {
       // C++ [class.ctor]p5:
       //   A constructor is trivial if all the direct base classes of its
@@ -156,17 +161,29 @@
       if (!BaseClassDecl->hasTrivialConstructor())
         data().HasTrivialConstructor = false;
       
-      // C++ [class.copy]p6:
-      //   A copy constructor is trivial if all the direct base classes of its
-      //   class have trivial copy constructors.
+      // C++0x [class.copy]p13:
+      //   A copy/move constructor for class X is trivial if [...]
+      //    [...]
+      //    -- the constructor selected to copy/move each direct base class
+      //       subobject is trivial, and
+      // FIXME: C++0x: We need to only consider the selected constructor
+      // instead of all of them.
       if (!BaseClassDecl->hasTrivialCopyConstructor())
         data().HasTrivialCopyConstructor = false;
-      
-      // C++ [class.copy]p11:
-      //   A copy assignment operator is trivial if all the direct base classes
-      //   of its class have trivial copy assignment operators.
+      if (!BaseClassDecl->hasTrivialMoveConstructor())
+        data().HasTrivialMoveConstructor = false;
+
+      // C++0x [class.copy]p27:
+      //   A copy/move assignment operator for class X is trivial if [...]
+      //    [...]
+      //    -- the assignment operator selected to copy/move each direct base
+      //       class subobject is trivial, and
+      // FIXME: C++0x: We need to only consider the selected operator instead
+      // of all of them.
       if (!BaseClassDecl->hasTrivialCopyAssignment())
         data().HasTrivialCopyAssignment = false;
+      if (!BaseClassDecl->hasTrivialMoveAssignment())
+        data().HasTrivialMoveAssignment = false;
     }
     
     // C++ [class.ctor]p3:
@@ -223,11 +240,11 @@
   //   -- has no non-trivial copy constructors,
   if (!hasTrivialCopyConstructor()) return false;
   //   -- has no non-trivial move constructors,
-  // FIXME: C++0x: Track and check trivial move constructors.
+  if (!hasTrivialMoveConstructor()) return false;
   //   -- has no non-trivial copy assignment operators,
   if (!hasTrivialCopyAssignment()) return false;
   //   -- has no non-trivial move assignment operators, and
-  // FIXME: C++0x: Track and check trivial move assignment operators.
+  if (!hasTrivialMoveAssignment()) return false;
   //   -- has a trivial destructor.
   if (!hasTrivialDestructor()) return false;
 
@@ -374,8 +391,18 @@
       
       // None of the special member functions are trivial.
       data().HasTrivialConstructor = false;
+
+      // C++0x [class.copy]p13:
+      //   A copy/move constructor for class X is trivial if [...]
+      //    -- class X has no virtual functions [...]
       data().HasTrivialCopyConstructor = false;
+      data().HasTrivialMoveConstructor = false;
+
+      // C++0x [class.copy]p27:
+      //   A copy/move assignment operator for class X is trivial if [...]
+      //    -- class X has no virtual functions [...]
       data().HasTrivialCopyAssignment = false;
+      data().HasTrivialMoveAssignment = false;
       // FIXME: Destructor?
     }
   }
@@ -439,18 +466,27 @@
     // FIXME: C++0x: don't do this for "= default" default constructors.
     data().HasTrivialConstructor = false;
 
-    // Note when we have a user-declared copy constructor, which will
-    // suppress the implicit declaration of a copy constructor.
-    if (!FunTmpl && Constructor->isCopyConstructor()) {
-      data().UserDeclaredCopyConstructor = true;
-      data().DeclaredCopyConstructor = true;
-      
-      // C++ [class.copy]p6:
-      //   A copy constructor is trivial if it is implicitly declared.
-      // FIXME: C++0x: don't do this for "= default" copy constructors.
-      data().HasTrivialCopyConstructor = false;
+    // Note when we have a user-declared copy or move constructor, which will
+    // suppress the implicit declaration of those constructors.
+    if (!FunTmpl) {
+      if (Constructor->isCopyConstructor()) {
+        data().UserDeclaredCopyConstructor = true;
+        data().DeclaredCopyConstructor = true;
+
+        // C++0x [class.copy]p13:
+        //   A copy/move constructor for class X is trivial if it is neither
+        //   user-provided nor deleted
+        // FIXME: C++0x: don't do this for "= default" copy constructors.
+        data().HasTrivialCopyConstructor = false;
+      } else if (Constructor->isMoveConstructor()) {
+        // C++0x [class.copy]p13:
+        //   A copy/move constructor for class X is trivial if it is neither
+        //   user-provided nor deleted
+        // FIXME: C++0x: don't do this for "= default" move constructors.
+        data().HasTrivialMoveConstructor = false;
+      }
     }
-    
+
     return;
   }
 
@@ -488,35 +524,53 @@
         return;
       
       ASTContext &Context = getASTContext();
-      QualType ArgType = FnType->getArgType(0);
-      if (const LValueReferenceType *Ref =ArgType->getAs<LValueReferenceType>())
-        ArgType = Ref->getPointeeType();
-      
-      ArgType = ArgType.getUnqualifiedType();
       QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
                                              const_cast<CXXRecordDecl*>(this)));
-      
+
+      bool isRValueRefArg = false;
+      QualType ArgType = FnType->getArgType(0);
+      if (const LValueReferenceType *Ref =
+          ArgType->getAs<LValueReferenceType>()) {
+        ArgType = Ref->getPointeeType();
+      } else if (const RValueReferenceType *Ref =
+               ArgType->getAs<RValueReferenceType>()) {
+        ArgType = Ref->getPointeeType();
+        isRValueRefArg = true;
+      }
       if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
         return;
-      
-      // This is a copy assignment operator.
-      // FIXME: Move assignment operators.
-      
-      // Suppress the implicit declaration of a copy constructor.
-      data().UserDeclaredCopyAssignment = true;
-      data().DeclaredCopyAssignment = true;
-      
-      // C++ [class.copy]p11:
-      //   A copy assignment operator is trivial if it is implicitly declared.
-      // FIXME: C++0x: don't do this for "= default" copy operators.
-      data().HasTrivialCopyAssignment = false;
-      
+
       // C++ [class]p4:
-      //   A POD-struct is an aggregate class that [...] has no user-defined copy
-      //   assignment operator [...].
+      //   A POD-struct is an aggregate class that [...] has no user-defined
+      //   copy assignment operator [...].
+      // FIXME: This should be probably determined dynamically in terms of
+      // other more precise attributes to correctly model how it is specified
+      // in C++0x. Setting it here happens to do the right thing.
       data().PlainOldData = false;
+
+      if (!isRValueRefArg) {
+        // This is a copy assignment operator.
+
+        // Suppress the implicit declaration of a copy constructor.
+        data().UserDeclaredCopyAssignment = true;
+        data().DeclaredCopyAssignment = true;
+
+        // C++0x [class.copy]p27:
+        //   A copy/move assignment operator for class X is trivial if it is
+        //   neither user-provided nor deleted [...]
+        // FIXME: C++0x: don't do this for "= default" copy operators.
+        data().HasTrivialCopyAssignment = false;
+      } else {
+        // This is a move assignment operator.
+
+        // C++0x [class.copy]p27:
+        //   A copy/move assignment operator for class X is trivial if it is
+        //   neither user-provided nor deleted [...]
+        // FIXME: C++0x: don't do this for "= default" copy operators.
+        data().HasTrivialMoveAssignment = false;
+      }
     }
-    
+
     // Keep the list of conversion functions up-to-date.
     if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
       // We don't record specializations.
@@ -556,7 +610,7 @@
       data().PlainOldData = false;
     }
     
-    // C++ [class]p9:
+    // C++0x [class]p9:
     //   A POD struct is a class that is both a trivial class and a 
     //   standard-layout class, and has no non-static data members of type 
     //   non-POD struct, non-POD union (or array of such types).
@@ -572,10 +626,31 @@
       if (FieldRec->getDefinition()) {
         if (!FieldRec->hasTrivialConstructor())
           data().HasTrivialConstructor = false;
+
+        // C++0x [class.copy]p13:
+        //   A copy/move constructor for class X is trivial if [...]
+        //    [...]
+        //    -- for each non-static data member of X that is of class type (or
+        //       an array thereof), the constructor selected to copy/move that
+        //       member is trivial;
+        // FIXME: C++0x: We don't correctly model 'selected' constructors.
         if (!FieldRec->hasTrivialCopyConstructor())
           data().HasTrivialCopyConstructor = false;
+        if (!FieldRec->hasTrivialMoveConstructor())
+          data().HasTrivialMoveConstructor = false;
+
+        // C++0x [class.copy]p27:
+        //   A copy/move assignment operator for class X is trivial if [...]
+        //    [...]
+        //    -- for each non-static data member of X that is of class type (or
+        //       an array thereof), the assignment operator selected to
+        //       copy/move that member is trivial;
+        // FIXME: C++0x: We don't correctly model 'selected' operators.
         if (!FieldRec->hasTrivialCopyAssignment())
           data().HasTrivialCopyAssignment = false;
+        if (!FieldRec->hasTrivialMoveAssignment())
+          data().HasTrivialMoveAssignment = false;
+
         if (!FieldRec->hasTrivialDestructor())
           data().HasTrivialDestructor = false;
       }

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=130076&r1=130075&r2=130076&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sat Apr 23 18:10:33 2011
@@ -843,7 +843,9 @@
   Data.Abstract = Record[Idx++];
   Data.HasTrivialConstructor = Record[Idx++];
   Data.HasTrivialCopyConstructor = Record[Idx++];
+  Data.HasTrivialMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyAssignment = Record[Idx++];
+  Data.HasTrivialMoveAssignment = Record[Idx++];
   Data.HasTrivialDestructor = Record[Idx++];
   Data.ComputedVisibleConversions = Record[Idx++];
   Data.DeclaredDefaultConstructor = Record[Idx++];

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=130076&r1=130075&r2=130076&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sat Apr 23 18:10:33 2011
@@ -3795,7 +3795,9 @@
   Record.push_back(Data.Abstract);
   Record.push_back(Data.HasTrivialConstructor);
   Record.push_back(Data.HasTrivialCopyConstructor);
+  Record.push_back(Data.HasTrivialMoveConstructor);
   Record.push_back(Data.HasTrivialCopyAssignment);
+  Record.push_back(Data.HasTrivialMoveAssignment);
   Record.push_back(Data.HasTrivialDestructor);
   Record.push_back(Data.ComputedVisibleConversions);
   Record.push_back(Data.DeclaredDefaultConstructor);

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=130076&r1=130075&r2=130076&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Sat Apr 23 18:10:33 2011
@@ -35,6 +35,8 @@
 struct DerivesEmpty : Empty {};
 struct HasCons { HasCons(int); };
 struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); };
+struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; // \
+    // expected-warning {{rvalue references}}
 struct HasDest { ~HasDest(); };
 class  HasPriv { int priv; };
 class  HasProt { protected: int prot; };
@@ -47,6 +49,7 @@
 union NonPODUnion { int i; Derives n; };
 struct DerivesHasCons : HasCons {};
 struct DerivesHasCopyAssign : HasCopyAssign {};
+struct DerivesHasMoveAssign : HasMoveAssign {};
 struct DerivesHasDest : HasDest {};
 struct DerivesHasPriv : HasPriv {};
 struct DerivesHasProt : HasProt {};
@@ -108,6 +111,7 @@
   { int arr[F(__is_pod(DerivesEmpty))]; }
   { int arr[F(__is_pod(HasCons))]; }
   { int arr[F(__is_pod(HasCopyAssign))]; }
+  { int arr[F(__is_pod(HasMoveAssign))]; }
   { int arr[F(__is_pod(HasDest))]; }
   { int arr[F(__is_pod(HasPriv))]; }
   { int arr[F(__is_pod(HasProt))]; }
@@ -115,6 +119,7 @@
   { int arr[F(__is_pod(HasVirt))]; }
   { int arr[F(__is_pod(DerivesHasCons))]; }
   { int arr[F(__is_pod(DerivesHasCopyAssign))]; }
+  { int arr[F(__is_pod(DerivesHasMoveAssign))]; }
   { int arr[F(__is_pod(DerivesHasDest))]; }
   { int arr[F(__is_pod(DerivesHasPriv))]; }
   { int arr[F(__is_pod(DerivesHasProt))]; }
@@ -141,6 +146,7 @@
   { int arr[T(__is_empty(DerivesEmpty))]; }
   { int arr[T(__is_empty(HasCons))]; }
   { int arr[T(__is_empty(HasCopyAssign))]; }
+  { int arr[T(__is_empty(HasMoveAssign))]; }
   { int arr[T(__is_empty(HasDest))]; }
   { int arr[T(__is_empty(HasFunc))]; }
   { int arr[T(__is_empty(HasOp))]; }
@@ -246,6 +252,10 @@
   HasCopy(HasCopy& cp);
 };
 
+struct HasMove {
+  HasMove(HasMove&& cp); // expected-warning {{rvalue references}}
+};
+
 struct HasTemplateCons {
   HasVirt Annoying;
 
@@ -266,6 +276,7 @@
   { int arr[T(__has_trivial_constructor(HasDest))]; }
   { int arr[T(__has_trivial_constructor(HasPriv))]; }
   { int arr[T(__has_trivial_constructor(HasCopyAssign))]; }
+  { int arr[T(__has_trivial_constructor(HasMoveAssign))]; }
   { int arr[T(__has_trivial_constructor(const Int))]; }
 
   { int arr[F(__has_trivial_constructor(HasCons))]; }
@@ -291,8 +302,10 @@
   { int arr[T(__has_trivial_copy(HasPriv))]; }
   { int arr[T(__has_trivial_copy(HasCons))]; }
   { int arr[T(__has_trivial_copy(HasRef))]; }
+  { int arr[T(__has_trivial_copy(HasMove))]; }
   { int arr[T(__has_trivial_copy(IntRef))]; }
   { int arr[T(__has_trivial_copy(HasCopyAssign))]; }
+  { int arr[T(__has_trivial_copy(HasMoveAssign))]; }
   { int arr[T(__has_trivial_copy(const Int))]; }
 
   { int arr[F(__has_trivial_copy(HasCopy))]; }
@@ -315,6 +328,8 @@
   { int arr[T(__has_trivial_assign(HasCons))]; }
   { int arr[T(__has_trivial_assign(HasRef))]; }
   { int arr[T(__has_trivial_assign(HasCopy))]; }
+  { int arr[T(__has_trivial_assign(HasMove))]; }
+  { int arr[T(__has_trivial_assign(HasMoveAssign))]; }
 
   { int arr[F(__has_trivial_assign(IntRef))]; }
   { int arr[F(__has_trivial_assign(HasCopyAssign))]; }
@@ -340,8 +355,10 @@
   { int arr[T(__has_trivial_destructor(HasCons))]; }
   { int arr[T(__has_trivial_destructor(HasRef))]; }
   { int arr[T(__has_trivial_destructor(HasCopy))]; }
+  { int arr[T(__has_trivial_destructor(HasMove))]; }
   { int arr[T(__has_trivial_destructor(IntRef))]; }
   { int arr[T(__has_trivial_destructor(HasCopyAssign))]; }
+  { int arr[T(__has_trivial_destructor(HasMoveAssign))]; }
   { int arr[T(__has_trivial_destructor(const Int))]; }
   { int arr[T(__has_trivial_destructor(DerivesAr))]; }
   { int arr[T(__has_trivial_destructor(VirtAr))]; }
@@ -371,6 +388,8 @@
   { int arr[T(__has_nothrow_assign(HasCons))]; }
   { int arr[T(__has_nothrow_assign(HasRef))]; }
   { int arr[T(__has_nothrow_assign(HasCopy))]; }
+  { int arr[T(__has_nothrow_assign(HasMove))]; }
+  { int arr[T(__has_nothrow_assign(HasMoveAssign))]; }
   { int arr[T(__has_nothrow_assign(HasNoThrowCopyAssign))]; }
   { int arr[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))]; }
   { int arr[T(__has_nothrow_assign(HasVirtDest))]; }
@@ -402,7 +421,9 @@
   { int arr[T(__has_nothrow_copy(HasPriv))]; }
   { int arr[T(__has_nothrow_copy(HasCons))]; }
   { int arr[T(__has_nothrow_copy(HasRef))]; }
+  { int arr[T(__has_nothrow_copy(HasMove))]; }
   { int arr[T(__has_nothrow_copy(HasCopyAssign))]; }
+  { int arr[T(__has_nothrow_copy(HasMoveAssign))]; }
   { int arr[T(__has_nothrow_copy(HasNoThrowCopy))]; }
   { int arr[T(__has_nothrow_copy(HasMultipleNoThrowCopy))]; }
   { int arr[T(__has_nothrow_copy(HasVirtDest))]; }
@@ -437,6 +458,7 @@
   { int arr[F(__has_nothrow_constructor(HasCons))]; }
   { int arr[F(__has_nothrow_constructor(HasRef))]; }
   { int arr[F(__has_nothrow_constructor(HasCopy))]; }
+  { int arr[F(__has_nothrow_constructor(HasMove))]; }
   { int arr[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))]; }
   { int arr[F(__has_nothrow_constructor(IntRef))]; }
   { int arr[F(__has_nothrow_constructor(void))]; }
@@ -460,7 +482,9 @@
   { int arr[F(__has_virtual_destructor(HasCons))]; }
   { int arr[F(__has_virtual_destructor(HasRef))]; }
   { int arr[F(__has_virtual_destructor(HasCopy))]; }
+  { int arr[F(__has_virtual_destructor(HasMove))]; }
   { int arr[F(__has_virtual_destructor(HasCopyAssign))]; }
+  { int arr[F(__has_virtual_destructor(HasMoveAssign))]; }
   { int arr[F(__has_virtual_destructor(IntRef))]; }
   { int arr[F(__has_virtual_destructor(VirtAr))]; }
 
@@ -599,12 +623,14 @@
 
   { int arr[F(__is_trivial(HasCons))]; }
   { int arr[F(__is_trivial(HasCopyAssign))]; }
+  { int arr[F(__is_trivial(HasMoveAssign))]; }
   { int arr[F(__is_trivial(HasDest))]; }
   { int arr[F(__is_trivial(HasRef))]; }
   { int arr[F(__is_trivial(HasNonPOD))]; }
   { int arr[F(__is_trivial(HasVirt))]; }
   { int arr[F(__is_trivial(DerivesHasCons))]; }
   { int arr[F(__is_trivial(DerivesHasCopyAssign))]; }
+  { int arr[F(__is_trivial(DerivesHasMoveAssign))]; }
   { int arr[F(__is_trivial(DerivesHasDest))]; }
   { int arr[F(__is_trivial(DerivesHasRef))]; }
   { int arr[F(__is_trivial(DerivesHasVirt))]; }





More information about the cfe-commits mailing list