189b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor// RUN: %clang_cc1 -fsyntax-only -verify %s
237d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<class T> struct A {
337d68185088947322a97eabdc1c0714b0debd929Douglas Gregor  void f(T);
437d68185088947322a97eabdc1c0714b0debd929Douglas Gregor  template<class X1> void g1(T, X1);
537d68185088947322a97eabdc1c0714b0debd929Douglas Gregor  template<class X2> void g2(T, X2);
637d68185088947322a97eabdc1c0714b0debd929Douglas Gregor  void h(T) { }
737d68185088947322a97eabdc1c0714b0debd929Douglas Gregor};
837d68185088947322a97eabdc1c0714b0debd929Douglas Gregor
937d68185088947322a97eabdc1c0714b0debd929Douglas Gregor// specialization
1037d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<> void A<int>::f(int);
1137d68185088947322a97eabdc1c0714b0debd929Douglas Gregor
1237d68185088947322a97eabdc1c0714b0debd929Douglas Gregor// out of class member template definition
1337d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<class T> template<class X1> void A<T>::g1(T, X1) { }
1437d68185088947322a97eabdc1c0714b0debd929Douglas Gregor
1537d68185088947322a97eabdc1c0714b0debd929Douglas Gregor// member template specialization
1637d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<> template<class X1> void A<int>::g1(int, X1);
1737d68185088947322a97eabdc1c0714b0debd929Douglas Gregor
1837d68185088947322a97eabdc1c0714b0debd929Douglas Gregor// member template specialization
1937d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<> template<>
2037d68185088947322a97eabdc1c0714b0debd929Douglas Gregor  void A<int>::g1(int, char);	// X1 deduced as char
2137d68185088947322a97eabdc1c0714b0debd929Douglas Gregor
2237d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<> template<>
2337d68185088947322a97eabdc1c0714b0debd929Douglas Gregor  void A<int>::g2<char>(int, char); // X2 specified as char
2437d68185088947322a97eabdc1c0714b0debd929Douglas Gregor                                    // member specialization even if defined in class definition
2537d68185088947322a97eabdc1c0714b0debd929Douglas Gregor
2637d68185088947322a97eabdc1c0714b0debd929Douglas Gregortemplate<> void A<int>::h(int) { }
2789b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor
2889b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregornamespace PR10024 {
2989b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor  template <typename T>
3089b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor  struct Test{
3189b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor    template <typename U>
3289b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor    void get(U i) {}
3389b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor  };
3489b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor
3589b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor  template <typename T>
3689b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor  template <>
3789b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor  void Test<T>::get<double>(double i) {}  // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}}
3889b9f10cca9e2812b3e7943d3150fe6c9028bbe4Douglas Gregor}
39