355 lines
8.5 KiB
C++
355 lines
8.5 KiB
C++
|
// 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}}
|