TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
+// MSVC12.0 / VS2013 Type Traits
+TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS)
+TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYMS)
+TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX)
+TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX)
+TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX)
+
// GNU and MS Type Traits
TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
case UTT_IsPolymorphic:
case UTT_IsAbstract:
case UTT_IsInterfaceClass:
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
// Fall-through
// These traits require a complete type.
const FunctionProtoType *CPT =
Operator->getType()->getAs<FunctionProtoType>();
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
- if (!CPT || !CPT->isNothrow(Self.Context))
+ if (!CPT || !CPT->isNothrow(C))
return false;
}
}
return RD->hasTrivialCopyAssignment() &&
!RD->hasNonTrivialCopyAssignment();
return false;
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
+ // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
+ // For now, let's fall through.
case UTT_HasTrivialDestructor:
- // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
// If __is_pod (type) is true or type is a reference type
// then the trait is true, else if type is a cv class or union
// type (or array thereof) with a trivial destructor
CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
if (!CPT)
return false;
- // FIXME: check whether evaluating default arguments can throw.
+ // TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw.
if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
return false;
Args[1]->getType(), RParenLoc);
switch (Kind) {
+ case clang::TT_IsConstructible:
+ case clang::TT_IsNothrowConstructible:
case clang::TT_IsTriviallyConstructible: {
// C++11 [meta.unary.prop]:
// is_trivially_constructible is defined as:
InitializationSequence Init(S, To, InitKind, ArgExprs);
if (Init.Failed())
return false;
-
+
ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs);
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
- // Under Objective-C ARC, if the destination has non-trivial Objective-C
- // lifetime, this is a non-trivial construction.
- if (S.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
- return false;
+ if (Kind == clang::TT_IsConstructible)
+ return true;
+
+ if (Kind == clang::TT_IsNothrowConstructible)
+ return S.canThrow(Result.get()) == CT_Cannot;
- // The initialization succeeded; now make sure there are no non-trivial
- // calls.
- return !Result.get()->hasNonTrivialCall(S.Context);
+ if (Kind == clang::TT_IsTriviallyConstructible) {
+ // Under Objective-C ARC, if the destination has non-trivial Objective-C
+ // lifetime, this is a non-trivial construction.
+ if (S.getLangOpts().ObjCAutoRefCount &&
+ hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType()))
+ return false;
+
+ // The initialization succeeded; now make sure there are no non-trivial
+ // calls.
+ return !Result.get()->hasNonTrivialCall(S.Context);
+ }
+
+ llvm_unreachable("unhandled type trait");
+ return false;
}
default: llvm_unreachable("not a TT");
}
ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
}
-
+
+ case BTT_IsNothrowAssignable:
case BTT_IsTriviallyAssignable: {
// C++11 [meta.unary.prop]p3:
// is_trivially_assignable is defined as:
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;
- // Under Objective-C ARC, if the destination has non-trivial Objective-C
- // lifetime, this is a non-trivial assignment.
- if (Self.getLangOpts().ObjCAutoRefCount &&
- hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
- return false;
+ if (BTT == BTT_IsNothrowAssignable)
+ return Self.canThrow(Result.get()) == CT_Cannot;
- return !Result.get()->hasNonTrivialCall(Self.Context);
+ if (BTT == BTT_IsTriviallyAssignable) {
+ // Under Objective-C ARC, if the destination has non-trivial Objective-C
+ // lifetime, this is a non-trivial assignment.
+ if (Self.getLangOpts().ObjCAutoRefCount &&
+ hasNontrivialObjCLifetime(LhsT.getNonReferenceType()))
+ return false;
+
+ return !Result.get()->hasNonTrivialCall(Self.Context);
+ }
+
+ llvm_unreachable("unhandled type trait");
+ return false;
}
default: llvm_unreachable("not a BTT");
}
template <class _Tp> _Tp&& declval() noexcept;
template <class _Tp, class... _Args>
-struct __is_nothrow_constructible
+struct _is_nothrow_constructible
{
static const bool value = noexcept(_Tp(declval<_Args>()...));
};
typedef _Allocator allocator_type;
basic_string()
- noexcept(__is_nothrow_constructible<allocator_type>::value);
+ noexcept(_is_nothrow_constructible<allocator_type>::value);
};
template <class, class, class _Compare>
{
public:
__map_value_compare()
- noexcept(__is_nothrow_constructible<_Compare>::value);
+ noexcept(_is_nothrow_constructible<_Compare>::value);
};
struct less
template<class T, class _Traits, class _Allocator>
-basic_string<T, _Traits, _Allocator>::basic_string() noexcept(__is_nothrow_constructible<allocator_type>::value) {}
+basic_string<T, _Traits, _Allocator>::basic_string() noexcept(_is_nothrow_constructible<allocator_type>::value) {}
template <class T, class Value, class _Compare>
__map_value_compare<T, Value, _Compare>::__map_value_compare()
- noexcept(__is_nothrow_constructible<_Compare>::value) {}
+ noexcept(_is_nothrow_constructible<_Compare>::value) {}
} // std
{ int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor))]; }
{ int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign))]; }
{ int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToDtor))]; }
+
+
+ { int arr[T(__is_nothrow_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign))]; }
+ { int arr[F(__is_nothrow_assignable(HasThrowMoveAssign, HasThrowMoveAssign))]; }
}
void has_trivial_move_assign() {
TrivialMoveButNotCopy&&)))]; }
}
+void constructible_checks() {
+ { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs))]; }
+ { int arr[F(__is_nothrow_constructible(HasNoThrowConstructorWithArgs))]; } // MSVC doesn't look into default args and gets this wrong.
+
+ { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs, HasCons))]; }
+ { int arr[T(__is_nothrow_constructible(HasNoThrowConstructorWithArgs, HasCons))]; }
+
+ { int arr[T(__is_constructible(NonTrivialDefault))]; }
+ { int arr[F(__is_nothrow_constructible(NonTrivialDefault))]; }
+
+ { int arr[T(__is_constructible(int))]; }
+ { int arr[T(__is_nothrow_constructible(int))]; }
+
+ { int arr[F(__is_constructible(NonPOD))]; }
+ { int arr[F(__is_nothrow_constructible(NonPOD))]; }
+
+ { int arr[T(__is_constructible(NonPOD, int))]; }
+ { int arr[F(__is_nothrow_constructible(NonPOD, int))]; }
+}
+
// Instantiation of __is_trivially_constructible
template<typename T, typename ...Args>
struct is_trivially_constructible {