cxx1y-contextual-conversion-tweaks.cpp
6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11 -fsyntax-only -pedantic-errors %s
// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -pedantic-errors %s -DCXX1Y
// Explicit member declarations behave as in C++11.
namespace n3323_example {
template <class T> class zero_init {
public:
zero_init() : val(static_cast<T>(0)) {}
zero_init(T val) : val(val) {}
operator T &() { return val; } //@13
operator T() const { return val; } //@14
private:
T val;
};
void Delete() {
zero_init<int *> p;
p = new int(7);
delete p; //@23
delete (p + 0);
delete + p;
}
void Switch() {
zero_init<int> i;
i = 7;
switch (i) {} // @31
switch (i + 0) {}
switch (+i) {}
}
}
#ifdef CXX1Y
#else
//expected-error@23 {{ambiguous conversion of delete expression of type 'zero_init<int *>' to a pointer}}
//expected-note@13 {{conversion to pointer type 'int *'}}
//expected-note@14 {{conversion to pointer type 'int *'}}
//expected-error@31 {{multiple conversions from switch condition type 'zero_init<int>' to an integral or enumeration type}}
//expected-note@13 {{conversion to integral type 'int'}}
//expected-note@14 {{conversion to integral type 'int'}}
#endif
namespace extended_examples {
struct A0 {
operator int(); // matching and viable
};
struct A1 {
operator int() &&; // matching and not viable
};
struct A2 {
operator float(); // not matching
};
struct A3 {
template<typename T> operator T(); // not matching (ambiguous anyway)
};
struct A4 {
template<typename T> operator int(); // not matching (ambiguous anyway)
};
struct B1 {
operator int() &&; // @70
operator int(); // @71 -- duplicate declaration with different qualifier is not allowed
};
struct B2 {
operator int() &&; // matching but not viable
operator float(); // not matching
};
void foo(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, B2 b2) {
switch (a0) {}
switch (a1) {} // @81 -- fails for different reasons
switch (a2) {} // @82
switch (a3) {} // @83
switch (a4) {} // @84
switch (b2) {} // @85 -- fails for different reasons
}
}
//expected-error@71 {{cannot overload a member function without a ref-qualifier with a member function with ref-qualifier '&&'}}
//expected-note@70 {{previous declaration is here}}
//expected-error@82 {{statement requires expression of integer type ('extended_examples::A2' invalid)}}
//expected-error@83 {{statement requires expression of integer type ('extended_examples::A3' invalid)}}
//expected-error@84 {{statement requires expression of integer type ('extended_examples::A4' invalid)}}
#ifdef CXX1Y
//expected-error@81 {{statement requires expression of integer type ('extended_examples::A1' invalid)}}
//expected-error@85 {{statement requires expression of integer type ('extended_examples::B2' invalid)}}
#else
//expected-error@81 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@54 {{'operator int' declared here}}
//expected-error@85 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@75 {{'operator int' declared here}}
#endif
namespace extended_examples_cxx1y {
struct A1 { // leads to viable match in C++1y, and no viable match in C++11
operator int() &&; // matching but not viable
template <typename T> operator T(); // In C++1y: matching and viable, since disambiguated by L.100
};
struct A2 { // leads to ambiguity in C++1y, and no viable match in C++11
operator int() &&; // matching but not viable
template <typename T> operator int(); // In C++1y: matching but ambiguous (disambiguated by L.105).
};
struct B1 { // leads to one viable match in both cases
operator int(); // matching and viable
template <typename T> operator T(); // In C++1y: matching and viable, since disambiguated by L.110
};
struct B2 { // leads to one viable match in both cases
operator int(); // matching and viable
template <typename T> operator int(); // In C++1y: matching but ambiguous, since disambiguated by L.115
};
struct C { // leads to no match in both cases
operator float(); // not matching
template <typename T> operator T(); // In C++1y: not matching, nor viable.
};
struct D { // leads to viable match in C++1y, and no viable match in C++11
operator int() &&; // matching but not viable
operator float(); // not matching
template <typename T> operator T(); // In C++1y: matching and viable, since disambiguated by L.125
};
void foo(A1 a1, A2 a2, B1 b1, B2 b2, C c, D d) {
switch (a1) {} // @138 -- should presumably call templated conversion operator to convert to int.
switch (a2) {} // @139
switch (b1) {}
switch (b2) {}
switch (c) {} // @142
switch (d) {} // @143
}
}
//expected-error@142 {{statement requires expression of integer type ('extended_examples_cxx1y::C' invalid)}}
#ifdef CXX1Y
//expected-error@139 {{statement requires expression of integer type ('extended_examples_cxx1y::A2' invalid)}}
#else
//expected-error@138 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@106 {{'operator int' declared here}}
//expected-error@139 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@111 {{'operator int' declared here}}
//expected-error@143 {{'this' argument to member function 'operator int' is an lvalue, but function has rvalue ref-qualifier}} expected-note@131 {{'operator int' declared here}}
#endif
namespace extended_examples_array_bounds {
typedef decltype(sizeof(int)) size_t;
struct X {
constexpr operator size_t() const { return 1; } // cxx11-note 3{{conversion}}
constexpr operator unsigned short() const { return 0; } // cxx11-note 3{{conversion}}
};
void f() {
X x;
int *p = new int[x]; // cxx11-error {{ambiguous}}
int arr[x]; // cxx11-error {{ambiguous}}
int (*q)[1] = new int[1][x]; // cxx11-error {{ambiguous}}
}
struct Y {
constexpr operator float() const { return 0.0f; } // cxx14-note 3{{candidate}}
constexpr operator int() const { return 1; } // cxx14-note 3{{candidate}}
};
void g() {
Y y;
int *p = new int[y]; // cxx14-error {{ambiguous}}
int arr[y]; // cxx14-error {{ambiguous}}
int (*q)[1] = new int[1][y]; // cxx14-error {{ambiguous}}
}
template<int N> struct Z {
constexpr operator int() const { return N; }
};
void h() {
int arrA[Z<1>()];
int arrB[Z<0>()]; // expected-error {{zero size array}}
int arrC[Z<-1>()]; // expected-error {{'arrC' declared as an array with a negative size}}
}
}