| // RUN: %clang_cc1 -fsyntax-only -verify %s |
| struct A0 { |
| struct K { }; |
| }; |
| |
| template <typename T> struct B0: A0 { |
| static void f() { |
| K k; |
| } |
| }; |
| |
| namespace E1 { |
| typedef double A; |
| |
| template<class T> class B { |
| typedef int A; |
| }; |
| |
| template<class T> |
| struct X : B<T> { |
| A* blarg(double *dp) { |
| return dp; |
| } |
| }; |
| } |
| |
| namespace E2 { |
| struct A { |
| struct B; |
| int *a; |
| int Y; |
| }; |
| |
| int a; |
| template<class T> struct Y : T { |
| struct B { /* ... */ }; |
| B b; |
| void f(int i) { a = i; } |
| Y* p; |
| }; |
| |
| Y<A> ya; |
| } |
| |
| namespace PR14402 { |
| template<typename T> |
| struct A { |
| typedef int n; |
| int f(); |
| |
| struct B {}; |
| struct C : B { |
| // OK, can't be sure whether we derive from A yet. |
| using A::n; |
| int g() { return f(); } |
| }; |
| |
| struct D { |
| using A::n; // expected-error {{using declaration refers into 'A<T>::', which is not a base class of 'D'}} |
| int g() { return f(); } // expected-error {{call to non-static member function 'f' of 'A' from nested type 'D'}} |
| }; |
| |
| struct E { char &f(); }; |
| struct F : E { |
| // FIXME: Reject this prior to instantiation; f() is known to return int. |
| char &g() { return f(); } |
| // expected-error@-1 {{'PR14402::A<int>::f' is not a member of class 'PR14402::A<int>::F'}} |
| // expected-error@-2 {{non-const lvalue reference to type 'char' cannot bind to a temporary of type 'int'}} |
| }; |
| }; |
| |
| template<> struct A<int>::B : A<int> {}; |
| A<int>::C::n n = A<int>::C().g(); |
| |
| // 'not a member' |
| char &r = A<int>::F().g(); // expected-note {{in instantiation of}} |
| template<> struct A<char>::E : A<char> {}; |
| // 'cannot bind to a temporary' |
| char &s = A<char>::F().g(); // expected-note {{in instantiation of}} |
| |
| struct X; |
| struct X { void f(); }; |
| struct X; |
| template<typename T> struct Y : X { |
| void g() { |
| X::f(); |
| } |
| }; |
| } |