1// Test case reduced from an experimental std modules implementation. 2// Tests that the compiler don't emit confusing error about the ambiguous ctor 3// about std::pair. 4// 5// RUN: rm -fr %t 6// RUN: mkdir %t 7// RUN: split-file %s %t 8// 9// RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-module-interface -o %t/std-string.pcm 10// RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-module-interface -o %t/std-algorithm.pcm 11// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify -o %t/Use.pcm 12 13// Test again with reduced BMI. 14// RUN: rm -fr %t 15// RUN: mkdir %t 16// RUN: split-file %s %t 17// 18// RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-reduced-module-interface -o %t/std-string.pcm 19// RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-reduced-module-interface -o %t/std-algorithm.pcm 20// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-reduced-module-interface -verify -o %t/Use.pcm 21 22//--- Use.cppm 23// expected-no-diagnostics 24module; 25#include "config.h" 26# 3 "pair-unambiguous-ctor.cppm" 1 3 27export module std:M; 28# 3 "pair-unambiguous-ctor.cppm" 2 3 29import :string; 30import :algorithm; 31 32auto check() { 33 return std::string(); 34} 35 36//--- string.cppm 37module; 38#include "string.h" 39# 28 "pair-unambiguous-ctor.cppm" 1 3 40export module std:string; 41export namespace std { 42 using std::string; 43} 44# 28 "pair-unambiguous-ctor.cppm" 2 3 45 46//--- algorithm.cppm 47module; 48#include "algorithm.h" 49# 38 "pair-unambiguous-ctor.cppm" 1 3 50export module std:algorithm; 51# 38 "pair-unambiguous-ctor.cppm" 2 3 52 53//--- pair.h 54namespace std __attribute__ ((__visibility__ ("default"))) 55{ 56 typedef long unsigned int size_t; 57 typedef long int ptrdiff_t; 58 59 typedef decltype(nullptr) nullptr_t; 60 61 template<typename _Tp, _Tp __v> 62 struct integral_constant 63 { 64 static constexpr _Tp value = __v; 65 typedef _Tp value_type; 66 typedef integral_constant<_Tp, __v> type; 67 constexpr operator value_type() const noexcept { return value; } 68 constexpr value_type operator()() const noexcept { return value; } 69 }; 70 71 template<typename _Tp, _Tp __v> 72 constexpr _Tp integral_constant<_Tp, __v>::value; 73 74 typedef integral_constant<bool, true> true_type; 75 typedef integral_constant<bool, false> false_type; 76 77 template<bool __v> 78 using __bool_constant = integral_constant<bool, __v>; 79 80 81 template<bool, typename, typename> 82 struct conditional; 83 84 template<bool _Cond, typename _Iftrue, typename _Iffalse> 85 struct conditional 86 { typedef _Iftrue type; }; 87 88 template<typename _Iftrue, typename _Iffalse> 89 struct conditional<false, _Iftrue, _Iffalse> 90 { typedef _Iffalse type; }; 91 92 93 template<bool, typename _Tp = void> 94 struct enable_if 95 { }; 96 97 98 template<typename _Tp> 99 struct enable_if<true, _Tp> 100 { typedef _Tp type; }; 101 102 template<typename _Tp, typename... _Args> 103 struct __is_constructible_impl 104 : public __bool_constant<__is_constructible(_Tp, _Args...)> 105 { }; 106 107 108 template<typename _Tp, typename... _Args> 109 struct is_constructible 110 : public __is_constructible_impl<_Tp, _Args...> 111 {}; 112 113 template<typename> 114 struct __is_void_helper 115 : public false_type { }; 116 117 template<> 118 struct __is_void_helper<void> 119 : public true_type { }; 120 121 template<typename _Tp> 122 struct is_void 123 : public __is_void_helper<_Tp>::type 124 { }; 125 126 template<typename...> 127 class tuple; 128 129 template<std::size_t...> 130 struct _Index_tuple; 131 132 template <bool, typename _T1, typename _T2> 133 struct _PCC 134 { 135 template <typename _U1, typename _U2> 136 static constexpr bool _ConstructiblePair() 137 { 138 return is_constructible<_T1, const _U1&>::value; 139 } 140 141 }; 142 143 template<typename _T1, typename _T2> 144 struct pair 145 { 146 typedef _T1 first_type; 147 typedef _T2 second_type; 148 149 _T1 first; 150 _T2 second; 151 152 using _PCCP = _PCC<true, _T1, _T2>; 153 154 template<typename _U1 = _T1, typename _U2=_T2, typename 155 enable_if<_PCCP::template 156 _ConstructiblePair<_U1, _U2>(), 157 bool>::type=true> 158 constexpr pair(const _T1& __a, const _T2& __b) 159 : first(__a), second(__b) { } 160 161 constexpr pair& 162 operator=(typename conditional< 163 is_constructible<_T2>::value, 164 const pair&, nullptr_t>::type __p) 165 { 166 first = __p.first; 167 second = __p.second; 168 return *this; 169 } 170 171 private: 172 template<typename... _Args1, std::size_t... _Indexes1, 173 typename... _Args2, std::size_t... _Indexes2> 174 constexpr 175 pair(tuple<_Args1...>&, tuple<_Args2...>&, 176 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); 177 178 }; 179 180 template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>; 181} 182 183//--- string.h 184#include "pair.h" 185 186namespace std __attribute__ ((__visibility__ ("default"))) 187{ 188 class __undefined; 189 190 template<typename _Tp> 191 using __make_not_void 192 = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type; 193 194 template <typename Ptr> 195 struct pointer_traits {}; 196 197 template<typename _Tp> 198 struct pointer_traits<_Tp*> 199 { 200 201 typedef _Tp* pointer; 202 203 typedef _Tp element_type; 204 205 static constexpr pointer 206 pointer_to(__make_not_void<element_type>& __r) noexcept 207 { return __builtin_addressof(__r); } 208 }; 209 210 template<typename _Tp> 211 class allocator; 212 213 template<typename _Alloc> 214 struct allocator_traits; 215 216 template<typename _Tp> 217 struct allocator_traits<allocator<_Tp>> 218 { 219 using pointer = _Tp*; 220 }; 221 222 template<typename _Alloc> 223 struct __alloc_traits 224 : std::allocator_traits<_Alloc> 225 { 226 typedef std::allocator_traits<_Alloc> _Base_type; 227 typedef typename _Base_type::pointer pointer; 228 }; 229 230 template<class _CharT> 231 struct char_traits; 232 233 template<typename _CharT, typename _Traits = char_traits<_CharT>, 234 typename _Alloc = allocator<_CharT> > 235 class basic_string 236 { 237 typedef std::__alloc_traits<_Alloc> _Alloc_traits; 238 239 public: 240 typedef typename _Alloc_traits::pointer pointer; 241 242 private: 243 pointer _M_dataplus; 244 _CharT _M_local_buf[16]; 245 246 pointer 247 _M_local_data() 248 { 249 return std::pointer_traits<pointer>::pointer_to(*_M_local_buf); 250 } 251 public: 252 basic_string() 253 : _M_dataplus(_M_local_data()) 254 { } 255 256 }; 257 258 typedef basic_string<char> string; 259} 260 261//--- algorithm.h 262#include "pair.h" 263namespace std { 264 struct _Power2_rehash_policy 265 { 266 std::pair<bool, std::size_t> 267 _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, 268 std::size_t __n_ins) noexcept 269 { 270 return { false, 0 }; 271 } 272 }; 273} 274 275//--- config.h 276namespace std 277{ 278 typedef __SIZE_TYPE__ size_t; 279} 280 281