62 lines · cpp
1// RUN: %clang_cc1 -std=c++1z -verify %s2 3template<typename T, bool B> using Fn = T () noexcept(B);4 5// - If the original A is a function pointer type, A can be "pointer to6// function" even if the deduced A is "pointer to noexcept function".7struct A {8 template<typename T> operator Fn<T, false>*(); // expected-note {{candidate}}9};10struct B {11 template<typename T> operator Fn<T, true>*();12};13void (*p1)() = A();14void (*p2)() = B();15void (*p3)() noexcept = A(); // expected-error {{no viable conversion}}16void (*p4)() noexcept = B();17 18// - If the original A is a pointer to member function type, A can be "pointer19// to member of type function" even if the deduced A is "pointer to member of20// type noexcept function".21struct C {22 template<typename T> operator Fn<T, false> A::*(); // expected-note {{candidate}}23};24struct D {25 template<typename T> operator Fn<T, true> A::*();26};27void (A::*q1)() = C();28void (A::*q2)() = D();29void (A::*q3)() noexcept = C(); // expected-error {{no viable conversion}}30void (A::*q4)() noexcept = D();31 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 a37// conversion function template, the second standard conversion sequence38// shall have exact match rank."39// Note that this *does* allow discarding noexcept, since that conversion has40// Exact Match rank.41struct E {42 template<typename T> operator Fn<T, false>&(); // expected-note {{candidate}}43};44struct F {45 template<typename T> operator Fn<T, true>&();46};47void (&r1)() = E();48void (&r2)() = F();49void (&r3)() noexcept = E(); // expected-error {{no viable conversion}}50void (&r4)() noexcept = F();51 52// FIXME: We reject this for entirely the wrong reason. We incorrectly succeed53// in deducing T = void, U = G::B, and only fail due to [over.ics.user]p3.54struct G {55 template<typename, typename> struct A {};56 template<typename U> struct A<U, int> : A<U, void> {};57 struct B { typedef int type; };58 59 template<typename T, typename U = B> operator A<T, typename U::type> *(); // expected-note {{candidate function [with T = void, U = G::B]}}60};61G::A<void, void> *g = G(); // expected-error {{no viable conversion}}62