summaryrefslogtreecommitdiffstats
path: root/test/SemaTemplate/temp_explicit.cpp
blob: 80c90d0cfcd2089aef4d4c0f1740e4218f6dd213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s
//
// Tests explicit instantiation of templates.
template<typename T, typename U = T> class X0 { };

namespace N {
  template<typename T, typename U = T> class X1 { };
}

// Check the syntax of explicit instantiations.
template class X0<int, float>;
template class X0<int>; // expected-note{{previous}}

template class N::X1<int>;
template class ::N::X1<int, float>;

using namespace N;

// Check for some bogus syntax that probably means that the user
// wanted to write an explicit specialization, but forgot the '<>'
// after 'template'.
template class X0<double> { }; // expected-error{{explicit specialization}}

// Check for explicit instantiations that come after other kinds of
// instantiations or declarations.
template class X0<int, int>; // expected-error{{duplicate}}

template<> class X0<char> { }; // expected-note{{previous}}
template class X0<char>; // expected-warning{{ignored}}

void foo(X0<short>) { }
template class X0<short>;

// Check that explicit instantiations actually produce definitions. We
// determine whether this happens by placing semantic errors in the
// definition of the template we're instantiating.
template<typename T> struct X2; // expected-note{{declared here}}

template struct X2<float>; // expected-error{{undefined template}}

template<typename T>
struct X2 {
  void f0(T*); // expected-error{{pointer to a reference}}
};

template struct X2<int>; // okay
template struct X2<int&>; // expected-note{{in instantiation of}}

// Check that explicit instantiations instantiate member classes.
template<typename T> struct X3 {
  struct Inner {
    void f(T*); // expected-error{{pointer to a reference}}
  };
};

void f1(X3<int&>); // okay, Inner, not instantiated

template struct X3<int&>; // expected-note{{instantiation}}

template<typename T> struct X4 {
  struct Inner {
    struct VeryInner {
      void f(T*); // expected-error 2{{pointer to a reference}}
    };
  };
};

void f2(X4<int&>); // okay, Inner, not instantiated
void f3(X4<int&>::Inner); // okay, Inner::VeryInner, not instantiated

template struct X4<int&>; // expected-note{{instantiation}}
template struct X4<float&>; // expected-note{{instantiation}}

// Check explicit instantiation of member classes
namespace N2 {

template<typename T>
struct X5 {
  struct Inner1 {
    void f(T&);
  };

  struct Inner2 { // expected-note {{here}}
    struct VeryInner {
      void g(T*); // expected-error 2{{pointer to a reference}}
    };
  };
};

}

template struct N2::X5<void>::Inner2;

using namespace N2;
template struct X5<int&>::Inner2; // expected-note{{instantiation}}

void f4(X5<float&>::Inner2);
template struct X5<float&>::Inner2; // expected-note{{instantiation}}

namespace N3 {
  template struct N2::X5<int>::Inner2; // expected-warning {{explicit instantiation of 'Inner2' not in a namespace enclosing 'N2'}}
}

struct X6 {
  struct Inner { // expected-note{{here}}
    void f();
  };
};

template struct X6::Inner; // expected-error{{non-templated}}

// PR5559
template <typename T>
struct Foo;

template <>
struct Foo<int> // expected-note{{header not required for explicitly-specialized}}
{
    template <typename U>
    struct Bar
    {};
};

template <> // expected-warning{{extraneous template parameter list}}
template <>
struct Foo<int>::Bar<void>
{};

namespace N1 {

  template<typename T> struct X7 { }; // expected-note{{here}}

  namespace Inner {
    template<typename T> struct X8 { };
  }

  template struct X7<int>;
  template struct Inner::X8<int>;
}

template<typename T> struct X9 { }; // expected-note{{here}}

template struct ::N1::Inner::X8<float>;

namespace N2 {
  using namespace N1;

  template struct X7<double>; // expected-warning{{must occur in namespace}}

  template struct X9<float>; // expected-warning{{must occur at global scope}}
}