diff options
Diffstat (limited to 'clang/test/SemaTemplate/member-access-expr.cpp')
-rw-r--r-- | clang/test/SemaTemplate/member-access-expr.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/clang/test/SemaTemplate/member-access-expr.cpp b/clang/test/SemaTemplate/member-access-expr.cpp new file mode 100644 index 0000000..f1aa30e --- /dev/null +++ b/clang/test/SemaTemplate/member-access-expr.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +void call_f0(T x) { + x.Base::f0(); +} + +struct Base { + void f0(); +}; + +struct X0 : Base { + typedef Base CrazyBase; +}; + +void test_f0(X0 x0) { + call_f0(x0); +} + +template<typename TheBase, typename T> +void call_f0_through_typedef(T x) { + typedef TheBase Base2; + x.Base2::f0(); +} + +void test_f0_through_typedef(X0 x0) { + call_f0_through_typedef<Base>(x0); +} + +template<typename TheBase, typename T> +void call_f0_through_typedef2(T x) { + typedef TheBase CrazyBase; // expected-note{{current scope}} + x.CrazyBase::f0(); // expected-error{{ambiguous}} \ + // expected-error 2{{no member named}} +} + +struct OtherBase { }; + +struct X1 : Base, OtherBase { + typedef OtherBase CrazyBase; // expected-note{{object type}} +}; + +void test_f0_through_typedef2(X0 x0, X1 x1) { + call_f0_through_typedef2<Base>(x0); + call_f0_through_typedef2<OtherBase>(x1); // expected-note{{instantiation}} + call_f0_through_typedef2<Base>(x1); // expected-note{{instantiation}} +} + + +struct X2 { + operator int() const; +}; + +template<typename T, typename U> +T convert(const U& value) { + return value.operator T(); // expected-error{{operator long}} +} + +void test_convert(X2 x2) { + convert<int>(x2); + convert<long>(x2); // expected-note{{instantiation}} +} + +template<typename T> +void destruct(T* ptr) { + ptr->~T(); + ptr->T::~T(); +} + +template<typename T> +void destruct_intptr(int *ip) { + ip->~T(); + ip->T::~T(); +} + +void test_destruct(X2 *x2p, int *ip) { + destruct(x2p); + destruct(ip); + destruct_intptr<int>(ip); +} + +// PR5220 +class X3 { +protected: + template <int> float* &f0(); + template <int> const float* &f0() const; + void f1() { + (void)static_cast<float*>(f0<0>()); + } + void f1() const{ + (void)f0<0>(); + } +}; + +// Fun with template instantiation and conversions +struct X4 { + int& member(); + float& member() const; +}; + +template<typename T> +struct X5 { + void f(T* ptr) { int& ir = ptr->member(); } + void g(T* ptr) { float& fr = ptr->member(); } +}; + +void test_X5(X5<X4> x5, X5<const X4> x5c, X4 *xp, const X4 *cxp) { + x5.f(xp); + x5c.g(cxp); +} + +// In theory we can do overload resolution at template-definition time on this. +// We should at least not assert. +namespace test4 { + struct Base { + template <class T> void foo() {} + }; + + template <class T> struct Foo : Base { + void test() { + foo<int>(); + } + }; +} + +namespace test5 { + template<typename T> + struct X { + using T::value; + + T &getValue() { + return &value; + } + }; +} + +// PR8739 +namespace test6 { + struct A {}; + struct B {}; + template <class T> class Base; + template <class T> class Derived : public Base<T> { + A *field; + void get(B **ptr) { + // It's okay if at some point we figure out how to diagnose this + // at instantiation time. + *ptr = field; + } + }; +} |