diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4692,7 +4692,7 @@ case UTT_IsArray: return T->isArrayType(); case UTT_IsPointer: - return T->isPointerType(); + return T->isAnyPointerType(); case UTT_IsLvalueReference: return T->isLValueReferenceType(); case UTT_IsRvalueReference: diff --git a/clang/test/SemaObjCXX/type-traits-is-pointer.mm b/clang/test/SemaObjCXX/type-traits-is-pointer.mm new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjCXX/type-traits-is-pointer.mm @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -verify %s +// expected-no-diagnostics + +template +void test_is_pointer() { + static_assert(__is_pointer(T), ""); + + static_assert(__is_pointer(T __weak), ""); + static_assert(__is_pointer(T __strong), ""); + static_assert(__is_pointer(T __autoreleasing), ""); + static_assert(__is_pointer(T __unsafe_unretained), ""); + + static_assert(__is_pointer(T __weak const), ""); + static_assert(__is_pointer(T __strong const), ""); + static_assert(__is_pointer(T __autoreleasing const), ""); + static_assert(__is_pointer(T __unsafe_unretained const), ""); + + static_assert(__is_pointer(T __weak volatile), ""); + static_assert(__is_pointer(T __strong volatile), ""); + static_assert(__is_pointer(T __autoreleasing volatile), ""); + static_assert(__is_pointer(T __unsafe_unretained volatile), ""); + + static_assert(__is_pointer(T __weak const volatile), ""); + static_assert(__is_pointer(T __strong const volatile), ""); + static_assert(__is_pointer(T __autoreleasing const volatile), ""); + static_assert(__is_pointer(T __unsafe_unretained const volatile), ""); +} + +@class Foo; + +int main(int, char**) { + test_is_pointer(); + test_is_pointer(); + test_is_pointer(); + test_is_pointer(); + + test_is_pointer(); + test_is_pointer(); + test_is_pointer(); + test_is_pointer(); + + test_is_pointer(); + test_is_pointer(); + test_is_pointer(); + test_is_pointer(); + + return 0; +} diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -897,6 +897,19 @@ // is_pointer +// In clang 10.0.0 and earlier __is_pointer didn't work with Objective-C types. +#if __has_keyword(__is_pointer) && _LIBCPP_CLANG_VER > 1000 + +template +struct _LIBCPP_TEMPLATE_VIS is_pointer : _BoolConstant<__is_pointer(_Tp)> { }; + +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) +template +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_pointer_v = __is_pointer(_Tp); +#endif + +#else // __has_keyword(__is_pointer) + template struct __libcpp_is_pointer : public false_type {}; template struct __libcpp_is_pointer<_Tp*> : public true_type {}; @@ -917,6 +930,8 @@ = is_pointer<_Tp>::value; #endif +#endif // __has_keyword(__is_pointer) + // is_reference #if __has_keyword(__is_lvalue_reference) && \