Clang Project

clang_source_code/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
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
4
5struct AnyT {
6  template<typename T>
7  operator T();
8};
9
10void test_cvqual_ref(AnyT any) {
11  const int &cir = any;  
12}
13
14struct AnyThreeLevelPtr {
15  template<typename T>
16  operator T***() const {
17    T x = 0; // expected-note 2{{declared const here}}
18    x = 0; // expected-error 2{{const-qualified type}}
19    T ***p;
20    return p;
21  }
22};
23
24struct X { };
25
26void 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}}
32}
33
34struct AnyPtrMem {
35  template<typename Class, typename T>
36  operator T Class::*() const
37  {
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}}
42    return 0;
43  }
44};
45
46void test_deduce_ptrmem_with_qual(AnyPtrMem apm) {
47  const float X::* pm = apm; // expected-note {{instantiation of}}
48}
49
50struct TwoLevelPtrMem {
51  template<typename Class1, typename Class2, typename T>
52  operator T Class1::*Class2::*() const
53  {
54    T x = 0; // expected-note 2{{declared const here}}
55    x = 0; // expected-error 2{{const-qualified type}}
56    return 0;
57  }
58};
59
60void 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}}
66}
67
68namespace non_ptr_ref_cv_qual {
69  template<typename Expected>
70  struct ConvToT {
71    template<typename T> operator T() {
72      using Check = T;
73      using Check = Expected;
74    }
75  };
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>();
82
83  // Example code that would be broken by the standard's rule.
84  struct Dest {};
85  Dest d1a((ConvToT<Dest>()));
86  Dest d1b = ConvToT<Dest>();
87  Dest &d2 = (d1a = ConvToT<Dest>());
88
89  template<typename Expected>
90  struct ConvToTRef {
91    template<typename T> operator T&() {
92      using Check = T;
93      using Check = Expected;
94    }
95  };
96  const int test_conv_to_t_ref_1 = ConvToTRef<int>();
97  const int &test_conv_to_t_ref_2 = ConvToTRef<const int>();
98
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>());
102
103  template<typename Expected>
104  struct ConvToConstT {
105    template<typename T> operator const T() {
106      using Check = T;
107      using Check = Expected;
108    }
109  };
110  const int test_conv_to_const_t_1 = ConvToConstT<int>();
111  const int &test_conv_to_const_t_2 = ConvToConstT<int>();
112
113  template<typename Expected>
114  struct ConvToConstTRef {
115    template<typename T> operator const T&() {
116      using Check = T;
117      using Check = Expected;
118    }
119  };
120  const int test_conv_to_const_t_ref_1 = ConvToConstTRef<int>();
121  const int &test_conv_to_const_t_ref_2 = ConvToConstTRef<int>();
122
123  template <typename T, int N> using Arr = T[N];
124  struct ConvToArr {
125    template <int N>
126    operator Arr<int, N> &() {
127      static_assert(N == 3, "");
128    }
129  };
130  int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok
131  const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion
132
133#if __cplusplus >= 201702L
134  template<bool Noexcept, typename T, typename ...U> using Function = T(U...) noexcept(Noexcept);
135  template<bool Noexcept> struct ConvToFunction {
136    template <typename T, typename ...U> operator Function<Noexcept, T, U...>&(); // expected-note {{candidate}}
137  };
138  void (&fn1)(int) noexcept(false) = ConvToFunction<false>();
139  void (&fn2)(int) noexcept(true)  = ConvToFunction<false>(); // expected-error {{no viable}}
140  void (&fn3)(int) noexcept(false) = ConvToFunction<true>();
141  void (&fn4)(int) noexcept(true)  = ConvToFunction<true>();
142
143  struct ConvToFunctionDeducingNoexcept {
144    template <bool Noexcept, typename T, typename ...U> operator Function<Noexcept, T, U...>&();
145  };
146  void (&fn5)(int) noexcept(false) = ConvToFunctionDeducingNoexcept();
147  void (&fn6)(int) noexcept(true)  = ConvToFunctionDeducingNoexcept();
148#endif
149}
150