forked from OSchip/llvm-project
62 lines
2.3 KiB
C++
62 lines
2.3 KiB
C++
// RUN: %clang_cc1 -std=c++1z -verify %s
|
|
|
|
template<typename T, bool B> using Fn = T () noexcept(B);
|
|
|
|
// - If the original A is a function pointer type, A can be "pointer to
|
|
// function" even if the deduced A is "pointer to noexcept function".
|
|
struct A {
|
|
template<typename T> operator Fn<T, false>*(); // expected-note {{candidate}}
|
|
};
|
|
struct B {
|
|
template<typename T> operator Fn<T, true>*();
|
|
};
|
|
void (*p1)() = A();
|
|
void (*p2)() = B();
|
|
void (*p3)() noexcept = A(); // expected-error {{no viable conversion}}
|
|
void (*p4)() noexcept = B();
|
|
|
|
// - If the original A is a pointer to member function type, A can be "pointer
|
|
// to member of type function" even if the deduced A is "pointer to member of
|
|
// type noexcept function".
|
|
struct C {
|
|
template<typename T> operator Fn<T, false> A::*(); // expected-note {{candidate}}
|
|
};
|
|
struct D {
|
|
template<typename T> operator Fn<T, true> A::*();
|
|
};
|
|
void (A::*q1)() = C();
|
|
void (A::*q2)() = D();
|
|
void (A::*q3)() noexcept = C(); // expected-error {{no viable conversion}}
|
|
void (A::*q4)() noexcept = D();
|
|
|
|
// There is no corresponding rule for references.
|
|
// FIXME: This seems like a defect.
|
|
// FIXME: We don't actually implement the final check for equal types at all!
|
|
// Instead, we handle the matching via [over.ics.user]p3:
|
|
// "If the user-defined conversion is specified by a specialization of a
|
|
// conversion function template, the second standard conversion sequence
|
|
// shall have exact match rank."
|
|
// Note that this *does* allow discarding noexcept, since that conversion has
|
|
// Exact Match rank.
|
|
struct E {
|
|
template<typename T> operator Fn<T, false>&(); // expected-note {{candidate}}
|
|
};
|
|
struct F {
|
|
template<typename T> operator Fn<T, true>&();
|
|
};
|
|
void (&r1)() = E();
|
|
void (&r2)() = F();
|
|
void (&r3)() noexcept = E(); // expected-error {{no viable conversion}}
|
|
void (&r4)() noexcept = F();
|
|
|
|
// FIXME: We reject this for entirely the wrong reason. We incorrectly succeed
|
|
// in deducing T = void, U = G::B, and only fail due to [over.ics.user]p3.
|
|
struct G {
|
|
template<typename, typename> struct A {};
|
|
template<typename U> struct A<U, int> : A<U, void> {};
|
|
struct B { typedef int type; };
|
|
|
|
template<typename T, typename U = B> operator A<T, typename U::type> *(); // expected-note {{candidate function [with T = void, U = G::B]}}
|
|
};
|
|
G::A<void, void> *g = G(); // expected-error {{no viable conversion}}
|