1// RUN: %clang_cc1 -fsyntax-only -verify %s
2
3namespace N {
4  namespace M {
5    template<typename T> struct Promote;
6
7    template<> struct Promote<short> {
8      typedef int type;
9    };
10
11    template<> struct Promote<int> {
12      typedef int type;
13    };
14
15    template<> struct Promote<float> {
16      typedef double type;
17    };
18
19    Promote<short>::type *ret_intptr(int* ip) { return ip; }
20    Promote<int>::type *ret_intptr2(int* ip) { return ip; }
21  }
22
23  M::Promote<int>::type *ret_intptr3(int* ip) { return ip; }
24  M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } // expected-warning{{'template' keyword outside of a template}}
25  M::template Promote<int> pi; // expected-warning{{'template' keyword outside of a template}}
26}
27
28N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; }
29::N::M::Promote<int>::type *ret_intptr6(int* ip) { return ip; }
30
31
32N::M::template; // expected-error{{expected unqualified-id}}
33N::M::template Promote; // expected-error{{expected unqualified-id}}
34
35namespace N {
36  template<typename T> struct A;
37
38  template<>
39  struct A<int> {
40    struct X;
41  };
42
43  struct B;
44}
45
46struct ::N::A<int>::X {
47  int foo;
48};
49
50template<typename T>
51struct TestA {
52  typedef typename N::template B<T>::type type; // expected-error{{'B' following the 'template' keyword does not refer to a template}} \
53                                                // expected-error{{expected member name}}
54};
55
56// Reduced from a Boost failure.
57namespace test1 {
58  template <class T> struct pair {
59    T x;
60    T y;
61
62    static T pair<T>::* const mem_array[2];
63  };
64
65  template <class T>
66  T pair<T>::* const pair<T>::mem_array[2] = { &pair<T>::x, &pair<T>::y };
67}
68
69typedef int T;
70namespace N1 {
71  template<typename T> T f0();
72}
73
74template<typename T> T N1::f0() { }
75
76namespace PR7385 {
77  template< typename > struct has_xxx0
78  {
79    template< typename > struct has_xxx0_introspect
80    {
81      template< typename > struct has_xxx0_substitute ;
82      template< typename V >
83      int int00( has_xxx0_substitute < typename V::template xxx< > > = 0 );
84    };
85    static const int value = has_xxx0_introspect<int>::value; // expected-error{{no member named 'value'}}
86    typedef int type;
87  };
88
89  has_xxx0<int>::type t; // expected-note{{instantiation of}}
90}
91
92namespace PR7725 {
93  template<class ignored> struct TypedefProvider;
94  template<typename T>
95  struct TemplateClass : public TypedefProvider<T>
96  {
97    void PrintSelf() {
98      TemplateClass::Test::PrintSelf();
99    }
100  };
101}
102
103namespace PR9226 {
104  template<typename a>
105  void nt() // expected-note{{function template 'nt' declared here}}
106  { nt<>:: } // expected-error{{qualified name refers into a specialization of function template 'nt'}} \
107  // expected-error{{expected unqualified-id}}
108
109  template<typename T>
110  void f(T*); // expected-note{{function template 'f' declared here}}
111
112  template<typename T>
113  void f(T*, T*); // expected-note{{function template 'f' declared here}}
114
115  void g() {
116    f<int>:: // expected-error{{qualified name refers into a specialization of function template 'f'}}
117  } // expected-error{{expected unqualified-id}}
118
119  struct X {
120    template<typename T> void f(); // expected-note{{function template 'f' declared here}}
121  };
122
123  template<typename T, typename U>
124  struct Y {
125    typedef typename T::template f<U> type; // expected-error{{template name refers to non-type template 'X::f'}}
126  };
127
128  Y<X, int> yxi; // expected-note{{in instantiation of template class 'PR9226::Y<PR9226::X, int>' requested here}}
129}
130
131namespace PR9449 {
132  template <typename T>
133  struct s; // expected-note{{template is declared here}}
134
135  template <typename T>
136  void f() {
137    int s<T>::template n<T>::* f; // expected-error{{implicit instantiation of undefined template 'PR9449::s<int>'}} \
138    // expected-error{{following the 'template' keyword}}
139  }
140
141  template void f<int>(); // expected-note{{in instantiation of}}
142}
143