2009-12-16 04:14:24 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
2009-03-24 07:06:20 +08:00
|
|
|
template<typename T>
|
|
|
|
class X {
|
|
|
|
public:
|
2009-03-24 08:38:23 +08:00
|
|
|
void f(T x); // expected-error{{argument may not have 'void' type}}
|
2009-03-24 07:06:20 +08:00
|
|
|
void g(T*);
|
|
|
|
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
static int h(T, T); // expected-error {{argument may not have 'void' type}}
|
2009-03-24 07:06:20 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
int identity(int x) { return x; }
|
|
|
|
|
|
|
|
void test(X<int> *xi, int *ip, X<int(int)> *xf) {
|
|
|
|
xi->f(17);
|
|
|
|
xi->g(ip);
|
|
|
|
xf->f(&identity);
|
|
|
|
xf->g(identity);
|
|
|
|
X<int>::h(17, 25);
|
|
|
|
X<int(int)>::h(identity, &identity);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_bad() {
|
2010-03-10 19:27:22 +08:00
|
|
|
X<void> xv; // expected-note{{in instantiation of template class 'X<void>' requested here}}
|
2009-03-24 07:06:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
class Overloading {
|
|
|
|
public:
|
|
|
|
int& f(T, T); // expected-note{{previous declaration is here}}
|
|
|
|
float& f(T, U); // expected-error{{functions that differ only in their return type cannot be overloaded}}
|
|
|
|
};
|
|
|
|
|
|
|
|
void test_ovl(Overloading<int, long> *oil, int i, long l) {
|
|
|
|
int &ir = oil->f(i, i);
|
|
|
|
float &fr = oil->f(i, l);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_ovl_bad() {
|
2010-03-10 19:27:22 +08:00
|
|
|
Overloading<float, float> off; // expected-note{{in instantiation of template class 'Overloading<float, float>' requested here}}
|
2009-03-24 07:06:20 +08:00
|
|
|
}
|
2009-03-24 08:15:49 +08:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class HasDestructor {
|
2009-03-25 00:43:20 +08:00
|
|
|
public:
|
2009-03-24 08:15:49 +08:00
|
|
|
virtual ~HasDestructor() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
|
|
|
|
// the code below should probably instantiate by itself.
|
|
|
|
int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1];
|
2009-03-25 00:43:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class Constructors {
|
|
|
|
public:
|
|
|
|
Constructors(const T&);
|
|
|
|
Constructors(const Constructors &other);
|
|
|
|
};
|
|
|
|
|
|
|
|
void test_constructors() {
|
|
|
|
Constructors<int> ci1(17);
|
|
|
|
Constructors<int> ci2 = ci1;
|
|
|
|
}
|
2009-03-25 08:34:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct ConvertsTo {
|
|
|
|
operator T();
|
|
|
|
};
|
|
|
|
|
|
|
|
void test_converts_to(ConvertsTo<int> ci, ConvertsTo<int *> cip) {
|
|
|
|
int i = ci;
|
|
|
|
int *ip = cip;
|
|
|
|
}
|
2009-08-24 23:23:48 +08:00
|
|
|
|
|
|
|
// PR4660
|
|
|
|
template<class T> struct A0 { operator T*(); };
|
|
|
|
template<class T> struct A1;
|
|
|
|
|
|
|
|
int *a(A0<int> &x0, A1<int> &x1) {
|
|
|
|
int *y0 = x0;
|
2009-12-19 16:11:05 +08:00
|
|
|
int *y1 = x1; // expected-error{{no viable conversion}}
|
2009-08-24 23:23:48 +08:00
|
|
|
}
|
2009-11-02 01:08:18 +08:00
|
|
|
|
|
|
|
struct X0Base {
|
|
|
|
int &f();
|
2009-11-20 08:59:20 +08:00
|
|
|
int& g(int);
|
|
|
|
static double &g(double);
|
2009-11-02 01:08:18 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct X0 : X0Base {
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
struct X1 : X0<U> {
|
2009-11-20 08:59:20 +08:00
|
|
|
int &f2() {
|
2009-12-02 06:10:20 +08:00
|
|
|
return X0Base::f();
|
2009-11-20 08:59:20 +08:00
|
|
|
}
|
2009-11-02 01:08:18 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
void test_X1(X1<int> x1i) {
|
|
|
|
int &ir = x1i.f2();
|
|
|
|
}
|
2009-11-20 08:59:20 +08:00
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
struct X2 : X0Base, U {
|
|
|
|
int &f2() { return X0Base::f(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct X3 {
|
|
|
|
void test(T x) {
|
|
|
|
double& d1 = X0Base::g(x);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template struct X3<double>;
|
2010-04-14 09:27:20 +08:00
|
|
|
|
|
|
|
// Don't try to instantiate this, it's invalid.
|
|
|
|
namespace test1 {
|
|
|
|
template <class T> class A {};
|
|
|
|
template <class T> class B {
|
|
|
|
void foo(A<test1::Undeclared> &a) // expected-error {{no member named 'Undeclared' in namespace 'test1'}}
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
template class B<int>;
|
|
|
|
}
|
2010-04-28 00:10:10 +08:00
|
|
|
|
|
|
|
namespace PR6947 {
|
|
|
|
template< class T >
|
|
|
|
struct X {
|
|
|
|
int f0( )
|
|
|
|
{
|
|
|
|
typedef void ( X::*impl_fun_ptr )( );
|
|
|
|
impl_fun_ptr pImpl = &X::template
|
|
|
|
f0_impl1<int>;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
int f1() {
|
|
|
|
}
|
|
|
|
template< class Processor>
|
|
|
|
void f0_impl1( )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
char g0() {
|
|
|
|
X<int> pc;
|
|
|
|
pc.f0();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-05-03 23:32:18 +08:00
|
|
|
|
|
|
|
namespace PR7022 {
|
|
|
|
template <typename >
|
|
|
|
struct X1
|
|
|
|
{
|
|
|
|
typedef int state_t( );
|
|
|
|
state_t g ;
|
|
|
|
};
|
|
|
|
|
|
|
|
template < typename U = X1<int> > struct X2
|
|
|
|
{
|
|
|
|
X2( U = U())
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void m(void)
|
|
|
|
{
|
|
|
|
typedef X2<> X2_type;
|
|
|
|
X2_type c;
|
|
|
|
}
|
2012-07-13 12:12:04 +08:00
|
|
|
}
|
2010-05-03 23:32:18 +08:00
|
|
|
|
2012-07-13 12:12:04 +08:00
|
|
|
namespace SameSignatureAfterInstantiation {
|
|
|
|
template<typename T> struct S {
|
|
|
|
void f(T *); // expected-note {{previous}}
|
|
|
|
void f(const T*); // expected-error {{multiple overloads of 'f' instantiate to the same signature 'void (const int *)'}}
|
|
|
|
};
|
|
|
|
S<const int> s; // expected-note {{instantiation}}
|
2010-05-03 23:32:18 +08:00
|
|
|
}
|