diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/SemaCXX/cxx0x-initializer-constructor.cpp | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/SemaCXX/cxx0x-initializer-constructor.cpp')
-rw-r--r-- | clang/test/SemaCXX/cxx0x-initializer-constructor.cpp | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp new file mode 100644 index 0000000..09aca24 --- /dev/null +++ b/clang/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -0,0 +1,283 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct one { char c[1]; }; +struct two { char c[2]; }; + +namespace std { + typedef decltype(sizeof(int)) size_t; + + // libc++'s implementation + template <class _E> + class initializer_list + { + const _E* __begin_; + size_t __size_; + + initializer_list(const _E* __b, size_t __s) + : __begin_(__b), + __size_(__s) + {} + + public: + typedef _E value_type; + typedef const _E& reference; + typedef const _E& const_reference; + typedef size_t size_type; + + typedef const _E* iterator; + typedef const _E* const_iterator; + + initializer_list() : __begin_(nullptr), __size_(0) {} + + size_t size() const {return __size_;} + const _E* begin() const {return __begin_;} + const _E* end() const {return __begin_ + __size_;} + }; +} + +namespace objects { + + struct X1 { X1(int); }; + struct X2 { explicit X2(int); }; // expected-note {{constructor declared here}} + + template <int N> + struct A { + A() { static_assert(N == 0, ""); } + A(int, double) { static_assert(N == 1, ""); } + }; + + template <int N> + struct F { + F() { static_assert(N == 0, ""); } + F(int, double) { static_assert(N == 1, ""); } + F(std::initializer_list<int>) { static_assert(N == 3, ""); } + }; + + template <int N> + struct D { + D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}} + D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}} + }; + + template <int N> + struct E { + E(int, int) { static_assert(N == 0, ""); } + E(X1, int) { static_assert(N == 1, ""); } + }; + + void overload_resolution() { + { A<0> a{}; } + { A<0> a = {}; } + { A<1> a{1, 1.0}; } + { A<1> a = {1, 1.0}; } + + { F<0> f{}; } + { F<0> f = {}; } + // Narrowing conversions don't affect viability. The next two choose + // the initializer_list constructor. + // FIXME: Emit narrowing conversion errors. + { F<3> f{1, 1.0}; } // xpected-error {{narrowing conversion}} + { F<3> f = {1, 1.0}; } // xpected-error {{narrowing conversion}} + { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } + { F<3> f = {1, 2, 3, 4, 5, 6, 7, 8}; } + { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; } + { F<3> f{1, 2}; } + + { D<0> d{1, 2, 3}; } + { D<1> d{1.0, 2.0, 3.0}; } + { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}} + + { E<0> e{1, 2}; } + } + + void explicit_implicit() { + { X1 x{0}; } + { X1 x = {0}; } + { X2 x{0}; } + { X2 x = {0}; } // expected-error {{constructor is explicit}} + } + + struct C { + C(); + C(int, double); + C(int, int); + + int operator[](C); + }; + + C function_call() { + void takes_C(C); + takes_C({1, 1.0}); + + C c; + c[{1, 1.0}]; + + return {1, 1.0}; + } + + void inline_init() { + (void) C{1, 1.0}; + (void) new C{1, 1.0}; + (void) A<1>{1, 1.0}; + (void) new A<1>{1, 1.0}; + } + + struct B { // expected-note 2 {{candidate constructor}} + B(C, int, C); // expected-note {{candidate constructor not viable: cannot convert initializer list argument to 'objects::C'}} + }; + + void nested_init() { + B b1{{1, 1.0}, 2, {3, 4}}; + B b2{{1, 1.0, 4}, 2, {3, 4}}; // expected-error {{no matching constructor for initialization of 'objects::B'}} + } + + void overloaded_call() { + one ov1(B); // expected-note {{not viable: cannot convert initializer list}} + two ov1(C); // expected-note {{not viable: cannot convert initializer list}} + + static_assert(sizeof(ov1({})) == sizeof(two), "bad overload"); + static_assert(sizeof(ov1({1, 2})) == sizeof(two), "bad overload"); + static_assert(sizeof(ov1({{1, 1.0}, 2, {3, 4}})) == sizeof(one), "bad overload"); + + ov1({1}); // expected-error {{no matching function}} + + one ov2(int); + two ov2(F<3>); + static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity + static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable + } + + struct G { // expected-note 6 {{not viable}} + // This is not an initializer-list constructor. + template<typename ...T> + G(std::initializer_list<int>, T ...); // expected-note 3 {{not viable}} + }; + + struct H { // expected-note 6 {{not viable}} + explicit H(int, int); // expected-note 3 {{not viable}} expected-note {{declared here}} + H(int, void*); // expected-note 3 {{not viable}} + }; + + void edge_cases() { + // invalid (the first phase only considers init-list ctors) + // (for the second phase, no constructor is viable) + G g1{1, 2, 3}; // expected-error {{no matching constructor}} + (void) new G{1, 2, 3}; // expected-error {{no matching constructor}} + (void) G{1, 2, 3} // expected-error {{no matching constructor}} + + // valid (T deduced to <>). + G g2({1, 2, 3}); + (void) new G({1, 2, 3}); + (void) G({1, 2, 3}); + + // invalid + H h1({1, 2}); // expected-error {{no matching constructor}} + (void) new H({1, 2}); // expected-error {{no matching constructor}} + // FIXME: Bad diagnostic, mentions void type instead of init list. + (void) H({1, 2}); // expected-error {{no matching conversion}} + + // valid (by copy constructor). + H h2({1, nullptr}); + (void) new H({1, nullptr}); + (void) H({1, nullptr}); + + // valid + H h3{1, 2}; + (void) new H{1, 2}; + (void) H{1, 2}; + } + + struct memberinit { + H h1{1, nullptr}; + H h2 = {1, nullptr}; + H h3{1, 1}; + H h4 = {1, 1}; // expected-error {{constructor is explicit}} + }; +} + +namespace PR12092 { + + struct S { + S(const char*); + }; + struct V { + template<typename T> V(T, T); + void f(std::initializer_list<S>); + void f(const V &); + }; + + void g() { + extern V s; + s.f({"foo", "bar"}); + } + +} + +namespace PR12117 { + struct A { A(int); }; + struct B { B(A); } b{{0}}; + struct C { C(int); } c{0}; +} + +namespace PR12167 { + template<int N> struct string {}; + + struct X { + X(const char v); + template<typename T> bool operator()(T) const; + }; + + template<int N, class Comparator> bool g(const string<N>& s, Comparator cmp) { + return cmp(s); + } + template<int N> bool f(const string<N> &s) { + return g(s, X{'x'}); + } + + bool s = f(string<1>()); +} + +namespace PR12257_PR12241 { + struct command_pair + { + command_pair(int, int); + }; + + struct command_map + { + command_map(std::initializer_list<command_pair>); + }; + + struct generator_pair + { + generator_pair(const command_map); + }; + + // 5 levels: init list, gen_pair, command_map, init list, command_pair + const std::initializer_list<generator_pair> x = {{{{{3, 4}}}}}; + + // 4 levels: init list, gen_pair, command_map via init list, command_pair + const std::initializer_list<generator_pair> y = {{{{1, 2}}}}; +} + +namespace PR12120 { + struct A { explicit A(int); A(float); }; // expected-note {{declared here}} + A a = { 0 }; // expected-error {{constructor is explicit}} + + struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}} + B b = { 0 }; // expected-error {{ambiguous}} +} + +namespace PR12498 { + class ArrayRef; // expected-note{{forward declaration}} + + struct C { + void foo(const ArrayRef&); // expected-note{{passing argument to parameter here}} + }; + + static void bar(C* c) + { + c->foo({ nullptr, 1 }); // expected-error{{initialization of incomplete type 'const PR12498::ArrayRef'}} + } + +} |