Author: majnemer Date: Mon May 23 12:21:55 2016 New Revision: 270458 URL: http://llvm.org/viewvc/llvm-project?rev=270458&view=rev Log: Clang support for __is_assignable intrinsic
MSVC now supports the __is_assignable type trait intrinsic, to enable easier and more efficient implementation of the Standard Library's is_assignable trait. As of Visual Studio 2015 Update 3, the VC Standard Library implementation uses the new intrinsic unconditionally. The implementation is pretty straightforward due to the previously existing is_nothrow_assignable and is_trivially_assignable. We handle __is_assignable via the same code as the other two except that we skip the extra checks for nothrow or triviality. Patch by Dave Bartolomeo! Differential Revision: http://reviews.llvm.org/D20492 Modified: cfe/trunk/docs/LanguageExtensions.rst cfe/trunk/include/clang/Basic/TokenKinds.def cfe/trunk/include/clang/Basic/TypeTraits.h cfe/trunk/lib/Lex/PPMacroExpansion.cpp cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Parse/ParseExpr.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/Lexer/has_feature_type_traits.cpp cfe/trunk/test/PCH/cxx-traits.cpp cfe/trunk/test/PCH/cxx-traits.h cfe/trunk/test/SemaCXX/type-traits.cpp Modified: cfe/trunk/docs/LanguageExtensions.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/docs/LanguageExtensions.rst (original) +++ cfe/trunk/docs/LanguageExtensions.rst Mon May 23 12:21:55 2016 @@ -1022,6 +1022,7 @@ The following type trait primitives are * ``__is_nothrow_assignable`` (MSVC 2013, clang) * ``__is_constructible`` (MSVC 2013, clang) * ``__is_nothrow_constructible`` (MSVC 2013, clang) +* ``__is_assignable`` (MSVC 2015, clang) Blocks ====== Modified: cfe/trunk/include/clang/Basic/TokenKinds.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TokenKinds.def (original) +++ cfe/trunk/include/clang/Basic/TokenKinds.def Mon May 23 12:21:55 2016 @@ -407,6 +407,9 @@ TYPE_TRAIT_2(__is_nothrow_assignable, Is TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX) TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX) +// MSVC14.0 / VS2015 Type Traits +TYPE_TRAIT_2(__is_assignable, IsAssignable, KEYCXX) + // GNU and MS Type Traits TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX) TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX) Modified: cfe/trunk/include/clang/Basic/TypeTraits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TypeTraits.h (original) +++ cfe/trunk/include/clang/Basic/TypeTraits.h Mon May 23 12:21:55 2016 @@ -74,6 +74,7 @@ namespace clang { BTT_IsConvertibleTo, BTT_IsSame, BTT_TypeCompatible, + BTT_IsAssignable, BTT_IsNothrowAssignable, BTT_IsTriviallyAssignable, BTT_Last = BTT_IsTriviallyAssignable, Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Mon May 23 12:21:55 2016 @@ -1196,6 +1196,7 @@ static bool HasFeature(const Preprocesso .Case("has_trivial_destructor", LangOpts.CPlusPlus) .Case("has_virtual_destructor", LangOpts.CPlusPlus) .Case("is_abstract", LangOpts.CPlusPlus) + .Case("is_assignable", LangOpts.CPlusPlus) .Case("is_base_of", LangOpts.CPlusPlus) .Case("is_class", LangOpts.CPlusPlus) .Case("is_constructible", LangOpts.CPlusPlus) Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon May 23 12:21:55 2016 @@ -1269,6 +1269,7 @@ void Parser::ParseClassSpecifier(tok::To Tok.isOneOf(tok::kw___is_abstract, tok::kw___is_arithmetic, tok::kw___is_array, + tok::kw___is_assignable, tok::kw___is_base_of, tok::kw___is_class, tok::kw___is_complete_type, Modified: cfe/trunk/lib/Parse/ParseExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp (original) +++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon May 23 12:21:55 2016 @@ -796,6 +796,7 @@ ExprResult Parser::ParseCastExpression(b REVERTIBLE_TYPE_TRAIT(__is_abstract); REVERTIBLE_TYPE_TRAIT(__is_arithmetic); REVERTIBLE_TYPE_TRAIT(__is_array); + REVERTIBLE_TYPE_TRAIT(__is_assignable); REVERTIBLE_TYPE_TRAIT(__is_base_of); REVERTIBLE_TYPE_TRAIT(__is_class); REVERTIBLE_TYPE_TRAIT(__is_complete_type); Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon May 23 12:21:55 2016 @@ -4459,6 +4459,7 @@ static bool EvaluateBinaryTypeTrait(Sema return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } + case BTT_IsAssignable: case BTT_IsNothrowAssignable: case BTT_IsTriviallyAssignable: { // C++11 [meta.unary.prop]p3: @@ -4506,6 +4507,9 @@ static bool EvaluateBinaryTypeTrait(Sema if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; + if (BTT == BTT_IsAssignable) + return true; + if (BTT == BTT_IsNothrowAssignable) return Self.canThrow(Result.get()) == CT_Cannot; Modified: cfe/trunk/test/Lexer/has_feature_type_traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/has_feature_type_traits.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/test/Lexer/has_feature_type_traits.cpp (original) +++ cfe/trunk/test/Lexer/has_feature_type_traits.cpp Mon May 23 12:21:55 2016 @@ -45,6 +45,11 @@ int is_abstract(); #endif // CHECK: int is_abstract(); +#if __has_feature(is_assignable) +int is_assignable(); +#endif +// CHECK: int is_assignable(); + #if __has_feature(is_base_of) int is_base_of(); #endif Modified: cfe/trunk/test/PCH/cxx-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx-traits.cpp (original) +++ cfe/trunk/test/PCH/cxx-traits.cpp Mon May 23 12:21:55 2016 @@ -18,6 +18,7 @@ bool copy_construct_int = n::is_triviall bool _is_abstract_result = __is_abstract(int); bool _is_arithmetic_result = __is_arithmetic(int); bool _is_array_result = __is_array(int); +bool _is_assignable_result = __is_assignable(int, int); bool _is_base_of_result = __is_base_of(int, int); bool _is_class_result = __is_class(int); bool _is_complete_type_result = __is_complete_type(int); Modified: cfe/trunk/test/PCH/cxx-traits.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.h?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/test/PCH/cxx-traits.h (original) +++ cfe/trunk/test/PCH/cxx-traits.h Mon May 23 12:21:55 2016 @@ -20,6 +20,7 @@ struct is_trivially_constructible { struct __is_abstract {}; // expected-warning {{made available}} struct __is_arithmetic {}; // expected-warning {{made available}} struct __is_array {}; // expected-warning {{made available}} +struct __is_assignable {}; // expected-warning {{made available}} struct __is_base_of {}; // expected-warning {{made available}} struct __is_class {}; // expected-warning {{made available}} struct __is_complete_type {}; // expected-warning {{made available}} Modified: cfe/trunk/test/SemaCXX/type-traits.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=270458&r1=270457&r2=270458&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/type-traits.cpp (original) +++ cfe/trunk/test/SemaCXX/type-traits.cpp Mon May 23 12:21:55 2016 @@ -1514,6 +1514,9 @@ void has_nothrow_move_assign() { { int arr[T(__is_nothrow_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign))]; } { int arr[F(__is_nothrow_assignable(HasThrowMoveAssign, HasThrowMoveAssign))]; } + + { int arr[T(__is_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign))]; } + { int arr[T(__is_assignable(HasThrowMoveAssign, HasThrowMoveAssign))]; } } void has_trivial_move_assign() { @@ -1974,6 +1977,46 @@ void trivial_checks() TrivialMoveButNotCopy)))]; } { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&, TrivialMoveButNotCopy&&)))]; } + { int arr[T((__is_trivially_assignable(int&, int)))]; } + { int arr[T((__is_trivially_assignable(int&, int&)))]; } + { int arr[T((__is_trivially_assignable(int&, int&&)))]; } + { int arr[T((__is_trivially_assignable(int&, const int&)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD&)))]; } + { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; } + { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; } + { int arr[T((__is_trivially_assignable(int*&, int*)))]; } + { int arr[T((__is_trivially_assignable(AllDefaulted, + const AllDefaulted &)))]; } + { int arr[T((__is_trivially_assignable(AllDefaulted, + AllDefaulted &&)))]; } + + { int arr[F((__is_assignable(int *&, float *)))]; } + { int arr[T((__is_assignable(HasCopyAssign &, HasCopyAssign)))]; } + { int arr[T((__is_assignable(HasCopyAssign &, HasCopyAssign &)))]; } + { int arr[T((__is_assignable(HasCopyAssign &, const HasCopyAssign &)))]; } + { int arr[T((__is_assignable(HasCopyAssign &, HasCopyAssign &&)))]; } + { int arr[T((__is_assignable(TrivialMoveButNotCopy &, + TrivialMoveButNotCopy &)))]; } + { int arr[T((__is_assignable(TrivialMoveButNotCopy &, + const TrivialMoveButNotCopy &)))]; } + { int arr[F((__is_assignable(AllDeleted, + const AllDeleted &)))]; } + { int arr[F((__is_assignable(AllDeleted, + AllDeleted &&)))]; } + { int arr[T((__is_assignable(ExtDefaulted, + const ExtDefaulted &)))]; } + { int arr[T((__is_assignable(ExtDefaulted, + ExtDefaulted &&)))]; } + + { int arr[T((__is_assignable(HasDefaultTrivialCopyAssign &, + HasDefaultTrivialCopyAssign &)))]; } + { int arr[T((__is_assignable(HasDefaultTrivialCopyAssign &, + const HasDefaultTrivialCopyAssign &)))]; } + { int arr[T((__is_assignable(TrivialMoveButNotCopy &, + TrivialMoveButNotCopy)))]; } + { int arr[T((__is_assignable(TrivialMoveButNotCopy &, + TrivialMoveButNotCopy &&)))]; } } void constructible_checks() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits