Issue 61443
Summary Issue with clang compilation of code using std::function and std::variant
Labels new issue
Assignees
Reporter DD-L
    
Hello, can someone explain this?

```
#include <functional>
#include <variant>

struct P;

struct A : std::function<P(void)> {
    using std::function<P(void)>::function;
    // ...
};


struct P {
    std::variant<int, A> m_member;
};

int main() {
    // ...
    return 0;
}
```


The above code can be compiled successfully on all gcc/MSVC versions that support `std::function` and `std::variant`: [`https://godbolt.org/z/jb9TzsGeG`](https://godbolt.org/z/jb9TzsGeG). 

However, all versions of clang (`<= ver 15.0.0`) report the following error:

```
In file included from <source>:4:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/functional:49:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_function.h:60:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/move.h:57:
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:2936:63: error: calling '_S_get' with incomplete return type 'typename __invoke_result<A &>::type' (aka 'P')
      template<typename _Tp, typename = decltype(_S_conv<_Tp>(_S_get()))>
 ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:349:4: note: in instantiation of template class 'std::__is_invocable_impl<std::__invoke_result<A &>, P, false>' requested here
        : __is_invocable_impl<_Res2, _Res>::type
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:353:34: note: in instantiation of template class 'std::function<P ()>::_Callable<A, A>' requested here
        using _Requires = __enable_if_t<_Cond::value, _Tp>;
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:434:33: note: in instantiation of template type alias '_Requires' requested here
 typename _Constraints = _Requires<_Callable<_Functor>>>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:435:2: note: in instantiation of default argument for 'function<A>' required here
        function(_Functor&& __f)
 ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:1297:4: note: while substituting deduced template arguments into function template 'function' [with _Functor = A, _Constraints = (no value)]
 __is_trivially_constructible(_Tp, _Tp&&)>>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:1303:14: note: (skipping 3 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
    : public __is_trivially_move_constructible_impl<_Tp>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:350:23: note: in instantiation of static data member 'std::__detail::__variant::_Traits<int, A>::_S_trivial_move_ctor' requested here
          _S_trivial_dtor && _S_trivial_move_ctor
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:732:45: note: in instantiation of static data member 'std::__detail::__variant::_Traits<int, A>::_S_trivial_move_assign' requested here
      _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>;
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:735:28: note: in instantiation of template type alias '_Move_assign_alias' requested here
    struct _Variant_base : _Move_assign_alias<_Types...>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:1337:15: note: in instantiation of template class 'std::__detail::__variant::_Variant_base<int, A>' requested here
    : private __detail::__variant::_Variant_base<_Types...>,
 ^
<source>:16:26: note: in instantiation of template class 'std::variant<int, A>' requested here
    std::variant<int, A> m_member;
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:2930:37: note: '_S_get' declared here
      static typename _Result::type _S_get();
                                    ^
<source>:15:8: note: definition of 'P' is not complete until the closing '}'
struct P {
 ^
1 error generated.
ASM generation compiler returned: 1
In file included from <source>:4:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/functional:49:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_function.h:60:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/move.h:57:
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:2936:63: error: calling '_S_get' with incomplete return type 'typename __invoke_result<A &>::type' (aka 'P')
      template<typename _Tp, typename = decltype(_S_conv<_Tp>(_S_get()))>
 ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:349:4: note: in instantiation of template class 'std::__is_invocable_impl<std::__invoke_result<A &>, P, false>' requested here
        : __is_invocable_impl<_Res2, _Res>::type
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:353:34: note: in instantiation of template class 'std::function<P ()>::_Callable<A, A>' requested here
        using _Requires = __enable_if_t<_Cond::value, _Tp>;
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:434:33: note: in instantiation of template type alias '_Requires' requested here
 typename _Constraints = _Requires<_Callable<_Functor>>>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/std_function.h:435:2: note: in instantiation of default argument for 'function<A>' required here
        function(_Functor&& __f)
 ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:1297:4: note: while substituting deduced template arguments into function template 'function' [with _Functor = A, _Constraints = (no value)]
 __is_trivially_constructible(_Tp, _Tp&&)>>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:1303:14: note: (skipping 3 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
    : public __is_trivially_move_constructible_impl<_Tp>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:350:23: note: in instantiation of static data member 'std::__detail::__variant::_Traits<int, A>::_S_trivial_move_ctor' requested here
          _S_trivial_dtor && _S_trivial_move_ctor
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:732:45: note: in instantiation of static data member 'std::__detail::__variant::_Traits<int, A>::_S_trivial_move_assign' requested here
      _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>;
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:735:28: note: in instantiation of template type alias '_Move_assign_alias' requested here
    struct _Variant_base : _Move_assign_alias<_Types...>
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/variant:1337:15: note: in instantiation of template class 'std::__detail::__variant::_Variant_base<int, A>' requested here
    : private __detail::__variant::_Variant_base<_Types...>,
 ^
<source>:16:26: note: in instantiation of template class 'std::variant<int, A>' requested here
    std::variant<int, A> m_member;
 ^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/type_traits:2930:37: note: '_S_get' declared here
      static typename _Result::type _S_get();
                                    ^
<source>:15:8: note: definition of 'P' is not complete until the closing '}'
struct P {
 ^
1 error generated.
Execution build compiler returned: 1
```


If I replace the implementation of `struct A` with the following implementation, clang can work properly:

```
struct A : std::function<P(void)> {
    // using std::function<P(void)>::function; // bad code
    
    A() = default;
    A(const A&) = default;
 A(A&&) = default;
    A(std::function<P(void)> f) : std::function<P(void)>(std::move(f)) {}

    // ...
};
```

Is this considered a bug in clang?
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to