[PATCH] MSVC 2013 type trait support
Alp Toker
alp at nuanti.com
Thu Dec 12 09:13:10 PST 2013
This patch adds support for the MSVC12.0 / 2013 type trait builtin
primitives sufficiently to support the new type_trait facilities added
to the C++ standard library.
With these clang is now more or less able to parse itself with the
Visual Studio 2013 SDK.
Fully Implemented:
* __is_constructible()
* __is_nothrow_constructible()
Implemented through fallback to other type traits (WIP, noted with two
TODOs):
* __is_destructible()
* __is_nothrow_destructible()
* __is_nothrow_assignable()
The patch is built on top of the other two posted earlier today unifying
(1) contextual keywords and (2) the new type traits implementation.
Alp.
--
http://www.nuanti.com
the browser experts
-------------- next part --------------
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index faafdba..19a250f 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -368,6 +368,13 @@ KEYWORD(L__FUNCTION__ , KEYMS)
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, KEYMS)
+TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYMS)
+TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYMS)
+
// GNU and MS Type Traits
TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX)
TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index fc53527..7a70ea2 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -37,6 +37,7 @@ namespace clang {
UTT_IsCompleteType,
UTT_IsCompound,
UTT_IsConst,
+ UTT_IsDestructible,
UTT_IsEmpty,
UTT_IsEnum,
UTT_IsFinal,
@@ -50,6 +51,7 @@ namespace clang {
UTT_IsMemberFunctionPointer,
UTT_IsMemberObjectPointer,
UTT_IsMemberPointer,
+ UTT_IsNothrowDestructible,
UTT_IsObject,
UTT_IsPOD,
UTT_IsPointer,
@@ -73,6 +75,7 @@ namespace clang {
BTT_IsBaseOf,
BTT_IsConvertible,
BTT_IsConvertibleTo,
+ BTT_IsNothrowAssignable,
BTT_IsSame,
BTT_TypeCompatible,
BTT_IsTriviallyAssignable
@@ -93,6 +96,8 @@ namespace clang {
/// \brief Names for type traits that operate specifically on types.
enum TypeTrait {
+ TT_IsConstructible,
+ TT_IsNothrowConstructible,
TT_IsTriviallyConstructible
};
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 2c9eb63..5804e71 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -3171,6 +3171,8 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
// These traits require a complete type.
case UTT_IsFinal:
case UTT_IsSealed:
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
// These trait expressions are designed to help implement predicates in
// [meta.unary.prop] despite not being named the same. They are specified
@@ -3431,6 +3433,10 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
return RD->hasTrivialCopyAssignment() &&
!RD->hasNonTrivialCopyAssignment();
return false;
+ case UTT_IsDestructible:
+ case UTT_IsNothrowDestructible:
+ // TODO: Implement UTT_IsDestructible and UTT_IsNothrowDestructible.
+ // For now, let's fall through.
case UTT_HasTrivialDestructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true or type is a reference type
@@ -3636,6 +3642,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation 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:
@@ -3699,15 +3707,35 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
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;
- // The initialization succeeded; now make sure there are no non-trivial
- // calls.
- return !Result.get()->hasNonTrivialCall(S.Context);
+ if (Kind == clang::TT_IsNothrowConstructible &&
+ isa<CXXConstructExpr>(Result.get())) {
+ CXXConstructExpr *CE = cast<CXXConstructExpr>(Result.get());
+ CXXConstructorDecl *Constructor = CE->getConstructor();
+ const FunctionProtoType *CPT =
+ Constructor->getType()->getAs<FunctionProtoType>();
+ CPT = S.ResolveExceptionSpec(KWLoc, CPT);
+ if (CPT && CPT->isNothrow(S.Context))
+ return true;
+ }
+
+ if (Kind == clang::TT_IsTriviallyConstructible ||
+ Kind == clang::TT_IsNothrowConstructible) {
+ // 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;
}
}
@@ -3856,7 +3884,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
}
-
+
+ case BTT_IsNothrowAssignable:
+ // TODO: Implement nothrow checking shared with TT_IsNothrowConstructible.
+ // Until then, let's fall back to the trivial assign check.
case BTT_IsTriviallyAssignable: {
// C++11 [meta.unary.prop]p3:
// is_trivially_assignable is defined as:
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index 3e47921..336e5ca 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -1889,6 +1889,19 @@ void trivial_checks()
{ int arr[F((__is_trivially_constructible(class_forward[])))]; }
{ int arr[F((__is_trivially_constructible(void)))]; }
+ { int arr[T(__is_nothrow_constructible(HasNoThrowConstructorWithArgs))]; }
+ { int arr[T(__is_nothrow_constructible(HasNoThrowConstructorWithArgs, HasCons))]; }
+ { int arr[F(__is_nothrow_constructible(NonTrivialDefault))]; }
+ { int arr[T(__is_nothrow_constructible(int))]; }
+ { int arr[F(__is_nothrow_constructible(NonPOD))]; }
+ { int arr[F(__is_nothrow_constructible(NonPOD, int))]; }
+
+ { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs))]; }
+ { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs, HasCons))]; }
+ { int arr[T(__is_constructible(NonTrivialDefault))]; }
+ { int arr[F(__is_constructible(NonPOD))]; }
+ { int arr[T(__is_constructible(NonPOD, int))]; }
+
{ int arr[T((__is_trivially_assignable(int&, int)))]; }
{ int arr[T((__is_trivially_assignable(int&, int&)))]; }
{ int arr[T((__is_trivially_assignable(int&, int&&)))]; }
More information about the cfe-commits
mailing list