| // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s |
| template<typename T, typename U> |
| struct X0 { |
| void f(T x, U y) { |
| (void)(x + y); // expected-error{{invalid operands}} |
| } |
| }; |
| |
| struct X1 { }; |
| |
| template struct X0<int, float>; |
| template struct X0<int*, int>; |
| template struct X0<int X1::*, int>; // expected-note{{instantiation of}} |
| |
| template<typename T> |
| struct X2 { |
| void f(T); |
| |
| T g(T x, T y) { |
| /* DeclStmt */; |
| T *xp = &x, &yr = y; // expected-error{{pointer to a reference}} |
| /* NullStmt */; |
| } |
| }; |
| |
| template struct X2<int>; |
| template struct X2<int&>; // expected-note{{instantiation of}} |
| |
| template<typename T> |
| struct X3 { |
| void f(T) { |
| Label: |
| T x; |
| goto Label; |
| } |
| }; |
| |
| template struct X3<int>; |
| |
| template <typename T> struct X4 { |
| T f() const { |
| return; // expected-error{{non-void function 'f' should return a value}} |
| } |
| |
| T g() const { |
| return 1; // expected-error{{void function 'g' should not return a value}} |
| } |
| }; |
| |
| template struct X4<void>; // expected-note{{in instantiation of}} |
| template struct X4<int>; // expected-note{{in instantiation of}} |
| |
| struct Incomplete; // expected-note 2{{forward declaration}} |
| |
| template<typename T> struct X5 { |
| T f() { } // expected-error{{incomplete result type}} |
| }; |
| void test_X5(X5<Incomplete> x5); // okay! |
| |
| template struct X5<Incomplete>; // expected-note{{instantiation}} |
| |
| template<typename T, typename U, typename V> struct X6 { |
| U f(T t, U u, V v) { |
| // IfStmt |
| if (t > 0) |
| return u; |
| else { |
| if (t < 0) |
| return v; // expected-error{{cannot initialize return object of type}} |
| } |
| |
| if (T x = t) { |
| t = x; |
| } |
| return v; // expected-error{{cannot initialize return object of type}} |
| } |
| }; |
| |
| struct ConvertibleToInt { |
| operator int() const; |
| }; |
| |
| template struct X6<ConvertibleToInt, float, char>; |
| template struct X6<bool, int, int*>; // expected-note{{instantiation}} |
| |
| template <typename T> struct X7 { |
| void f() { |
| void *v = this; |
| } |
| }; |
| |
| template struct X7<int>; |
| |
| template<typename T> struct While0 { |
| void f(T t) { |
| while (t) { |
| } |
| |
| while (T t2 = T()) ; |
| } |
| }; |
| |
| template struct While0<float>; |
| |
| template<typename T> struct Do0 { |
| void f(T t) { |
| do { |
| } while (t); // expected-error{{not contextually}} |
| } |
| }; |
| |
| struct NotConvertibleToBool { }; |
| template struct Do0<ConvertibleToInt>; |
| template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}} |
| |
| template<typename T> struct For0 { |
| void f(T f, T l) { |
| for (; f != l; ++f) { |
| if (*f) |
| continue; |
| else if (*f == 17) |
| break; |
| } |
| } |
| }; |
| |
| template struct For0<int*>; |
| |
| template<typename T> struct Member0 { |
| void f(T t) { |
| t; |
| t.f; |
| t->f; |
| |
| T* tp; |
| tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}} |
| tp->f; |
| |
| this->f; |
| this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}} |
| } |
| }; |
| |
| template<typename T, typename U> struct Switch0 { |
| U f(T value, U v0, U v1, U v2) { |
| switch (value) { |
| case 0: return v0; |
| |
| case 1: return v1; |
| |
| case 2: // fall through |
| |
| default: |
| return v2; |
| } |
| } |
| }; |
| |
| template struct Switch0<int, float>; |
| |
| template<typename T, int I1, int I2> struct Switch1 { |
| T f(T x, T y, T z) { |
| switch (x) { |
| case I1: return y; // expected-note{{previous}} |
| case I2: return z; // expected-error{{duplicate}} |
| default: return x; |
| } |
| } |
| }; |
| |
| template struct Switch1<int, 1, 2>; |
| template struct Switch1<int, 2, 2>; // expected-note{{instantiation}} |
| |
| template<typename T> struct IndirectGoto0 { |
| void f(T x) { |
| // FIXME: crummy error message below |
| goto *x; // expected-error{{incompatible}} |
| |
| prior: |
| T prior_label; |
| prior_label = &&prior; // expected-error{{assigning to 'int'}} |
| |
| T later_label; |
| later_label = &&later; // expected-error{{assigning to 'int'}} |
| |
| later: |
| (void)(1+1); |
| } |
| }; |
| |
| template struct IndirectGoto0<void*>; |
| template struct IndirectGoto0<int>; // expected-note{{instantiation}} |
| |
| template<typename T> struct TryCatch0 { |
| void f() { |
| try { |
| } catch (T t) { // expected-error{{incomplete type}} \ |
| // expected-error{{abstract class}} |
| } catch (...) { |
| } |
| } |
| }; |
| |
| struct Abstract { |
| virtual void foo() = 0; // expected-note{{pure virtual}} |
| }; |
| |
| template struct TryCatch0<int>; // okay |
| template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}} |
| template struct TryCatch0<Abstract>; // expected-note{{instantiation}} |
| |
| // PR4383 |
| template<typename T> struct X; |
| template<typename T> struct Y : public X<T> { |
| Y& x() { return *this; } |
| }; |
| |
| // Make sure our assertions don't get too uppity. |
| namespace test0 { |
| template <class T> class A { void foo(T array[10]); }; |
| template class A<int>; |
| } |
| |
| namespace PR7016 { |
| template<typename T> void f() { T x = x; } |
| template void f<int>(); |
| } |
| |
| namespace PR9880 { |
| struct lua_State; |
| struct no_tag { char a; }; // (A) |
| struct yes_tag { long a; long b; }; // (A) |
| |
| template <typename T> |
| struct HasIndexMetamethod { |
| template <typename U> |
| static no_tag check(...); |
| template <typename U> |
| static yes_tag check(char[sizeof(&U::luaIndex)]); |
| enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) }; |
| }; |
| |
| class SomeClass { |
| public: |
| int luaIndex(lua_State* L); |
| }; |
| |
| int i = HasIndexMetamethod<SomeClass>::value; |
| } |