Взаимодействие модулей Clang со стандартными ‹iterator› и ‹boost/move/iterator.hpp›

(См. в конце вопроса информацию о конкретных версиях Boost и Clang, которые я использую)

При компиляции в Clang из master/HEAD с использованием новой экспериментальной функции -fmodules я получаю ошибку сборки при компиляции следующего файла с параметрами командной строки, показанными ниже:

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

Команда компиляции и ошибка:

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.

Если я удалю #include <iterator> или перемещу его после #include <boost/move/iterator.hpp>, ошибки исчезнут.

Вопрос: Является ли это просто побочным продуктом библиотек Boost (очевидно, в частности, Boost Move), которые не были подготовлены для модулей с файлами карт модулей Clang? Может ли это быть ошибкой с файлами карт модуля, которые Clang теперь реализовал для libc++, или даже ошибкой в ​​​​самой реализации модулей?

Интересно, что я могу избавиться от ошибки, закомментировав строки 28-28 из 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>

Используемые версии

Повышение 1.61

Clang взят из вершины основной ветки в зеркале github LLVM по состоянию на 7 декабря 2016 г. (технически это из ветки LLVM, но только в основной ветке, идентичной собственной основной ветке LLVM):

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

person Anthony Hall    schedule 08.12.2016    source источник
comment
Похоже, что Clang забывает о квалификаторе пространства имен при попытке выполнить поиск имени в модуле. Или, по крайней мере, это мое лучшее предположение. Это не похоже на ошибку в libС++ или в карте модуля. Я буду исследовать дальше.   -  person EricWF    schedule 09.12.2016


Ответы (2)


Я полагаю, что это было вызвано проблемой с module.modulemap libc++, которую я исправил вчера в r289028. . Эта ошибка приводила к тому, что макрос _LIBCPP_VERSION не экспортировался libc++ при включенных модулях.

Глядя на boost/move/detail/iterator_traits.hpp, кажется, что если _LIBCPP_VERSION не определено, он пропустит настройку и в конечном итоге объявит совершенно другие определения тегов итератора. (В частности, они будут определены непосредственно в пространстве имен std, а не в пространстве имен управления версиями libc++).

Если вы пересоберете LLVM и libc++, это должно решить вашу проблему. Если нет, не стесняйтесь сообщить об ошибке.

PS. Кажется, я всего лишь на шаг впереди.

person EricWF    schedule 09.12.2016
comment
Итак, вы исправили ошибку месяц назад, с которой я столкнулся пару дней назад, затем вы исправили вчера ошибку, с которой я столкнулся вчера... будем надеяться, что это не фиксированное линейное соответствие, так что не пройдет еще месяц, пока вы не исправите ошибку. через два дня найду... ;-) - person Anthony Hall; 10.12.2016
comment
Будем надеяться, что вы больше не столкнетесь с ошибками :-) Однако такие вещи вероятны при игре с экспериментальными функциями. - person EricWF; 11.12.2016
comment
Спасибо за ваш ответ о новом исправлении - у меня не было возможности обновить исходный код clang и попробовать его, но я вернусь, когда у меня будет, и дам вам знать. - person Anthony Hall; 14.12.2016

На данный момент я могу говорить только за boost 1.59.1, но он также явно предполагает, что libc++ можно встретить только при сборке с clang:

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

Это вызывает (почти) точно такую ​​же ошибку, как показано выше, даже в Mac OS X 10.9, в которой есть libc++, предшествовавший введению регрессии libc++, вызвавшей проблему, обсуждаемую в этой теме.

person RJVB    schedule 15.05.2017