undefined-template.cpp
7.56 KB
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
152
153
154
155
156
157
158
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s
#if !defined(INCLUDE)
template <class T> struct C1 {
static char s_var_1; // expected-note{{forward declaration of template entity is here}}
static char s_var_2; // expected-note{{forward declaration of template entity is here}}
static void s_func_1(); // expected-note{{forward declaration of template entity is here}}
static void s_func_2(); // expected-note{{forward declaration of template entity is here}}
void meth_1(); // expected-note2{{forward declaration of template entity is here}}
void meth_2();
template <class T1> static char s_tvar_2; // expected-note{{forward declaration of template entity is here}}
template <class T1> static void s_tfunc_2(); // expected-note{{forward declaration of template entity is here}}
template<typename T1> struct C2 {
static char s_var_2; // expected-note{{forward declaration of template entity is here}}
static void s_func_2(); // expected-note{{forward declaration of template entity is here}}
void meth_2(); // expected-note{{forward declaration of template entity is here}}
template <class T2> static char s_tvar_2; // expected-note{{forward declaration of template entity is here}}
template <class T2> void tmeth_2(); // expected-note{{forward declaration of template entity is here}}
};
};
extern template char C1<int>::s_var_2;
extern template void C1<int>::s_func_2();
extern template void C1<int>::meth_2();
extern template char C1<int>::s_tvar_2<char>;
extern template void C1<int>::s_tfunc_2<char>();
extern template void C1<int>::C2<long>::s_var_2;
extern template void C1<int>::C2<long>::s_func_2();
extern template void C1<int>::C2<long>::meth_2();
extern template char C1<int>::C2<long>::s_tvar_2<char>;
extern template void C1<int>::C2<long>::tmeth_2<char>();
char func_01() {
return C1<int>::s_var_2;
}
char func_02() {
return C1<int>::s_var_1; // expected-warning{{instantiation of variable 'C1<int>::s_var_1' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_var_1' is explicitly instantiated in another translation unit}}
}
char func_03() {
return C1<char>::s_var_2; // expected-warning{{instantiation of variable 'C1<char>::s_var_2' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::s_var_2' is explicitly instantiated in another translation unit}}
}
void func_04() {
C1<int>::s_func_1(); // expected-warning{{instantiation of function 'C1<int>::s_func_1' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_func_1' is explicitly instantiated in another translation unit}}
}
void func_05() {
C1<int>::s_func_2();
}
void func_06() {
C1<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<char>::s_func_2' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::s_func_2' is explicitly instantiated in another translation unit}}
}
void func_07(C1<int> *x) {
x->meth_1(); // expected-warning{{instantiation of function 'C1<int>::meth_1' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::meth_1' is explicitly instantiated in another translation unit}}
}
void func_08(C1<int> *x) {
x->meth_2();
}
void func_09(C1<char> *x) {
x->meth_1(); // expected-warning{{instantiation of function 'C1<char>::meth_1' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::meth_1' is explicitly instantiated in another translation unit}}
}
char func_10() {
return C1<int>::s_tvar_2<char>;
}
char func_11() {
return C1<int>::s_tvar_2<long>; // expected-warning{{instantiation of variable 'C1<int>::s_tvar_2<long>' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_tvar_2<long>' is explicitly instantiated in another translation unit}}
}
void func_12() {
C1<int>::s_tfunc_2<char>();
}
void func_13() {
C1<int>::s_tfunc_2<long>(); // expected-warning{{instantiation of function 'C1<int>::s_tfunc_2<long>' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_tfunc_2<long>' is explicitly instantiated in another translation unit}}
}
char func_14() {
return C1<int>::C2<long>::s_var_2;
}
char func_15() {
return C1<int>::C2<char>::s_var_2; //expected-warning {{instantiation of variable 'C1<int>::C2<char>::s_var_2' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::s_var_2' is explicitly instantiated in another translation unit}}
}
void func_16() {
C1<int>::C2<long>::s_func_2();
}
void func_17() {
C1<int>::C2<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<int>::C2<char>::s_func_2' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::s_func_2' is explicitly instantiated in another translation unit}}
}
void func_18(C1<int>::C2<long> *x) {
x->meth_2();
}
void func_19(C1<int>::C2<char> *x) {
x->meth_2(); // expected-warning{{instantiation of function 'C1<int>::C2<char>::meth_2' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::meth_2' is explicitly instantiated in another translation unit}}
}
char func_20() {
return C1<int>::C2<long>::s_tvar_2<char>;
}
char func_21() {
return C1<int>::C2<long>::s_tvar_2<long>; // expected-warning{{instantiation of variable 'C1<int>::C2<long>::s_tvar_2<long>' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<long>::s_tvar_2<long>' is explicitly instantiated in another translation unit}}
}
void func_22(C1<int>::C2<long> *x) {
x->tmeth_2<char>();
}
void func_23(C1<int>::C2<long> *x) {
x->tmeth_2<int>(); // expected-warning{{instantiation of function 'C1<int>::C2<long>::tmeth_2<int>' required here, but no definition is available}}
// expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<long>::tmeth_2<int>' is explicitly instantiated in another translation unit}}
}
namespace test_24 {
template <typename T> struct X {
friend void g(int);
operator int() { return 0; }
};
void h(X<int> x) { g(x); } // no warning for use of 'g' despite the declaration having been instantiated from a template
}
#define INCLUDE
#include "undefined-template.cpp"
void func_25(SystemHeader<char> *x) {
x->meth();
}
int main() {
return 0;
}
#else
#pragma clang system_header
template <typename T> struct SystemHeader { T meth(); };
#endif