diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index dfd3bd6e2622..946f3a30006b 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -319,28 +319,63 @@ class CXXRecordDecl : public RecordDecl { /// 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 @@ public: 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 @@ public: /// \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 diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 015b49aed6fd..af796d54c4d2 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -32,7 +32,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) 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 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // 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 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 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 @@ bool CXXRecordDecl::isTriviallyCopyable() const { // -- 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 @@ void CXXRecordDecl::addedMember(Decl *D) { // 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 @@ void CXXRecordDecl::addedMember(Decl *D) { // 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 @@ void CXXRecordDecl::addedMember(Decl *D) { return; ASTContext &Context = getASTContext(); - QualType ArgType = FnType->getArgType(0); - if (const LValueReferenceType *Ref =ArgType->getAs()) - ArgType = Ref->getPointeeType(); - - ArgType = ArgType.getUnqualifiedType(); QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( const_cast(this))); - + + bool isRValueRefArg = false; + QualType ArgType = FnType->getArgType(0); + if (const LValueReferenceType *Ref = + ArgType->getAs()) { + ArgType = Ref->getPointeeType(); + } else if (const RValueReferenceType *Ref = + ArgType->getAs()) { + 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(D)) { // We don't record specializations. @@ -556,7 +610,7 @@ void CXXRecordDecl::addedMember(Decl *D) { 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 @@ void CXXRecordDecl::addedMember(Decl *D) { 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; } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 889ef7324c83..a85099d5ef79 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -843,7 +843,9 @@ void ASTDeclReader::ReadCXXDefinitionData( 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++]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 05078cc01206..24a9c66755fc 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3795,7 +3795,9 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec 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); diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 70aec32b088a..fe5be639616e 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -35,6 +35,8 @@ typedef Derives DerivesArNB[]; 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 @@ typedef NonPOD NonPODArNB[]; 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 @@ void is_pod() { 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 @@ void is_pod() { 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 @@ void is_empty() { 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 @@ struct HasCopy { HasCopy(HasCopy& cp); }; +struct HasMove { + HasMove(HasMove&& cp); // expected-warning {{rvalue references}} +}; + struct HasTemplateCons { HasVirt Annoying; @@ -266,6 +276,7 @@ void has_trivial_default_constructor() { { 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 @@ void has_trivial_copy_constructor() { { 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 @@ void has_trivial_copy_assignment() { { 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 @@ void has_trivial_destructor() { { 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 @@ void has_nothrow_assign() { { 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 @@ void has_nothrow_copy() { { 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 @@ void has_nothrow_constructor() { { 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 @@ void has_virtual_destructor() { { 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 @@ void is_trivial() { 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))]; }