Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang Modules interaction with std <iterator> and <boost/move/iterator.hpp>

(See end of question for information on particular versions of Boost and Clang I am using)

Compiling in Clang from master/HEAD, using the new experimental -fmodules feature, I get a build error from compiling the following file with the command-line options shown below:

#include <iterator>
#include <boost/move/iterator.hpp>

Compile command and error:

anhall@leviathan: <path-to-clang-install-from-master>/bin/clang++ -o file.o -c file.cpp --std=c++1z -stdlib=libc++ -fmodules

In file included from file.cpp:2:
In file included from /usr/local/include/boost/move/iterator.hpp:27:
/usr/local/include/boost/move/detail/iterator_traits.hpp:60:17: error: reference to 'random_access_iterator_tag' is ambiguous
   typedef std::random_access_iterator_tag   iterator_category;
                ^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: note: candidate found by name lookup is 'std::__1::random_access_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY random_access_iterator_tag : public bidirectional_iterator_tag {};
                             ^
/usr/local/include/boost/move/detail/iterator_traits.hpp:34:8: note: candidate found by name lookup is 'std::random_access_iterator_tag'
struct random_access_iterator_tag;
       ^
/usr/local/include/boost/move/detail/iterator_traits.hpp:71:17: error: reference to 'random_access_iterator_tag' is ambiguous
   typedef std::random_access_iterator_tag   iterator_category;
                ^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: note: candidate found by name lookup is 'std::__1::random_access_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY random_access_iterator_tag : public bidirectional_iterator_tag {};
                             ^
/usr/local/include/boost/move/detail/iterator_traits.hpp:34:8: note: candidate found by name lookup is 'std::random_access_iterator_tag'
struct random_access_iterator_tag;
       ^
In file included from file.cpp:2:
/usr/local/include/boost/move/iterator.hpp:196:17: error: reference to 'output_iterator_tag' is ambiguous
   typedef std::output_iterator_tag    iterator_category;
                ^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:435:30: note: candidate found by name lookup is 'std::__1::output_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY output_iterator_tag {};
                             ^
/usr/local/include/boost/move/detail/iterator_traits.hpp:35:8: note: candidate found by name lookup is 'std::output_iterator_tag'
struct output_iterator_tag;
       ^
In file included from file.cpp:2:
/usr/local/include/boost/move/iterator.hpp:238:17: error: reference to 'output_iterator_tag' is ambiguous
   typedef std::output_iterator_tag    iterator_category;
                ^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:435:30: note: candidate found by name lookup is 'std::__1::output_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY output_iterator_tag {};
                             ^
/usr/local/include/boost/move/detail/iterator_traits.hpp:35:8: note: candidate found by name lookup is 'std::output_iterator_tag'
struct output_iterator_tag;
       ^
In file included from file.cpp:2:
/usr/local/include/boost/move/iterator.hpp:278:17: error: reference to 'output_iterator_tag' is ambiguous
   typedef std::output_iterator_tag    iterator_category;
                ^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:435:30: note: candidate found by name lookup is 'std::__1::output_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY output_iterator_tag {};
                             ^
/usr/local/include/boost/move/detail/iterator_traits.hpp:35:8: note: candidate found by name lookup is 'std::output_iterator_tag'
struct output_iterator_tag;
       ^
5 errors generated.

If I delete the #include <iterator> or move it after the #include <boost/move/iterator.hpp>, the errors dissapear.

Question: Is this simply a byproduct of Boost libraries (Boost Move, in particular, apparently) not being prepared for Modules with Clang module map files? Could this be a bug with the module map files Clang has now implemented for libc++, or even a bug in the modules implementation itself?

Interestingly, I can get the error to go away by commenting out lines 28-28 of boost/move/detail/iterator_traits.hpp:

// #include <boost/move/detail/std_ns_begin.hpp>
// BOOST_MOVE_STD_NS_BEG
//
// struct input_iterator_tag;
// struct forward_iterator_tag;
// struct bidirectional_iterator_tag;
// struct random_access_iterator_tag;
// struct output_iterator_tag;
//
// BOOST_MOVE_STD_NS_END
// #include <boost/move/detail/std_ns_end.hpp>

Versions in use

Boost 1.61

Clang is from tip of master branch in the github mirror of LLVM, as of Dec 7, 2016 (technicaly it's from a fork of LLVM, but it's only on the master branch that's identical to LLVM's own master branch):

clang version 4.0.0 (https://github.com/matus-chochlik/clang.git b9cb1c8a1ebf52695372de12c7b04c8ef1bd8b4e) (https://github.com/llvm-mirror/llvm.git b60c7b1f61eabbe971d08568adb790a7cfc6a403)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Users/anhall/impersonal/code/llvm-reflexpr/install/bin
like image 270
Anthony Hall Avatar asked Dec 08 '16 23:12

Anthony Hall


2 Answers

I believe this was caused by an issue with libc++'s module.modulemap, which I fixed yesterday in r289028. This bug caused the _LIBCPP_VERSION macro to not be exported by libc++ when modules are enabled.

After looking at boost/move/detail/iterator_traits.hpp it seems that if _LIBCPP_VERSION is not defined it will miss-configure and end up declaring entirely different definitions of the iterator tags. (Specifically it will define them directly in namespace std and not in libc++'s versioning namespace).

If you re-build LLVM and libc++ it should fix your issue. If not feel free to file a bug.

PS. It seems I'm just one step ahead.

like image 141
EricWF Avatar answered Sep 29 '22 19:09

EricWF


I can only speak for boost 1.59.1 at the moment, but it clearly also makes the assumption that libc++ can only be encountered when building with clang :

#if defined(__clang__) && defined(_LIBCPP_VERSION)
// ...
#else
// ...
#endif

That provokes the (almost) exact same error as shown above, even on Mac OS X 10.9 which has a libc++ that predates the introduction of the libc++ regression that caused the issue discussed in this thread.

like image 41
RJVB Avatar answered Sep 29 '22 17:09

RJVB