r178111 - Implement compiler intrinsics needed for compatibility with MSVC 2012 <type_traits>.
Joao Matos
ripzonetriton at gmail.com
Tue Mar 26 18:34:17 PDT 2013
Author: triton
Date: Tue Mar 26 20:34:16 2013
New Revision: 178111
URL: http://llvm.org/viewvc/llvm-project?rev=178111&view=rev
Log:
Implement compiler intrinsics needed for compatibility with MSVC 2012 <type_traits>.
Patch by me and Ryan Molden.
Modified:
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/include/clang/Basic/TypeTraits.h
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/type-traits.cpp
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Tue Mar 26 20:34:16 2013
@@ -351,31 +351,34 @@ KEYWORD(typeof , KE
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)
Modified: cfe/trunk/include/clang/Basic/TypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TypeTraits.h (original)
+++ cfe/trunk/include/clang/Basic/TypeTraits.h Tue Mar 26 20:34:16 2013
@@ -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,
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Mar 26 20:34:16 2013
@@ -1558,9 +1558,12 @@ void StmtPrinter::VisitUnresolvedMemberE
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";
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Mar 26 20:34:16 2013
@@ -1188,10 +1188,13 @@ ExprResult Parser::ParseCastExpression(b
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:
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Mar 26 20:34:16 2013
@@ -2511,11 +2511,15 @@ static UnaryTypeTrait UnaryTypeTraitFrom
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;
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar 26 20:34:16 2013
@@ -2975,10 +2975,13 @@ static bool CheckUnaryTypeTraitTypeCompl
// 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:
@@ -2997,6 +3000,42 @@ static bool CheckUnaryTypeTraitTypeCompl
llvm_unreachable("Type trait not handled by switch");
}
+static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
+ Sema &Self, SourceLocation KeyLoc, ASTContext &C,
+ bool (CXXRecordDecl::*HasTrivial)() const,
+ bool (CXXRecordDecl::*HasNonTrivial)() const,
+ bool (CXXMethodDecl::*IsDesiredOp)() const)
+{
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())
+ return true;
+
+ DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op);
+ DeclarationNameInfo NameInfo(Name, KeyLoc);
+ LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName);
+ if (Self.LookupQualifiedName(Res, RD)) {
+ bool FoundOperator = false;
+ 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->*IsDesiredOp)()) {
+ FoundOperator = true;
+ const FunctionProtoType *CPT =
+ Operator->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT || !CPT->isNothrow(Self.Context))
+ return false;
+ }
+ }
+ return FoundOperator;
+ }
+ return false;
+}
+
static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
SourceLocation KeyLoc, QualType T) {
assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
@@ -3133,6 +3172,15 @@ static bool EvaluateUnaryTypeTrait(Sema
return RD->hasTrivialDefaultConstructor() &&
!RD->hasNonTrivialDefaultConstructor();
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::is_trivially_move_constructible (20.9.4.3).
+ if (T.isPODType(Self.Context))
+ return true;
+ if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
+ return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor();
+ 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
@@ -3145,6 +3193,15 @@ static bool EvaluateUnaryTypeTrait(Sema
return RD->hasTrivialCopyConstructor() &&
!RD->hasNonTrivialCopyConstructor();
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 (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
+ return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment();
+ 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
@@ -3198,38 +3255,26 @@ static bool EvaluateUnaryTypeTrait(Sema
if (T->isReferenceType())
return false;
if (T.isPODType(Self.Context) || T->isObjCLifetimeType())
- return true;
- if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
- if (RD->hasTrivialCopyAssignment() && !RD->hasNonTrivialCopyAssignment())
- return true;
+ 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->isCopyAssignmentOperator()) {
- 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;
- }
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C,
+ &CXXRecordDecl::hasTrivialCopyAssignment,
+ &CXXRecordDecl::hasNonTrivialCopyAssignment,
+ &CXXMethodDecl::isCopyAssignmentOperator);
+ 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>())
+ return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C,
+ &CXXRecordDecl::hasTrivialMoveAssignment,
+ &CXXRecordDecl::hasNonTrivialMoveAssignment,
+ &CXXMethodDecl::isMoveAssignmentOperator);
return false;
case UTT_HasNothrowCopy:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=178111&r1=178110&r2=178111&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Tue Mar 26 20:34:16 2013
@@ -39,9 +39,34 @@ struct DerivesEmpty : Empty {};
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;
+ HasDefaultTrivialCopyAssign &operator=(
+ const HasDefaultTrivialCopyAssign&) = default;
};
struct TrivialMoveButNotCopy {
TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default;
@@ -69,6 +94,7 @@ struct DerivesHasPriv : HasPriv {};
struct DerivesHasProt : HasProt {};
struct DerivesHasRef : HasRef {};
struct DerivesHasVirt : HasVirt {};
+struct DerivesHasMoveCtor : HasMoveCtor {};
struct HasNoThrowCopyAssign {
void operator =(const HasNoThrowCopyAssign&) throw();
@@ -165,7 +191,7 @@ typedef Empty EmptyAr[10];
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()
{
@@ -941,6 +967,19 @@ struct AllDefaulted {
~AllDefaulted() = default;
};
+struct NoDefaultMoveAssignDueToUDCopyCtor {
+ NoDefaultMoveAssignDueToUDCopyCtor(const NoDefaultMoveAssignDueToUDCopyCtor&);
+};
+
+struct NoDefaultMoveAssignDueToUDCopyAssign {
+ NoDefaultMoveAssignDueToUDCopyAssign& operator=(
+ const NoDefaultMoveAssignDueToUDCopyAssign&);
+};
+
+struct NoDefaultMoveAssignDueToDtor {
+ ~NoDefaultMoveAssignDueToDtor();
+};
+
struct AllDeleted {
AllDeleted() = delete;
AllDeleted(const AllDeleted &) = delete;
@@ -1203,6 +1242,32 @@ void has_trivial_default_constructor() {
{ 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[T(__has_trivial_move_constructor(AllDeleted))]; }
+
+ { 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))]; }
@@ -1355,6 +1420,54 @@ void has_nothrow_assign() {
{ 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[T(__has_nothrow_move_assign(AllDeleted))]; }
+
+
+ { 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))]; }
+ { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor))]; }
+ { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign))]; }
+ { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToDtor))]; }
+}
+
+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(HasStaticMemberMoveAssign))]; }
+ { int arr[T(__has_trivial_move_assign(AllDeleted))]; }
+
+ { 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))]; }
+ { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor))]; }
+ { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign))]; }
+}
+
void has_nothrow_copy() {
{ int arr[T(__has_nothrow_copy(Int))]; }
{ int arr[T(__has_nothrow_copy(IntAr))]; }
More information about the cfe-commits
mailing list