blob: a08a04806cae00a84d8c1782205c3c79749a965d [file] [log] [blame]
Sebastian Redl2b916b82012-01-17 22:49:42 +00001// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2
3namespace std {
4 typedef decltype(sizeof(int)) size_t;
5
6 // libc++'s implementation
7 template <class _E>
8 class initializer_list
9 {
10 const _E* __begin_;
11 size_t __size_;
12
13 initializer_list(const _E* __b, size_t __s)
14 : __begin_(__b),
15 __size_(__s)
16 {}
17
18 public:
19 typedef _E value_type;
20 typedef const _E& reference;
21 typedef const _E& const_reference;
22 typedef size_t size_type;
23
24 typedef const _E* iterator;
25 typedef const _E* const_iterator;
26
27 initializer_list() : __begin_(nullptr), __size_(0) {}
28
29 size_t size() const {return __size_;}
30 const _E* begin() const {return __begin_;}
31 const _E* end() const {return __begin_ + __size_;}
32 };
33}
34
Sebastian Redl84760e32012-01-17 22:49:58 +000035template <typename T, typename U>
36struct same_type { static const bool value = false; };
37template <typename T>
38struct same_type<T, T> { static const bool value = true; };
39
Sebastian Redl2b916b82012-01-17 22:49:42 +000040struct one { char c[1]; };
41struct two { char c[2]; };
42
43struct A {
44 int a, b;
45};
46
47struct B {
48 B();
49 B(int, int);
50};
51
52void simple_list() {
53 std::initializer_list<int> il = { 1, 2, 3 };
54 std::initializer_list<double> dl = { 1.0, 2.0, 3 };
55 std::initializer_list<A> al = { {1, 2}, {2, 3}, {3, 4} };
56 std::initializer_list<B> bl = { {1, 2}, {2, 3}, {} };
57}
58
59void function_call() {
60 void f(std::initializer_list<int>);
61 f({1, 2, 3});
62
63 void g(std::initializer_list<B>);
64 g({ {1, 2}, {2, 3}, {} });
65}
Sebastian Redlfe592282012-01-17 22:49:48 +000066
67struct C {
68 C(int);
69};
70
71struct D {
72 D();
73 operator int();
74 operator C();
75};
76
77void overloaded_call() {
78 one overloaded(std::initializer_list<int>);
79 two overloaded(std::initializer_list<B>);
80
81 static_assert(sizeof(overloaded({1, 2, 3})) == sizeof(one), "bad overload");
82 static_assert(sizeof(overloaded({ {1, 2}, {2, 3}, {} })) == sizeof(two), "bad overload");
83
84 void ambiguous(std::initializer_list<A>); // expected-note {{candidate}}
85 void ambiguous(std::initializer_list<B>); // expected-note {{candidate}}
86 ambiguous({ {1, 2}, {2, 3}, {3, 4} }); // expected-error {{ambiguous}}
87
88 one ov2(std::initializer_list<int>); // expected-note {{candidate}}
89 two ov2(std::initializer_list<C>); // expected-note {{candidate}}
90 // Worst sequence to int is identity, whereas to C it's user-defined.
91 static_assert(sizeof(ov2({1, 2, 3})) == sizeof(one), "bad overload");
92 // But here, user-defined is worst in both cases.
93 ov2({1, 2, D()}); // expected-error {{ambiguous}}
94}
Sebastian Redl84760e32012-01-17 22:49:58 +000095
96template <typename T>
97T deduce(std::initializer_list<T>); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
98template <typename T>
99T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
100
101void argument_deduction() {
102 static_assert(same_type<decltype(deduce({1, 2, 3})), int>::value, "bad deduction");
103 static_assert(same_type<decltype(deduce({1.0, 2.0, 3.0})), double>::value, "bad deduction");
104
105 deduce({1, 2.0}); // expected-error {{no matching function}}
106
107 static_assert(same_type<decltype(deduce_ref({1, 2, 3})), int>::value, "bad deduction");
108 static_assert(same_type<decltype(deduce_ref({1.0, 2.0, 3.0})), double>::value, "bad deduction");
109
110 deduce_ref({1, 2.0}); // expected-error {{no matching function}}
111}