blob: 7f1b3b0f240ed8bad20edfcf1d85e26100c479e5 [file] [log] [blame]
// RUN: %clang_cc1 -std=c++11 -verify %s
namespace std_example {
template<class T> struct A { ~A() = delete; }; // expected-note {{deleted here}}
template<class T> auto h() -> A<T>;
template<class T> auto i(T) -> T;
template<class T> auto f(T) -> decltype(i(h<T>())); // #1
template<class T> auto f(T) -> void; // #2
auto g() -> void {
f(42); // ok, calls #2, since #1 is not viable.
}
template<class T> auto q(T) -> decltype((h<T>()));
void r() {
// Deduction against q succeeds, but results in a temporary which can't be
// destroyed.
q(42); // expected-error {{attempt to use a deleted function}}
}
}
class PD {
friend struct A;
~PD(); // expected-note 5{{here}}
public:
typedef int n;
};
struct DD {
~DD() = delete; // expected-note 2{{here}}
typedef int n;
};
PD pd();
DD dd();
struct A {
decltype(pd()) s; // ok
decltype(pd())::n n; // ok
decltype(dd()) *p = new decltype(dd()); // ok
};
A a();
// Two errors here: one for the decltype, one for the variable.
decltype(
pd(), // expected-error {{private destructor}}
pd()) pd1; // expected-error {{private destructor}}
decltype(dd(), // expected-error {{deleted function}}
dd()) dd1;
decltype(a(),
dd()) dd2; // expected-error {{deleted function}}
decltype(
pd(), // expected-error {{temporary of type 'PD' has private destructor}}
0) pd2;
decltype(((13, ((dd())))))::n dd_parens; // ok
decltype(((((42)), pd())))::n pd_parens_comma; // ok
// Ensure parens aren't stripped from a decltype node.
extern decltype(pd()) pd_ref; // ok
decltype((pd_ref)) pd_ref3 = pd_ref; // ok, PD &
decltype(pd_ref) pd_ref2 = pd_ref; // expected-error {{private destructor}}
namespace libcxx_example {
struct nat {
nat() = delete;
nat(const nat&) = delete;
nat &operator=(const nat&) = delete;
~nat() = delete;
};
struct any {
any(...);
};
template<typename T, typename U> struct is_same { static const bool value = false; };
template<typename T> struct is_same<T, T> { static const bool value = true; };
template<typename T> T declval();
void swap(int &a, int &b);
nat swap(any, any);
template<typename T> struct swappable {
typedef decltype(swap(declval<T&>(), declval<T&>())) type;
static const bool value = !is_same<type, nat>::value;
constexpr operator bool() const { return value; }
};
static_assert(swappable<int>(), "");
static_assert(!swappable<const int>(), "");
}
namespace RequireCompleteType {
template<int N, bool OK> struct S {
static_assert(OK, "boom!"); // expected-error 2{{boom!}}
};
template<typename T> T make();
template<int N, bool OK> S<N, OK> make();
void consume(...);
decltype(make<0, false>()) *p1; // ok
decltype((make<1, false>())) *p2; // ok
// A complete type is required here in order to detect an overloaded 'operator,'.
decltype(123, make<2, false>()) *p3; // expected-note {{here}}
decltype(consume(make<3, false>())) *p4; // expected-note {{here}}
decltype(make<decltype(make<4, false>())>()) *p5; // ok
}
namespace Overload {
DD operator+(PD &a, PD &b);
decltype(pd()) *pd_ptr;
decltype(*pd_ptr + *pd_ptr) *dd_ptr; // ok
decltype(0, *pd_ptr) pd_ref2 = pd_ref; // ok
DD operator,(int a, PD b);
decltype(0, *pd_ptr) *dd_ptr2; // expected-error {{private destructor}}
}