xref: /llvm-project/clang/test/Modules/pair-unambiguous-ctor.cppm (revision da00c60dae0040185dc45039c4397f6e746548e9)
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