90 lines
1.8 KiB
C++
90 lines
1.8 KiB
C++
// 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();
|
|
}
|
|
};
|
|
}
|