__invokable and __invoke_of now check for incomplete types and issue a compile-time diagnostic if they are used with incomplete types for anything except a return type. Note that both arguments *and* parameters are checked for completeness.

llvm-svn: 131818
This commit is contained in:
Howard Hinnant 2011-05-22 00:09:02 +00:00
parent a8805fd71a
commit 5eb6bdfa1d
2 changed files with 148 additions and 5 deletions

View File

@ -3586,10 +3586,10 @@ private:
public:
weak_ptr();
template<class _Yp> weak_ptr(shared_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat>::type = __nat());
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0);
weak_ptr(weak_ptr const& __r);
template<class _Yp> weak_ptr(weak_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat>::type = __nat());
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0);
~weak_ptr();
@ -3640,7 +3640,7 @@ template<class _Tp>
template<class _Yp>
inline _LIBCPP_INLINE_VISIBILITY
weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat>::type)
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
{
@ -3652,7 +3652,7 @@ template<class _Tp>
template<class _Yp>
inline _LIBCPP_INLINE_VISIBILITY
weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat>::type)
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
{

View File

@ -845,7 +845,15 @@ struct __type_list
typedef _Tp _Tail;
};
struct __nat {};
struct __nat
{
#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
__nat() = delete;
__nat(const __nat&) = delete;
__nat& operator=(const __nat&) = delete;
~__nat() = delete;
#endif
};
template <class _Tp>
struct __align_type
@ -2775,6 +2783,140 @@ template <class _Tp> struct _LIBCPP_VISIBLE is_trivial
#ifndef _LIBCPP_HAS_NO_VARIADICS
// Check for complete types
template <class ..._T> struct __check_complete;
template <>
struct __check_complete<>
{
};
template <class _H, class _T0, class ..._T>
struct __check_complete<_H, _T0, _T...>
: private __check_complete<_H>,
private __check_complete<_T0, _T...>
{
};
template <class _H>
struct __check_complete<_H, _H>
: private __check_complete<_H>
{
};
template <class _T>
struct __check_complete<_T>
{
static_assert(sizeof(_T) > 0, "Type must be complete.");
};
template <class _T>
struct __check_complete<_T&>
: private __check_complete<_T>
{
};
template <class _T>
struct __check_complete<_T&&>
: private __check_complete<_T>
{
};
template <class _R, class ..._Param>
struct __check_complete<_R (*)(_Param...)>
: private __check_complete<_Param...>
{
};
template <class _R, class ..._Param>
struct __check_complete<_R (_Param...)>
: private __check_complete<_Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...)>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) const>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) volatile>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) const volatile>
: private __check_complete<_Class, _Param...>
{
};
#if __has_feature(cxx_reference_qualified_functions)
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) &>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) const&>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) volatile&>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) const volatile&>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) &&>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) const&&>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) volatile&&>
: private __check_complete<_Class, _Param...>
{
};
template <class _R, class _Class, class ..._Param>
struct __check_complete<_R (_Class::*)(_Param...) const volatile&&>
: private __check_complete<_Class, _Param...>
{
};
#endif
template <class _R, class _Class>
struct __check_complete<_R _Class::*>
: private __check_complete<_Class>
{
};
// __invoke forward declarations
// fall back - none of the bullets
@ -2819,6 +2961,7 @@ __invoke(_F&& __f, _Args&& ...__args)
template <class _F, class ..._Args>
struct __invokable_imp
: private __check_complete<_F, _Args...>
{
typedef decltype(
__invoke(_STD::declval<_F>(), _STD::declval<_Args>()...)