[libcxx] r332040 - Fix PR37407 - callable traits don't correctly check complete types.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Thu May 10 13:59:36 PDT 2018


Author: ericwf
Date: Thu May 10 13:59:35 2018
New Revision: 332040

URL: http://llvm.org/viewvc/llvm-project?rev=332040&view=rev
Log:
Fix PR37407 - callable traits don't correctly check complete types.

Checking for complete types is really rather tricky when you consider
the amount of specializations required to check a function type. This
specifically caused PR37407 where we incorrectly diagnosed
noexcept function types as incomplete (but there were plenty of other
cases that would cause this).

This patch removes the complete type checking for now. I'm going
to look into adding a clang builtin to correctly do this for us.

Modified:
    libcxx/trunk/include/type_traits
    libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
    libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp

Modified: libcxx/trunk/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=332040&r1=332039&r2=332040&view=diff
==============================================================================
--- libcxx/trunk/include/type_traits (original)
+++ libcxx/trunk/include/type_traits Thu May 10 13:59:35 2018
@@ -4168,147 +4168,6 @@ template <class _Tp> struct __is_referen
 
 #ifndef _LIBCPP_CXX03_LANG
 
-// Check for complete types
-
-template <class ..._Tp> struct __check_complete;
-
-template <>
-struct __check_complete<>
-{
-};
-
-template <class _Hp, class _T0, class ..._Tp>
-struct __check_complete<_Hp, _T0, _Tp...>
-    : private __check_complete<_Hp>,
-      private __check_complete<_T0, _Tp...>
-{
-};
-
-template <class _Hp>
-struct __check_complete<_Hp, _Hp>
-    : private __check_complete<_Hp>
-{
-};
-
-template <class _Tp>
-struct __check_complete<_Tp>
-{
-    static_assert(sizeof(_Tp) > 0, "Type must be complete.");
-};
-
-template <class _Tp>
-struct __check_complete<_Tp&>
-    : private __check_complete<_Tp>
-{
-};
-
-template <class _Tp>
-struct __check_complete<_Tp&&>
-    : private __check_complete<_Tp>
-{
-};
-
-template <class _Rp, class ..._Param>
-struct __check_complete<_Rp (*)(_Param...)>
-    : private __check_complete<_Rp>
-{
-};
-
-template <class ..._Param>
-struct __check_complete<void (*)(_Param...)>
-{
-};
-
-template <class _Rp, class ..._Param>
-struct __check_complete<_Rp (_Param...)>
-    : private __check_complete<_Rp>
-{
-};
-
-template <class ..._Param>
-struct __check_complete<void (_Param...)>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...)>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) const>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) volatile>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) const volatile>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) &>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) const&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) volatile&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) const volatile&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) &&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) const&&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) volatile&&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class, class ..._Param>
-struct __check_complete<_Rp (_Class::*)(_Param...) const volatile&&>
-    : private __check_complete<_Class>
-{
-};
-
-template <class _Rp, class _Class>
-struct __check_complete<_Rp _Class::*>
-    : private __check_complete<_Class>
-{
-};
-
-
 template <class _Fp, class _A0,
          class _DecayFp = typename decay<_Fp>::type,
          class _DecayA0 = typename decay<_A0>::type,
@@ -4491,8 +4350,9 @@ _LIBCPP_INVOKE_RETURN(_VSTD::forward<_Fp
 
 template <class _Ret, class _Fp, class ..._Args>
 struct __invokable_r
-    : private __check_complete<_Fp>
 {
+    // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void,
+    // or incomplete array types as required by the standard.
     using _Result = decltype(
         _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...));
 

Modified: libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp?rev=332040&r1=332039&r2=332040&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of.pass.cpp Thu May 10 13:59:35 2018
@@ -104,36 +104,43 @@ int main()
     test_result_of<S const volatile&(unsigned char, int&), double const volatile&> ();
     }
     { // pointer to function
-    typedef bool         (&RF0)();
+    typedef bool        (&RF0)();
     typedef bool*       (&RF1)(int);
     typedef bool&       (&RF2)(int, int);
     typedef bool const& (&RF3)(int, int, int);
+    typedef bool        (&RF4)(int, ...);
     typedef bool        (*PF0)();
     typedef bool*       (*PF1)(int);
     typedef bool&       (*PF2)(int, int);
     typedef bool const& (*PF3)(int, int, int);
+    typedef bool        (*PF4)(int, ...);
     typedef bool        (*&PRF0)();
     typedef bool*       (*&PRF1)(int);
     typedef bool&       (*&PRF2)(int, int);
     typedef bool const& (*&PRF3)(int, int, int);
+    typedef bool        (*&PRF4)(int, ...);
     test_result_of<RF0(), bool>();
     test_result_of<RF1(int), bool*>();
     test_result_of<RF2(int, long), bool&>();
     test_result_of<RF3(int, long, int), bool const&>();
+    test_result_of<RF4(int, float, void*), bool>();
     test_result_of<PF0(), bool>();
     test_result_of<PF1(int), bool*>();
     test_result_of<PF2(int, long), bool&>();
     test_result_of<PF3(int, long, int), bool const&>();
+    test_result_of<PF4(int, float, void*), bool>();
     test_result_of<PRF0(), bool>();
     test_result_of<PRF1(int), bool*>();
     test_result_of<PRF2(int, long), bool&>();
     test_result_of<PRF3(int, long, int), bool const&>();
+    test_result_of<PRF4(int, float, void*), bool>();
     }
     { // pointer to member function
 
     typedef int         (S::*PMS0)();
     typedef int*        (S::*PMS1)(long);
     typedef int&        (S::*PMS2)(long, int);
+    typedef const int&  (S::*PMS3)(int, ...);
     test_result_of<PMS0(                             S),   int> ();
     test_result_of<PMS0(                             S&),  int> ();
     test_result_of<PMS0(                             S*),  int> ();
@@ -193,9 +200,13 @@ int main()
     test_no_result<PMS2(std::reference_wrapper<ND>, int, int)>();
     test_no_result<PMS2(std::unique_ptr<ND>,        int, int)>();
 
+    test_result_of<PMS3(S&, int), const int &>();
+    test_result_of<PMS3(S&, int, long), const int &>();
+
     typedef int        (S::*PMS0C)() const;
     typedef int*       (S::*PMS1C)(long) const;
     typedef int&       (S::*PMS2C)(long, int) const;
+    typedef const int& (S::*PMS3C)(int, ...) const;
     test_result_of<PMS0C(               S),   int> ();
     test_result_of<PMS0C(               S&),  int> ();
     test_result_of<PMS0C(const          S&),  int> ();
@@ -238,9 +249,13 @@ int main()
     test_no_result<PMS2C(volatile       S&, int, int)>();
     test_no_result<PMS2C(const volatile S&, int, int)>();
 
+    test_result_of<PMS3C(S&, int), const int &>();
+    test_result_of<PMS3C(S&, int, long), const int &>();
+
     typedef int       (S::*PMS0V)() volatile;
     typedef int*       (S::*PMS1V)(long) volatile;
     typedef int&       (S::*PMS2V)(long, int) volatile;
+    typedef const int& (S::*PMS3V)(int, ...) volatile;
     test_result_of<PMS0V(               S),   int> ();
     test_result_of<PMS0V(               S&),  int> ();
     test_result_of<PMS0V(volatile       S&),  int> ();
@@ -274,9 +289,13 @@ int main()
     test_no_result<PMS2V(const          S&, int, int)>();
     test_no_result<PMS2V(const volatile S&, int, int)>();
 
+    test_result_of<PMS3V(S&, int), const int &>();
+    test_result_of<PMS3V(S&, int, long), const int &>();
+
     typedef int        (S::*PMS0CV)() const volatile;
     typedef int*       (S::*PMS1CV)(long) const volatile;
     typedef int&       (S::*PMS2CV)(long, int) const volatile;
+    typedef const int& (S::*PMS3CV)(int, ...) const volatile;
     test_result_of<PMS0CV(               S),   int> ();
     test_result_of<PMS0CV(               S&),  int> ();
     test_result_of<PMS0CV(const          S&),  int> ();
@@ -321,6 +340,9 @@ int main()
     test_result_of<PMS2CV(volatile       S*&, int, int), int&> ();
     test_result_of<PMS2CV(const volatile S*&, int, int), int&> ();
     test_result_of<PMS2CV(std::unique_ptr<S>, int, int), int&> ();
+
+    test_result_of<PMS3CV(S&, int), const int &>();
+    test_result_of<PMS3CV(S&, int, long), const int &>();
     }
     { // pointer to member data
     typedef char S::*PMD;

Modified: libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp?rev=332040&r1=332039&r2=332040&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/result_of11.pass.cpp Thu May 10 13:59:35 2018
@@ -58,6 +58,20 @@ void test_result_of_imp()
 
 int main()
 {
+    { // Function types with noexcept
+    typedef bool (&RF0)(int) noexcept;
+    typedef bool (&RF1)(int, ...) noexcept;
+    typedef bool (*PF0)(int) noexcept;
+    typedef bool (*PF1)(int, ...) noexcept;
+    typedef bool (*&PRF0)(int) noexcept;
+    typedef bool (*&PRF1)(int, ...) noexcept;
+    test_result_of_imp<RF0(int), bool>();
+    test_result_of_imp<PF0(int), bool>();
+    test_result_of_imp<PRF0(int), bool>();
+    test_result_of_imp<RF1(int, int), bool>();
+    test_result_of_imp<PF1(int, int), bool>();
+    test_result_of_imp<PRF1(int, int), bool>();
+    }
     {
     typedef char F::*PMD;
     test_result_of_imp<PMD(F                &), char                &>();




More information about the cfe-commits mailing list