1 // RUN: %clang_cc1 -std=c++1z -verify %s
3 template<typename T
, bool B
> using Fn
= T () noexcept(B
);
5 // - If the original A is a function pointer type, A can be "pointer to
6 // function" even if the deduced A is "pointer to noexcept function".
8 template<typename T
> operator Fn
<T
, false>*(); // expected-note {{candidate}}
11 template<typename T
> operator Fn
<T
, true>*();
15 void (*p3
)() noexcept
= A(); // expected-error {{no viable conversion}}
16 void (*p4
)() noexcept
= B();
18 // - If the original A is a pointer to member function type, A can be "pointer
19 // to member of type function" even if the deduced A is "pointer to member of
20 // type noexcept function".
22 template<typename T
> operator Fn
<T
, false> A::*(); // expected-note {{candidate}}
25 template<typename T
> operator Fn
<T
, true> A::*();
27 void (A::*q1
)() = C();
28 void (A::*q2
)() = D();
29 void (A::*q3
)() noexcept
= C(); // expected-error {{no viable conversion}}
30 void (A::*q4
)() noexcept
= D();
32 // There is no corresponding rule for references.
33 // FIXME: This seems like a defect.
34 // FIXME: We don't actually implement the final check for equal types at all!
35 // Instead, we handle the matching via [over.ics.user]p3:
36 // "If the user-defined conversion is specified by a specialization of a
37 // conversion function template, the second standard conversion sequence
38 // shall have exact match rank."
39 // Note that this *does* allow discarding noexcept, since that conversion has
42 template<typename T
> operator Fn
<T
, false>&(); // expected-note {{candidate}}
45 template<typename T
> operator Fn
<T
, true>&();
49 void (&r3
)() noexcept
= E(); // expected-error {{no viable conversion}}
50 void (&r4
)() noexcept
= F();
52 // FIXME: We reject this for entirely the wrong reason. We incorrectly succeed
53 // in deducing T = void, U = G::B, and only fail due to [over.ics.user]p3.
55 template<typename
, typename
> struct A
{};
56 template<typename U
> struct A
<U
, int> : A
<U
, void> {};
57 struct B
{ typedef int type
; };
59 template<typename T
, typename U
= B
> operator A
<T
, typename
U::type
> *(); // expected-note {{candidate function [with T = void, U = G::B]}}
61 G::A
<void, void> *g
= G(); // expected-error {{no viable conversion}}