1// RUN: %clang_cc1 -fsyntax-only -verify %s
2
3namespace PR8965 {
4  template<typename T>
5  struct X {
6    typedef int type;
7
8    T field; // expected-note{{in instantiation of member class}}
9  };
10
11  template<typename T>
12  struct Y {
13    struct Inner;
14
15    typedef typename X<Inner>::type // expected-note{{in instantiation of template class}}
16      type; // expected-note{{not-yet-instantiated member is declared here}}
17
18    struct Inner {
19      typedef type field; // expected-error{{no member 'type' in 'PR8965::Y<int>'; it has not yet been instantiated}}
20    };
21  };
22
23  Y<int> y; // expected-note{{in instantiation of template class}}
24}
25
26template<typename T>
27class X {
28public:
29  struct C { T &foo(); };
30
31  struct D {
32    struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}}
33    struct F; // expected-note{{member is declared here}}
34  };
35};
36
37X<int>::C *c1;
38X<float>::C *c2;
39
40X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
41X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
42
43void test_naming() {
44  c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}}
45  xi = xf;  // expected-error{{assigning to 'X<int>::X<int> *' from incompatible type 'X<float>::X<float> *'}}
46    // FIXME: error above doesn't print the type X<int>::X cleanly!
47}
48
49void test_instantiation(X<double>::C *x,
50                        X<float>::D::E *e,
51                        X<float>::D::F *f) {
52  double &dr = x->foo();
53  float &fr = e->bar();
54  f->foo(); // expected-error{{implicit instantiation of undefined member 'X<float>::D::F'}}
55
56}
57
58
59X<void>::C *c3; // okay
60X<void>::D::E *e1; // okay
61X<void>::D::E e2; // expected-note{{in instantiation of member class 'X<void>::D::E' requested here}}
62
63// Redeclarations.
64namespace test1 {
65  template <typename T> struct Registry {
66    struct node;
67    static node *Head;
68    struct node {
69      node(int v) { Head = this; }
70    };
71  };
72  void test() {
73    Registry<int>::node node(0);
74  }
75}
76
77// Redeclarations during explicit instantiations.
78namespace test2 {
79  template <typename T> class A {
80    class Foo;
81    class Foo {
82      int foo();
83    };
84  };
85  template class A<int>;
86
87  template <typename T> class B {
88    class Foo;
89    class Foo {
90    public:
91      typedef int X;
92    };
93    typename Foo::X x;
94    class Foo;
95  };
96  template class B<int>;
97
98  template <typename T> class C {
99    class Foo;
100    class Foo;
101  };
102  template <typename T> class C<T>::Foo {
103    int x;
104  };
105  template class C<int>;
106}
107
108namespace AliasTagDef {
109  template<typename T>
110  struct F {
111    using S = struct U { // expected-warning {{C++11}}
112      T g() {
113        return T();
114      }
115    };
116  };
117
118  int m = F<int>::S().g();
119  int n = F<int>::U().g();
120}
121
122namespace rdar10397846 {
123  template<int I> struct A
124  {
125    struct B
126    {
127      struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
128    };
129  };
130
131  template<int N> void foo()
132  {
133    class A<N>::B::C X; // expected-note{{in instantiation of member function}}
134    int A<N+1>::B::C::*member = 0;
135  }
136
137  void bar()
138  {
139    foo<0>();
140    foo<1>(); // expected-note{{in instantiation of function template}}
141  }
142}
143