2009-12-16 04:14:24 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
2009-05-15 07:26:13 +08:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct X0 {
|
|
|
|
void f(T x, U y) {
|
2009-05-21 06:33:37 +08:00
|
|
|
(void)(x + y); // expected-error{{invalid operands}}
|
2009-05-15 07:26:13 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct X1 { };
|
|
|
|
|
|
|
|
template struct X0<int, float>;
|
|
|
|
template struct X0<int*, int>;
|
|
|
|
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}
|
2009-05-15 07:40:54 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct X2 {
|
|
|
|
void f(T);
|
|
|
|
|
|
|
|
T g(T x, T y) {
|
2009-05-15 08:01:03 +08:00
|
|
|
/* DeclStmt */;
|
|
|
|
T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
|
2009-05-15 07:40:54 +08:00
|
|
|
/* NullStmt */;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct X2<int>;
|
2009-05-15 08:01:03 +08:00
|
|
|
template struct X2<int&>; // expected-note{{instantiation of}}
|
2009-05-15 08:15:26 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct X3 {
|
|
|
|
void f(T) {
|
|
|
|
Label:
|
|
|
|
T x;
|
|
|
|
goto Label;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct X3<int>;
|
2009-05-15 08:48:27 +08:00
|
|
|
|
|
|
|
template <typename T> struct X4 {
|
|
|
|
T f() const {
|
|
|
|
return; // expected-warning{{non-void function 'f' should return a value}}
|
|
|
|
}
|
|
|
|
|
|
|
|
T g() const {
|
|
|
|
return 1; // expected-warning{{void function 'g' should not return a value}}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-05-19 01:01:57 +08:00
|
|
|
template struct X4<void>; // expected-note{{in instantiation of}}
|
|
|
|
template struct X4<int>; // expected-note{{in instantiation of}}
|
2009-05-16 01:59:04 +08:00
|
|
|
|
2009-05-19 04:51:54 +08:00
|
|
|
struct Incomplete; // expected-note 2{{forward declaration}}
|
2009-05-16 01:59:04 +08:00
|
|
|
|
|
|
|
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}}
|
2009-05-16 02:53:42 +08:00
|
|
|
|
|
|
|
template<typename T, typename U, typename V> struct X6 {
|
|
|
|
U f(T t, U u, V v) {
|
|
|
|
// IfStmt
|
|
|
|
if (t > 0)
|
|
|
|
return u;
|
2009-05-16 05:18:27 +08:00
|
|
|
else {
|
|
|
|
if (t < 0)
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
return v; // expected-error{{cannot initialize return object of type}}
|
2009-05-16 05:18:27 +08:00
|
|
|
}
|
|
|
|
|
2009-05-21 05:51:01 +08:00
|
|
|
if (T x = t) {
|
|
|
|
t = x;
|
|
|
|
}
|
2009-05-16 05:18:27 +08:00
|
|
|
return v;
|
2009-05-16 02:53:42 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ConvertibleToInt {
|
|
|
|
operator int() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct X6<ConvertibleToInt, float, char>;
|
|
|
|
template struct X6<bool, int, int*>; // expected-note{{instantiation}}
|
2009-05-16 04:26:03 +08:00
|
|
|
|
|
|
|
template <typename T> struct X7 {
|
|
|
|
void f() {
|
|
|
|
void *v = this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct X7<int>;
|
2009-05-16 05:45:53 +08:00
|
|
|
|
|
|
|
template<typename T> struct While0 {
|
|
|
|
void f(T t) {
|
|
|
|
while (t) {
|
|
|
|
}
|
|
|
|
|
|
|
|
while (T t2 = T()) ;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct While0<float>;
|
2009-05-16 05:56:04 +08:00
|
|
|
|
|
|
|
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}}
|
2009-05-16 06:12:32 +08:00
|
|
|
|
|
|
|
template<typename T> struct For0 {
|
|
|
|
void f(T f, T l) {
|
|
|
|
for (; f != l; ++f) {
|
2009-05-16 06:32:39 +08:00
|
|
|
if (*f)
|
|
|
|
continue;
|
|
|
|
else if (*f == 17)
|
|
|
|
break;
|
2009-05-16 06:12:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct For0<int*>;
|
2009-05-16 07:10:19 +08:00
|
|
|
|
|
|
|
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;
|
2009-07-11 05:35:09 +08:00
|
|
|
this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
|
2009-05-16 07:10:19 +08:00
|
|
|
}
|
|
|
|
};
|
2009-05-16 07:57:33 +08:00
|
|
|
|
|
|
|
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}}
|
2009-05-16 08:20:29 +08:00
|
|
|
|
|
|
|
template<typename T> struct IndirectGoto0 {
|
|
|
|
void f(T x) {
|
|
|
|
// FIXME: crummy error message below
|
|
|
|
goto *x; // expected-error{{incompatible}}
|
2009-05-23 07:25:52 +08:00
|
|
|
|
|
|
|
prior:
|
|
|
|
T prior_label = &&prior;
|
|
|
|
|
|
|
|
T later_label = &&later;
|
|
|
|
|
|
|
|
later:
|
|
|
|
(void)(1+1);
|
2009-05-16 08:20:29 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template struct IndirectGoto0<void*>;
|
|
|
|
template struct IndirectGoto0<int>; // expected-note{{instantiation}}
|
2009-05-19 04:51:54 +08:00
|
|
|
|
|
|
|
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}}
|
2009-06-13 10:59:33 +08:00
|
|
|
|
|
|
|
// PR4383
|
|
|
|
template<typename T> struct X;
|
|
|
|
template<typename T> struct Y : public X<T> {
|
|
|
|
Y& x() { return *this; }
|
|
|
|
};
|