summaryrefslogtreecommitdiff
path: root/clang/test/SemaTemplate/instantiate-member-class.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/SemaTemplate/instantiate-member-class.cpp')
-rw-r--r--clang/test/SemaTemplate/instantiate-member-class.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/clang/test/SemaTemplate/instantiate-member-class.cpp b/clang/test/SemaTemplate/instantiate-member-class.cpp
new file mode 100644
index 0000000..bb64276
--- /dev/null
+++ b/clang/test/SemaTemplate/instantiate-member-class.cpp
@@ -0,0 +1,142 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace PR8965 {
+ template<typename T>
+ struct X {
+ typedef int type;
+
+ T field; // expected-note{{in instantiation of member class}}
+ };
+
+ template<typename T>
+ struct Y {
+ struct Inner;
+
+ typedef typename X<Inner>::type // expected-note{{in instantiation of template class}}
+ type; // expected-note{{not-yet-instantiated member is declared here}}
+
+ struct Inner {
+ typedef type field; // expected-error{{no member 'type' in 'PR8965::Y<int>'; it has not yet been instantiated}}
+ };
+ };
+
+ Y<int> y; // expected-note{{in instantiation of template class}}
+}
+
+template<typename T>
+class X {
+public:
+ struct C { T &foo(); };
+
+ struct D {
+ struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}}
+ struct F; // expected-note{{member is declared here}}
+ };
+};
+
+X<int>::C *c1;
+X<float>::C *c2;
+
+X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
+X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
+
+void test_naming() {
+ c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}}
+ xi = xf; // expected-error{{assigning to 'X<int>::X<int> *' from incompatible type 'X<float>::X<float> *'}}
+ // FIXME: error above doesn't print the type X<int>::X cleanly!
+}
+
+void test_instantiation(X<double>::C *x,
+ X<float>::D::E *e,
+ X<float>::D::F *f) {
+ double &dr = x->foo();
+ float &fr = e->bar();
+ f->foo(); // expected-error{{implicit instantiation of undefined member 'X<float>::D::F'}}
+
+}
+
+
+X<void>::C *c3; // okay
+X<void>::D::E *e1; // okay
+X<void>::D::E e2; // expected-note{{in instantiation of member class 'X<void>::D::E' requested here}}
+
+// Redeclarations.
+namespace test1 {
+ template <typename T> struct Registry {
+ struct node;
+ static node *Head;
+ struct node {
+ node(int v) { Head = this; }
+ };
+ };
+ void test() {
+ Registry<int>::node node(0);
+ }
+}
+
+// Redeclarations during explicit instantiations.
+namespace test2 {
+ template <typename T> class A {
+ class Foo;
+ class Foo {
+ int foo();
+ };
+ };
+ template class A<int>;
+
+ template <typename T> class B {
+ class Foo;
+ class Foo {
+ public:
+ typedef int X;
+ };
+ typename Foo::X x;
+ class Foo;
+ };
+ template class B<int>;
+
+ template <typename T> class C {
+ class Foo;
+ class Foo;
+ };
+ template <typename T> class C<T>::Foo {
+ int x;
+ };
+ template class C<int>;
+}
+
+namespace AliasTagDef {
+ template<typename T>
+ struct F {
+ using S = struct U { // expected-warning {{C++11}}
+ T g() {
+ return T();
+ }
+ };
+ };
+
+ int m = F<int>::S().g();
+ int n = F<int>::U().g();
+}
+
+namespace rdar10397846 {
+ template<int I> struct A
+ {
+ struct B
+ {
+ struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+ };
+ };
+
+ template<int N> void foo()
+ {
+ class A<N>::B::C X; // expected-note{{in instantiation of member function}}
+ int A<N+1>::B::C::*member = 0;
+ }
+
+ void bar()
+ {
+ foo<0>();
+ foo<1>(); // expected-note{{in instantiation of function template}}
+ }
+}