Skip to content

Commit 81a9c08

Browse files
committed
Add more tests
1 parent be3a509 commit 81a9c08

File tree

4 files changed

+116
-1
lines changed

4 files changed

+116
-1
lines changed

clang/lib/Sema/SemaInit.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -4285,6 +4285,22 @@ static void TryConstructorInitialization(Sema &S,
42854285
// CWG2311: T{ prvalue_of_type_T } is not eligible for copy elision
42864286
// Make this an elision if this won't call an initializer-list
42874287
// constructor. (Always on an aggregate type or check constructors first.)
4288+
4289+
// This effectively makes our resolution as follows. The parts in angle
4290+
// brackets are additions.
4291+
// C++17 [over.match.list]p(1.2):
4292+
// - If no viable initializer-list constructor is found <and the
4293+
// initializer list does not consist of exactly a single element with
4294+
// the same cv-unqualified class type as T>, [...]
4295+
// C++17 [dcl.init.list]p(3.6):
4296+
// - Otherwise, if T is a class type, constructors are considered. The
4297+
// applicable constructors are enumerated and the best one is chosen
4298+
// through overload resolution. <If no constructor is found and the
4299+
// initializer list consists of exactly a single element with the same
4300+
// cv-unqualified class type as T, the object is initialized from that
4301+
// element (by copy-initialization for copy-list-initialization, or by
4302+
// direct-initialization for direct-list-initialization). Otherwise, >
4303+
// if a narrowing conversion [...]
42884304
assert(!IsInitListCopy &&
42894305
"IsInitListCopy only possible with aggregate types");
42904306
CopyElisionPossible = true;

clang/test/CXX/drs/cwg23xx.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,20 @@ struct X {
176176
X<std::initializer_list<any>> x{ X<std::initializer_list<any>>() };
177177
// since-cxx17-error@-1 {{call to deleted constructor of 'X<std::initializer_list<any>>'}}
178178
// since-cxx17-note@#cwg2311-X {{'X' has been explicitly marked deleted here}}
179+
180+
// Per the currently implemented resolution, this does not apply to std::initializer_list.
181+
// An initializer list initialized from `{ e }` always has exactly one element constructed
182+
// from `e`, where previously that could have been a copy of an init list or `e.operator std::initializer_list()`
183+
struct InitListCtor {
184+
InitListCtor(int);
185+
InitListCtor(InitListCtor&&) = delete;
186+
InitListCtor(std::initializer_list<InitListCtor>) = delete; // #cwg2311-InitListCtor
187+
};
188+
189+
std::initializer_list<InitListCtor> i;
190+
auto j = std::initializer_list<InitListCtor>{ i };
191+
// since-cxx17-error@-1 {{conversion function from 'std::initializer_list<InitListCtor>' to 'const cwg2311::InitListCtor' invokes a deleted function}}
192+
// since-cxx17-note@#cwg2311-InitListCtor {{'InitListCtor' has been explicitly marked deleted here}}
179193
#endif
180194
}
181195

clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ template<typename T> constexpr bool has_type(T&) { return true; }
1919

2020
std::initializer_list il1 = {1, 2, 3, 4, 5};
2121
auto il2 = std::initializer_list{1, 2, 3, 4};
22-
auto il3 = std::initializer_list{il1};
22+
auto il3 = std::initializer_list(il1);
2323
auto il4 = std::initializer_list{il1, il1, il1};
2424
static_assert(has_type<std::initializer_list<int>>(il1));
2525
static_assert(has_type<std::initializer_list<int>>(il2));
2626
static_assert(has_type<std::initializer_list<int>>(il3));
2727
static_assert(has_type<std::initializer_list<std::initializer_list<int>>>(il4));
2828

29+
auto il5 = std::initializer_list{il1};
30+
// expected-error@-1 {{no viable conversion from 'std::initializer_list<int>' to 'const int'}}
31+
2932
template<typename T> struct vector {
3033
template<typename Iter> vector(Iter, Iter);
3134
vector(std::initializer_list<T>);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
2+
3+
// This is heavily affected by the speculative resolution applied to CWG2311
4+
// So behaviour shown here is subject to change.
5+
6+
// expected-no-diagnostics
7+
8+
namespace std {
9+
typedef decltype(sizeof(int)) size_t;
10+
11+
// libc++'s implementation
12+
template <class _E>
13+
class initializer_list
14+
{
15+
const _E* __begin_;
16+
size_t __size_;
17+
18+
initializer_list(const _E* __b, size_t __s)
19+
: __begin_(__b),
20+
__size_(__s)
21+
{}
22+
23+
public:
24+
typedef _E value_type;
25+
typedef const _E& reference;
26+
typedef const _E& const_reference;
27+
typedef size_t size_type;
28+
29+
typedef const _E* iterator;
30+
typedef const _E* const_iterator;
31+
32+
constexpr initializer_list() : __begin_(nullptr), __size_(0) {}
33+
34+
constexpr size_t size() const {return __size_;}
35+
const _E* begin() const {return __begin_;}
36+
const _E* end() const {return __begin_ + __size_;}
37+
};
38+
39+
template<typename T>
40+
struct vector {
41+
size_t sz;
42+
constexpr vector() : sz(0) {}
43+
constexpr vector(initializer_list<T> ilist) : sz(ilist.size()) {}
44+
constexpr vector(const vector& other) : sz(other.sz) {}
45+
constexpr std::size_t size() const { return sz; }
46+
};
47+
}
48+
49+
// https://github.com/llvm/llvm-project/pull/77768#issuecomment-1908062472
50+
namespace Issue1 {
51+
struct A {
52+
constexpr A() {}
53+
};
54+
55+
struct B {
56+
int called_ctor;
57+
constexpr explicit B(A) : called_ctor(0) {}
58+
constexpr explicit B(std::vector<A>) : called_ctor(1) {}
59+
};
60+
61+
struct C {
62+
B b;
63+
constexpr C() : b({A()}) {}
64+
};
65+
66+
static_assert(C().b.called_ctor == 0);
67+
}
68+
69+
// https://github.com/llvm/llvm-project/pull/77768#issuecomment-1957171805
70+
namespace Issue2 {
71+
struct A {
72+
constexpr A(int x_) {}
73+
constexpr A(const std::vector<A>& a) {}
74+
};
75+
76+
void f() {
77+
constexpr std::vector<A> a{1,2};
78+
constexpr std::vector<A> b{a};
79+
// -> constexpr std::vector<A> b(std::initializer_list<A>{ A(a) });
80+
static_assert(b.size() == 1);
81+
}
82+
}

0 commit comments

Comments
 (0)