1 // RUN: %clang_cc1 -fsyntax-only %s -verify
2 // RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify
3 // RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
10 void test_cvqual_ref(AnyT any
) {
14 struct AnyThreeLevelPtr
{
16 operator T
***() const {
17 T x
= 0; // expected-note 2{{declared const here}}
18 x
= 0; // expected-error 2{{const-qualified type}}
26 void test_deduce_with_qual(AnyThreeLevelPtr a3
) {
27 int * const * const * const ip1
= a3
;
28 // FIXME: This is wrong; we are supposed to deduce 'T = int' here.
29 const int * const * const * const ip2
= a3
; // expected-note {{instantiation of}}
30 // This one is correct, though.
31 const double * * * ip3
= a3
; // expected-note {{instantiation of}}
35 template<typename Class
, typename T
>
36 operator T
Class::*() const
38 // This is correct: we don't need a qualification conversion here, so we
39 // deduce 'T = const float'.
40 T x
= 0; // expected-note {{declared const here}}
41 x
= 0; // expected-error {{const-qualified type}}
46 void test_deduce_ptrmem_with_qual(AnyPtrMem apm
) {
47 const float X::* pm
= apm
; // expected-note {{instantiation of}}
50 struct TwoLevelPtrMem
{
51 template<typename Class1
, typename Class2
, typename T
>
52 operator T
Class1::*Class2::*() const
54 T x
= 0; // expected-note 2{{declared const here}}
55 x
= 0; // expected-error 2{{const-qualified type}}
60 void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm
) {
61 // FIXME: This is wrong: we should deduce T = 'float'
62 const float X::* const X::* pm2
= apm
; // expected-note {{instantiation of}}
63 // This is correct: we don't need a qualification conversion, so we directly
64 // deduce T = 'const double'
65 const double X::* X::* pm1
= apm
; // expected-note {{instantiation of}}
68 namespace non_ptr_ref_cv_qual
{
69 template<typename Expected
>
71 template<typename T
> operator T() {
73 using Check
= Expected
;
76 const int test_conv_to_t_1
= ConvToT
<int>();
77 // We intentionally deviate from [temp.deduct.conv]p4 here, and also remove
78 // the top-level cv-quaifiers from A *after* removing the reference type, if
79 // P is not also a reference type. This matches what other compilers are
80 // doing, and is necessary to support real-world code.
81 const int &test_conv_to_t_2
= ConvToT
<int>();
83 // Example code that would be broken by the standard's rule.
85 Dest
d1a((ConvToT
<Dest
>()));
86 Dest d1b
= ConvToT
<Dest
>();
87 Dest
&d2
= (d1a
= ConvToT
<Dest
>());
89 template<typename Expected
>
91 template<typename T
> operator T
&() {
93 using Check
= Expected
;
96 const int test_conv_to_t_ref_1
= ConvToTRef
<int>();
97 const int &test_conv_to_t_ref_2
= ConvToTRef
<const int>();
99 Dest
d3a((ConvToTRef
<const Dest
>())); // initialize the copy ctor parameter with 'const Dest&'
100 Dest d3b
= ConvToTRef
<Dest
>(); // convert to non-const T via [over.match.copy]/1.2
101 Dest
&d4
= (d3a
= ConvToTRef
<const Dest
>());
103 template<typename Expected
>
104 struct ConvToConstT
{
105 template<typename T
> operator const T() {
107 using Check
= Expected
;
110 const int test_conv_to_const_t_1
= ConvToConstT
<int>();
111 const int &test_conv_to_const_t_2
= ConvToConstT
<int>();
113 template<typename Expected
>
114 struct ConvToConstTRef
{
115 template<typename T
> operator const T
&() {
117 using Check
= Expected
;
120 const int test_conv_to_const_t_ref_1
= ConvToConstTRef
<int>();
121 const int &test_conv_to_const_t_ref_2
= ConvToConstTRef
<int>();
123 template <typename T
, int N
> using Arr
= T
[N
];
126 operator Arr
<int, N
> &() {
127 static_assert(N
== 3, "");
130 int (&test_conv_to_arr_1
)[3] = ConvToArr(); // ok
131 const int (&test_conv_to_arr_2
)[3] = ConvToArr(); // ok, with qualification conversion
133 struct ConvToConstArr
{
135 operator const Arr
<int, N
> &() { // expected-note {{candidate}}
136 static_assert(N
== 3, "");
139 Arr
<int, 3> &test_conv_to_const_arr_1
= ConvToConstArr(); // expected-error {{no viable}}
140 const Arr
<int, 3> &test_conv_to_const_arr_2
= ConvToConstArr(); // ok
142 #if __cplusplus >= 201702L
143 template<bool Noexcept
, typename T
, typename
...U
> using Function
= T(U
...) noexcept(Noexcept
);
144 template<bool Noexcept
> struct ConvToFunction
{
145 template <typename T
, typename
...U
> operator Function
<Noexcept
, T
, U
...>&(); // expected-note {{candidate}}
147 void (&fn1
)(int) noexcept(false) = ConvToFunction
<false>();
148 void (&fn2
)(int) noexcept(true) = ConvToFunction
<false>(); // expected-error {{no viable}}
149 void (&fn3
)(int) noexcept(false) = ConvToFunction
<true>();
150 void (&fn4
)(int) noexcept(true) = ConvToFunction
<true>();
152 struct ConvToFunctionDeducingNoexcept
{
153 template <bool Noexcept
, typename T
, typename
...U
> operator Function
<Noexcept
, T
, U
...>&();
155 void (&fn5
)(int) noexcept(false) = ConvToFunctionDeducingNoexcept();
156 void (&fn6
)(int) noexcept(true) = ConvToFunctionDeducingNoexcept();