| // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s |
| |
| // --------------------------------------------------------------------- |
| // C++ Functional Casts |
| // --------------------------------------------------------------------- |
| template<int N> |
| struct ValueInit0 { |
| int f() { |
| return int(); |
| } |
| }; |
| |
| template struct ValueInit0<5>; |
| |
| template<int N> |
| struct FunctionalCast0 { |
| int f() { |
| return int(N); |
| } |
| }; |
| |
| template struct FunctionalCast0<5>; |
| |
| struct X { // expected-note 3 {{candidate constructor (the implicit copy constructor)}} |
| X(int, int); // expected-note 3 {{candidate constructor}} |
| }; |
| |
| template<int N, int M> |
| struct BuildTemporary0 { |
| X f() { |
| return X(N, M); |
| } |
| }; |
| |
| template struct BuildTemporary0<5, 7>; |
| |
| template<int N, int M> |
| struct Temporaries0 { |
| void f() { |
| (void)X(N, M); |
| } |
| }; |
| |
| template struct Temporaries0<5, 7>; |
| |
| // Ensure that both the constructor and the destructor are instantiated by |
| // checking for parse errors from each. |
| template<int N> struct BadX { |
| BadX() { int a[-N]; } // expected-error {{array with a negative size}} |
| ~BadX() { int a[-N]; } // expected-error {{array with a negative size}} |
| }; |
| |
| template<int N> |
| struct PR6671 { |
| void f() { (void)BadX<1>(); } // expected-note 2 {{instantiation}} |
| }; |
| template struct PR6671<1>; |
| |
| // --------------------------------------------------------------------- |
| // new/delete expressions |
| // --------------------------------------------------------------------- |
| struct Y { }; |
| |
| template<typename T> |
| struct New0 { |
| T* f(bool x) { |
| if (x) |
| return new T; // expected-error{{no matching}} |
| else |
| return new T(); |
| } |
| }; |
| |
| template struct New0<int>; |
| template struct New0<Y>; |
| template struct New0<X>; // expected-note{{instantiation}} |
| |
| template<typename T, typename Arg1> |
| struct New1 { |
| T* f(bool x, Arg1 a1) { |
| return new T(a1); // expected-error{{no matching}} |
| } |
| }; |
| |
| template struct New1<int, float>; |
| template struct New1<Y, Y>; |
| template struct New1<X, Y>; // expected-note{{instantiation}} |
| |
| template<typename T, typename Arg1, typename Arg2> |
| struct New2 { |
| T* f(bool x, Arg1 a1, Arg2 a2) { |
| return new T(a1, a2); // expected-error{{no matching}} |
| } |
| }; |
| |
| template struct New2<X, int, float>; |
| template struct New2<X, int, int*>; // expected-note{{instantiation}} |
| // FIXME: template struct New2<int, int, float>; |
| |
| // PR5833 |
| struct New3 { |
| New3(); |
| |
| void *operator new[](__SIZE_TYPE__) __attribute__((unavailable)); // expected-note{{explicitly made unavailable}} |
| }; |
| |
| template<class C> |
| void* object_creator() { |
| return new C(); // expected-error{{call to unavailable function 'operator new[]'}} |
| } |
| |
| template void *object_creator<New3[4]>(); // expected-note{{instantiation}} |
| |
| template<typename T> |
| struct Delete0 { |
| void f(T t) { |
| delete t; // expected-error{{cannot delete}} |
| ::delete [] t; // expected-error{{cannot delete}} |
| } |
| }; |
| |
| template struct Delete0<int*>; |
| template struct Delete0<X*>; |
| template struct Delete0<int>; // expected-note{{instantiation}} |
| |
| namespace PR5755 { |
| template <class T> |
| void Foo() { |
| char* p = 0; |
| delete[] p; |
| } |
| |
| void Test() { |
| Foo<int>(); |
| } |
| } |
| |
| namespace PR10480 { |
| template<typename T> |
| struct X { |
| X(); |
| ~X() { |
| T *ptr = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} |
| } |
| }; |
| |
| template<typename T> |
| void f() { |
| new X<int>[1]; // expected-note{{in instantiation of member function 'PR10480::X<int>::~X' requested here}} |
| } |
| |
| template void f<int>(); |
| } |
| |
| // --------------------------------------------------------------------- |
| // throw expressions |
| // --------------------------------------------------------------------- |
| template<typename T> |
| struct Throw1 { |
| void f(T t) { |
| throw; |
| throw t; // expected-error{{incomplete type}} |
| } |
| }; |
| |
| struct Incomplete; // expected-note 2{{forward}} |
| |
| template struct Throw1<int>; |
| template struct Throw1<int*>; |
| template struct Throw1<Incomplete*>; // expected-note{{instantiation}} |
| |
| // --------------------------------------------------------------------- |
| // typeid expressions |
| // --------------------------------------------------------------------- |
| |
| namespace std { |
| class type_info; |
| } |
| |
| template<typename T> |
| struct TypeId0 { |
| const std::type_info &f(T* ptr) { |
| if (ptr) |
| return typeid(ptr); |
| else |
| return typeid(T); // expected-error{{'typeid' of incomplete type 'Incomplete'}} |
| } |
| }; |
| |
| struct Abstract { |
| virtual void f() = 0; |
| }; |
| |
| template struct TypeId0<int>; |
| template struct TypeId0<Incomplete>; // expected-note{{instantiation of member function}} |
| template struct TypeId0<Abstract>; |
| |
| // --------------------------------------------------------------------- |
| // type traits |
| // --------------------------------------------------------------------- |
| template<typename T> |
| struct is_pod { |
| static const bool value = __is_pod(T); |
| }; |
| |
| static int is_pod0[is_pod<X>::value? -1 : 1]; |
| static int is_pod1[is_pod<Y>::value? 1 : -1]; |
| |
| // --------------------------------------------------------------------- |
| // initializer lists |
| // --------------------------------------------------------------------- |
| template<typename T, typename Val1> |
| struct InitList1 { |
| void f(Val1 val1) { |
| T x = { val1 }; |
| } |
| }; |
| |
| struct APair { |
| int *x; |
| const float *y; |
| }; |
| |
| template struct InitList1<int[1], float>; |
| template struct InitList1<APair, int*>; |
| |
| template<typename T, typename Val1, typename Val2> |
| struct InitList2 { |
| void f(Val1 val1, Val2 val2) { |
| T x = { val1, val2 }; // expected-error{{cannot initialize}} |
| } |
| }; |
| |
| template struct InitList2<APair, int*, float*>; |
| template struct InitList2<APair, int*, double*>; // expected-note{{instantiation}} |
| |
| // --------------------------------------------------------------------- |
| // member references |
| // --------------------------------------------------------------------- |
| template<typename T, typename Result> |
| struct DotMemRef0 { |
| void f(T t) { |
| Result result = t.m; // expected-error{{non-const lvalue reference to type}} |
| } |
| }; |
| |
| struct MemInt { |
| int m; |
| }; |
| |
| struct InheritsMemInt : MemInt { }; |
| |
| struct MemIntFunc { |
| static int m(int); |
| }; |
| |
| template struct DotMemRef0<MemInt, int&>; |
| template struct DotMemRef0<InheritsMemInt, int&>; |
| template struct DotMemRef0<MemIntFunc, int (*)(int)>; |
| template struct DotMemRef0<MemInt, float&>; // expected-note{{instantiation}} |
| |
| template<typename T, typename Result> |
| struct ArrowMemRef0 { |
| void f(T t) { |
| Result result = t->m; // expected-error 2{{non-const lvalue reference}} |
| } |
| }; |
| |
| template<typename T> |
| struct ArrowWrapper { |
| T operator->(); |
| }; |
| |
| template struct ArrowMemRef0<MemInt*, int&>; |
| template struct ArrowMemRef0<InheritsMemInt*, int&>; |
| template struct ArrowMemRef0<MemIntFunc*, int (*)(int)>; |
| template struct ArrowMemRef0<MemInt*, float&>; // expected-note{{instantiation}} |
| |
| template struct ArrowMemRef0<ArrowWrapper<MemInt*>, int&>; |
| template struct ArrowMemRef0<ArrowWrapper<InheritsMemInt*>, int&>; |
| template struct ArrowMemRef0<ArrowWrapper<MemIntFunc*>, int (*)(int)>; |
| template struct ArrowMemRef0<ArrowWrapper<MemInt*>, float&>; // expected-note{{instantiation}} |
| template struct ArrowMemRef0<ArrowWrapper<ArrowWrapper<MemInt*> >, int&>; |
| |
| struct UnresolvedMemRefArray { |
| int f(int); |
| int f(char); |
| }; |
| UnresolvedMemRefArray Arr[10]; |
| template<typename U> int UnresolvedMemRefArrayT(U u) { |
| return Arr->f(u); |
| } |
| template int UnresolvedMemRefArrayT<int>(int); |
| |
| // FIXME: we should be able to return a MemInt without the reference! |
| MemInt &createMemInt(int); |
| |
| template<int N> |
| struct NonDepMemberExpr0 { |
| void f() { |
| createMemInt(N).m = N; |
| } |
| }; |
| |
| template struct NonDepMemberExpr0<0>; |
| |
| template<typename T, typename Result> |
| struct MemberFuncCall0 { |
| void f(T t) { |
| Result result = t.f(); |
| } |
| }; |
| |
| template<typename T> |
| struct HasMemFunc0 { |
| T f(); |
| }; |
| |
| |
| template struct MemberFuncCall0<HasMemFunc0<int&>, const int&>; |
| |
| template<typename Result> |
| struct ThisMemberFuncCall0 { |
| Result g(); |
| |
| void f() { |
| Result r1 = g(); |
| Result r2 = this->g(); |
| } |
| }; |
| |
| template struct ThisMemberFuncCall0<int&>; |
| |
| template<typename T> |
| struct NonDepMemberCall0 { |
| void foo(HasMemFunc0<int&> x) { |
| T result = x.f(); // expected-error{{non-const lvalue reference}} |
| } |
| }; |
| |
| template struct NonDepMemberCall0<int&>; |
| template struct NonDepMemberCall0<const int&>; |
| template struct NonDepMemberCall0<float&>; // expected-note{{instantiation}} |
| |
| |
| template<typename T> |
| struct QualifiedDeclRef0 { |
| T f() { |
| return is_pod<X>::value; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'const bool'}} |
| } |
| }; |
| |
| template struct QualifiedDeclRef0<bool>; |
| template struct QualifiedDeclRef0<int&>; // expected-note{{instantiation}} |