Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing #include's for in_place_factory when compiling for CUDA with clang #97

Open
jzmaddock opened this issue Sep 27, 2021 · 5 comments

Comments

@jzmaddock
Copy link
Contributor

I'm not sure if this is an optional or Boost.Format issue, but I suspect this belongs here.

The issue is that some optional methods use in_place_factory as an argument to is_base_of which absolutely requires a complete type as argument, but so far as I can see in_place_factory is only ever forward declared.

When compiling for CUDA with clang this leads to:

In file included from <source>:14:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/format.hpp:38:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/format/internals.hpp:21:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/optional.hpp:15:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:43:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_of.hpp:12:
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_and_derived.hpp:142:25: error: invalid application of 'sizeof' to an incomplete type 'boost::in_place_factory_base'
    BOOST_STATIC_ASSERT(sizeof(B) != 0);
                        ^~~~~~~~~
/opt/compiler-explorer/libs/boost_1_77_0/boost/static_assert.hpp:70:55: note: expanded from macro 'BOOST_STATIC_ASSERT'
#     define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
                                                      ^~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_and_derived.hpp:217:41: note: in instantiation of template class 'boost::detail::is_base_and_derived_impl2<boost::in_place_factory_base, std::locale>' requested here
    BOOST_STATIC_CONSTANT(bool, value = bound_type::value);
                                        ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_of.hpp:25:31: note: in instantiation of template class 'boost::detail::is_base_and_derived_impl<boost::in_place_factory_base, std::locale>' requested here
            (::boost::detail::is_base_and_derived_impl<ncvB,ncvD>::value) ||
                              ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_of.hpp:31:58: note: in instantiation of template class 'boost::detail::is_base_of_imp<boost::in_place_factory_base, std::locale>' requested here
      : public integral_constant<bool, (::boost::detail::is_base_of_imp<Base, Derived>::value)> {};
                                                         ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:794:32: note: in instantiation of template class 'boost::is_base_of<boost::in_place_factory_base, std::locale>' requested here
  : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
                               ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:823:25: note: in instantiation of template class 'boost::optional_detail::is_convertible_to_T_or_factory<std::locale, const std::locale &>' requested here
  : boost::conditional< is_convertible_to_T_or_factory<T, U>::value
                        ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::optional_detail::is_optional_val_init_candidate<std::locale, const std::locale &, false>' requested here
  struct enable_if : public enable_if_c<Cond::value, T> {};
                                        ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:951:53: note: in instantiation of template class 'boost::enable_if<boost::optional_detail::is_optional_val_init_candidate<std::locale, const std::locale &, false>, bool>' requested here
                      BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
                                                    ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/format/format_implementation.hpp:40:44: note: while substituting deduced template arguments into function template 'optional' [with Expr = const std::locale &]
          exceptions_(io::all_error_bits), loc_(loc)
                                           ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/detail/optional_factory_support.hpp:32:9: note: forward declaration of 'boost::in_place_factory_base'
  class in_place_factory_base ;

You can see the issue here: https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:cuda,selection:(endColumn:23,endLineNumber:9,positionColumn:23,positionLineNumber:9,selectionStartColumn:23,selectionStartLineNumber:9,startColumn:23,startLineNumber:9),source:'%23include+%3Cboost/config.hpp%3E%0A//%0A//+These+%23undefs+reflect+the+current+state+of+Boost.Config+develop+compared+to+1.77:%0A//%0A%23undef+BOOST_NO_CXX11_VARIADIC_TEMPLATES%0A%23undef+BOOST_NO_VARIADIC_TEMPLATES%0A//%0A//+These+includes+are+required+to+make+this+compile,%0A//+uncomment+to+remove+the+errors:%0A//%0A//%23include+%3Cboost/utility/in_place_factory.hpp%3E%0A//%23include+%3Cboost/utility/typed_in_place_factory.hpp%3E%0A%0A%23include+%3Cboost/format.hpp%3E%0A'),l:'5',n:'0',o:'CUDA+C%2B%2B+source+%231',t:'0')),k:63.22701688555347,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:cuclang1100,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:cuda,libs:!(),options:'-std%3Dc%2B%2B14+-O3+-I/opt/compiler-explorer/libs/boost_1_77_0/',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'clang+11.0.0+sm_75+CUDA-10.2+(CUDA+C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),header:(),k:43.667751209994,l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(compiler:1,editor:1,fontScale:12,fontUsePx:'0',wrap:'1'),l:'5',n:'0',o:'Output+of+clang+11.0.0+sm_75+CUDA-10.2+(Compiler+%231)',t:'0')),header:(),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:36.77298311444653,l:'3',n:'0',o:'',t:'0')),l:'2',m:100,n:'0',o:'',t:'0')),version:4

Adding

#include <boost/utility/in_place_factory.hpp>
#include <boost/utility/typed_in_place_factory.hpp>

Before including optional.hpp fixes the issue.

@jzmaddock
Copy link
Contributor Author

This is moved from boostorg/config#406

@psalz
Copy link

psalz commented Sep 28, 2021

Ah yes, I remember running into this a couple of years ago as well. The problem is not actually in Boost.Optional, but rather stems from the fact that not all Boost libraries solely rely on Boost.Config for compiler detection (i.e., some roll their own). So even with the changes in boostorg/config#297 (great to finally see some movement there!) other places still need to be updated to either check for __NVCC__ instead of __CUDACC__, or, preferably, use only macros set by Boost.Config.

In this case the problem is a check in Boost.TypeTraits' intrinsic.hpp on line 163. I suspect there are several other Boost libraries with the same problem.

@jzmaddock
Copy link
Contributor Author

In this case the problem is a check in Boost.TypeTraits' intrinsic.hpp on line 163. I suspect there are several other Boost libraries with the same problem.

That is "a" problem, not "the" problem. I'll get to that shortly, but it is still a requirement that arguments to is_base_of are complete types even if we use an intrinsic to get the answer.

@psalz
Copy link

psalz commented Oct 1, 2021

Heh, okay sure, apologies for the absolute statement. From my (superficial) understanding it seems like there are two separate issues at hand:

  1. Clang CUDA not using the available intrinsics,
  2. Incomplete types being used within the fallback implementation of BOOST_IS_BASE_OF.

I am however confused as to when the branch #if defined(BOOST_CLANG) && defined(__has_feature) && !defined(__CUDACC__) is NOT being taken (aside from the bug at hand), i.e., when the fallback mechanism was supposed to kick in. I tried compiling the above example with NVCC + Clang as a host compiler (nvcc -ccbin clang++-10), and it seems that at least during the host compilation phase, __CUDACC__ is not set, leading to the intrinsics being used.

What I can say however is that replacing the check with !defined(__NVCC__) as suggested by me above is in fact not the solution, because this then does trigger the fallback for NVCC + Clang as host, causing the incomplete type error.

@jzmaddock
Copy link
Contributor Author

The type_traits issues are addressed here: boostorg/type_traits#162

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants