1 // RUN: clang-cc -fsyntax-only -verify %s
2 template<typename T, typename U = int> struct A; // expected-note 2{{template is declared here}}
3 
4 template<> struct A<double, double>; // expected-note{{forward declaration}}
5 
6 template<> struct A<float, float> {  // expected-note{{previous definition}}
7   int x;
8 };
9 
10 template<> struct A<float> { // expected-note{{previous definition}}
11   int y;
12 };
13 
14 int test_specs(A<float, float> *a1, A<float, int> *a2) {
15   return a1->x + a2->y;
16 }
17 
18 int test_incomplete_specs(A<double, double> *a1,
19                           A<double> *a2)
20 {
21   (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
22   (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
23 }
24 
25 typedef float FLOAT;
26 
27 template<> struct A<float, FLOAT>;
28 
29 template<> struct A<FLOAT, float> { }; // expected-error{{redefinition}}
30 
31 template<> struct A<float, int> { }; // expected-error{{redefinition}}
32 
33 template<typename T, typename U = int> struct X;
34 
35 template <> struct X<int, int> { int foo(); }; // #1
36 template <> struct X<float> { int bar(); };  // #2
37 
38 typedef int int_type;
39 void testme(X<int_type> *x1, X<float, int> *x2) {
40   (void)x1->foo(); // okay: refers to #1
41   (void)x2->bar(); // okay: refers to #2
42 }
43 
44 // Make sure specializations are proper classes.
45 template<>
46 struct A<char> {
47   A();
48 };
49 
50 A<char>::A() { }
51 
52 // Diagnose specialization errors
53 struct A<double> { }; // expected-error{{template specialization requires 'template<>'}}
54 
55 template<> struct ::A<double>;
56 
57 namespace N {
58   template<typename T> struct B; // expected-note 2{{template is declared here}}
59 
60   template<> struct ::N::B<char>; // okay
61   template<> struct ::N::B<short>; // okay
62   template<> struct ::N::B<int>; // okay
63 
64   int f(int);
65 }
66 
67 template<> struct N::B<int> { }; // okay
68 
69 template<> struct N::B<float> { }; // expected-error{{class template specialization of 'B' not in namespace 'N'}}
70 
71 namespace M {
72   template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}}
73 
74   template<> struct ::A<long double>; // expected-error{{class template specialization of 'A' must occur in the global scope}}
75 }
76 
77 template<> struct N::B<char> {
78   int testf(int x) { return f(x); }
79 };
80 
81