| // Test case reduced from an experimental std modules implementation. |
| // Tests that the compiler don't emit confusing error about the ambiguous ctor |
| // about std::pair. |
| // |
| // RUN: rm -fr %t |
| // RUN: mkdir %t |
| // RUN: split-file %s %t |
| // |
| // RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-module-interface -o %t/std-string.pcm |
| // RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-module-interface -o %t/std-algorithm.pcm |
| // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify -o %t/Use.pcm |
| |
| // Test again with reduced BMI. |
| // RUN: rm -fr %t |
| // RUN: mkdir %t |
| // RUN: split-file %s %t |
| // |
| // RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-reduced-module-interface -o %t/std-string.pcm |
| // RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-reduced-module-interface -o %t/std-algorithm.pcm |
| // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-reduced-module-interface -verify -o %t/Use.pcm |
| |
| //--- Use.cppm |
| // expected-no-diagnostics |
| module; |
| #include "config.h" |
| # 3 "pair-unambiguous-ctor.cppm" 1 3 |
| export module std:M; |
| # 3 "pair-unambiguous-ctor.cppm" 2 3 |
| import :string; |
| import :algorithm; |
| |
| auto check() { |
| return std::string(); |
| } |
| |
| //--- string.cppm |
| module; |
| #include "string.h" |
| # 28 "pair-unambiguous-ctor.cppm" 1 3 |
| export module std:string; |
| export namespace std { |
| using std::string; |
| } |
| # 28 "pair-unambiguous-ctor.cppm" 2 3 |
| |
| //--- algorithm.cppm |
| module; |
| #include "algorithm.h" |
| # 38 "pair-unambiguous-ctor.cppm" 1 3 |
| export module std:algorithm; |
| # 38 "pair-unambiguous-ctor.cppm" 2 3 |
| |
| //--- pair.h |
| namespace std __attribute__ ((__visibility__ ("default"))) |
| { |
| typedef long unsigned int size_t; |
| typedef long int ptrdiff_t; |
| |
| typedef decltype(nullptr) nullptr_t; |
| |
| template<typename _Tp, _Tp __v> |
| struct integral_constant |
| { |
| static constexpr _Tp value = __v; |
| typedef _Tp value_type; |
| typedef integral_constant<_Tp, __v> type; |
| constexpr operator value_type() const noexcept { return value; } |
| constexpr value_type operator()() const noexcept { return value; } |
| }; |
| |
| template<typename _Tp, _Tp __v> |
| constexpr _Tp integral_constant<_Tp, __v>::value; |
| |
| typedef integral_constant<bool, true> true_type; |
| typedef integral_constant<bool, false> false_type; |
| |
| template<bool __v> |
| using __bool_constant = integral_constant<bool, __v>; |
| |
| |
| template<bool, typename, typename> |
| struct conditional; |
| |
| template<bool _Cond, typename _Iftrue, typename _Iffalse> |
| struct conditional |
| { typedef _Iftrue type; }; |
| |
| template<typename _Iftrue, typename _Iffalse> |
| struct conditional<false, _Iftrue, _Iffalse> |
| { typedef _Iffalse type; }; |
| |
| |
| template<bool, typename _Tp = void> |
| struct enable_if |
| { }; |
| |
| |
| template<typename _Tp> |
| struct enable_if<true, _Tp> |
| { typedef _Tp type; }; |
| |
| template<typename _Tp, typename... _Args> |
| struct __is_constructible_impl |
| : public __bool_constant<__is_constructible(_Tp, _Args...)> |
| { }; |
| |
| |
| template<typename _Tp, typename... _Args> |
| struct is_constructible |
| : public __is_constructible_impl<_Tp, _Args...> |
| {}; |
| |
| template<typename> |
| struct __is_void_helper |
| : public false_type { }; |
| |
| template<> |
| struct __is_void_helper<void> |
| : public true_type { }; |
| |
| template<typename _Tp> |
| struct is_void |
| : public __is_void_helper<_Tp>::type |
| { }; |
| |
| template<typename...> |
| class tuple; |
| |
| template<std::size_t...> |
| struct _Index_tuple; |
| |
| template <bool, typename _T1, typename _T2> |
| struct _PCC |
| { |
| template <typename _U1, typename _U2> |
| static constexpr bool _ConstructiblePair() |
| { |
| return is_constructible<_T1, const _U1&>::value; |
| } |
| |
| }; |
| |
| template<typename _T1, typename _T2> |
| struct pair |
| { |
| typedef _T1 first_type; |
| typedef _T2 second_type; |
| |
| _T1 first; |
| _T2 second; |
| |
| using _PCCP = _PCC<true, _T1, _T2>; |
| |
| template<typename _U1 = _T1, typename _U2=_T2, typename |
| enable_if<_PCCP::template |
| _ConstructiblePair<_U1, _U2>(), |
| bool>::type=true> |
| constexpr pair(const _T1& __a, const _T2& __b) |
| : first(__a), second(__b) { } |
| |
| constexpr pair& |
| operator=(typename conditional< |
| is_constructible<_T2>::value, |
| const pair&, nullptr_t>::type __p) |
| { |
| first = __p.first; |
| second = __p.second; |
| return *this; |
| } |
| |
| private: |
| template<typename... _Args1, std::size_t... _Indexes1, |
| typename... _Args2, std::size_t... _Indexes2> |
| constexpr |
| pair(tuple<_Args1...>&, tuple<_Args2...>&, |
| _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); |
| |
| }; |
| |
| template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>; |
| } |
| |
| //--- string.h |
| #include "pair.h" |
| |
| namespace std __attribute__ ((__visibility__ ("default"))) |
| { |
| class __undefined; |
| |
| template<typename _Tp> |
| using __make_not_void |
| = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type; |
| |
| template <typename Ptr> |
| struct pointer_traits {}; |
| |
| template<typename _Tp> |
| struct pointer_traits<_Tp*> |
| { |
| |
| typedef _Tp* pointer; |
| |
| typedef _Tp element_type; |
| |
| static constexpr pointer |
| pointer_to(__make_not_void<element_type>& __r) noexcept |
| { return __builtin_addressof(__r); } |
| }; |
| |
| template<typename _Tp> |
| class allocator; |
| |
| template<typename _Alloc> |
| struct allocator_traits; |
| |
| template<typename _Tp> |
| struct allocator_traits<allocator<_Tp>> |
| { |
| using pointer = _Tp*; |
| }; |
| |
| template<typename _Alloc> |
| struct __alloc_traits |
| : std::allocator_traits<_Alloc> |
| { |
| typedef std::allocator_traits<_Alloc> _Base_type; |
| typedef typename _Base_type::pointer pointer; |
| }; |
| |
| template<class _CharT> |
| struct char_traits; |
| |
| template<typename _CharT, typename _Traits = char_traits<_CharT>, |
| typename _Alloc = allocator<_CharT> > |
| class basic_string |
| { |
| typedef std::__alloc_traits<_Alloc> _Alloc_traits; |
| |
| public: |
| typedef typename _Alloc_traits::pointer pointer; |
| |
| private: |
| pointer _M_dataplus; |
| _CharT _M_local_buf[16]; |
| |
| pointer |
| _M_local_data() |
| { |
| return std::pointer_traits<pointer>::pointer_to(*_M_local_buf); |
| } |
| public: |
| basic_string() |
| : _M_dataplus(_M_local_data()) |
| { } |
| |
| }; |
| |
| typedef basic_string<char> string; |
| } |
| |
| //--- algorithm.h |
| #include "pair.h" |
| namespace std { |
| struct _Power2_rehash_policy |
| { |
| std::pair<bool, std::size_t> |
| _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, |
| std::size_t __n_ins) noexcept |
| { |
| return { false, 0 }; |
| } |
| }; |
| } |
| |
| //--- config.h |
| namespace std |
| { |
| typedef __SIZE_TYPE__ size_t; |
| } |
| |