17dcc97e7SSerge Pavlov // RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s
27dcc97e7SSerge Pavlov
3*2adab1bcSNick Lewycky #if !defined(INCLUDE)
47dcc97e7SSerge Pavlov template <class T> struct C1 {
57dcc97e7SSerge Pavlov static char s_var_1; // expected-note{{forward declaration of template entity is here}}
67dcc97e7SSerge Pavlov static char s_var_2; // expected-note{{forward declaration of template entity is here}}
77dcc97e7SSerge Pavlov static void s_func_1(); // expected-note{{forward declaration of template entity is here}}
87dcc97e7SSerge Pavlov static void s_func_2(); // expected-note{{forward declaration of template entity is here}}
97dcc97e7SSerge Pavlov void meth_1(); // expected-note2{{forward declaration of template entity is here}}
107dcc97e7SSerge Pavlov void meth_2();
117dcc97e7SSerge Pavlov template <class T1> static char s_tvar_2; // expected-note{{forward declaration of template entity is here}}
127dcc97e7SSerge Pavlov template <class T1> static void s_tfunc_2(); // expected-note{{forward declaration of template entity is here}}
137dcc97e7SSerge Pavlov template<typename T1> struct C2 {
147dcc97e7SSerge Pavlov static char s_var_2; // expected-note{{forward declaration of template entity is here}}
157dcc97e7SSerge Pavlov static void s_func_2(); // expected-note{{forward declaration of template entity is here}}
167dcc97e7SSerge Pavlov void meth_2(); // expected-note{{forward declaration of template entity is here}}
177dcc97e7SSerge Pavlov template <class T2> static char s_tvar_2; // expected-note{{forward declaration of template entity is here}}
187dcc97e7SSerge Pavlov template <class T2> void tmeth_2(); // expected-note{{forward declaration of template entity is here}}
197dcc97e7SSerge Pavlov };
207dcc97e7SSerge Pavlov };
217dcc97e7SSerge Pavlov
227dcc97e7SSerge Pavlov extern template char C1<int>::s_var_2;
237dcc97e7SSerge Pavlov extern template void C1<int>::s_func_2();
247dcc97e7SSerge Pavlov extern template void C1<int>::meth_2();
257dcc97e7SSerge Pavlov extern template char C1<int>::s_tvar_2<char>;
267dcc97e7SSerge Pavlov extern template void C1<int>::s_tfunc_2<char>();
277dcc97e7SSerge Pavlov extern template void C1<int>::C2<long>::s_var_2;
287dcc97e7SSerge Pavlov extern template void C1<int>::C2<long>::s_func_2();
297dcc97e7SSerge Pavlov extern template void C1<int>::C2<long>::meth_2();
307dcc97e7SSerge Pavlov extern template char C1<int>::C2<long>::s_tvar_2<char>;
317dcc97e7SSerge Pavlov extern template void C1<int>::C2<long>::tmeth_2<char>();
327dcc97e7SSerge Pavlov
func_01()337dcc97e7SSerge Pavlov char func_01() {
347dcc97e7SSerge Pavlov return C1<int>::s_var_2;
357dcc97e7SSerge Pavlov }
367dcc97e7SSerge Pavlov
func_02()377dcc97e7SSerge Pavlov char func_02() {
387dcc97e7SSerge Pavlov return C1<int>::s_var_1; // expected-warning{{instantiation of variable 'C1<int>::s_var_1' required here, but no definition is available}}
397dcc97e7SSerge Pavlov // 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}}
407dcc97e7SSerge Pavlov }
417dcc97e7SSerge Pavlov
func_03()427dcc97e7SSerge Pavlov char func_03() {
437dcc97e7SSerge Pavlov return C1<char>::s_var_2; // expected-warning{{instantiation of variable 'C1<char>::s_var_2' required here, but no definition is available}}
447dcc97e7SSerge Pavlov // 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}}
457dcc97e7SSerge Pavlov }
467dcc97e7SSerge Pavlov
func_04()477dcc97e7SSerge Pavlov void func_04() {
487dcc97e7SSerge Pavlov C1<int>::s_func_1(); // expected-warning{{instantiation of function 'C1<int>::s_func_1' required here, but no definition is available}}
497dcc97e7SSerge Pavlov // 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}}
507dcc97e7SSerge Pavlov }
517dcc97e7SSerge Pavlov
func_05()527dcc97e7SSerge Pavlov void func_05() {
537dcc97e7SSerge Pavlov C1<int>::s_func_2();
547dcc97e7SSerge Pavlov }
557dcc97e7SSerge Pavlov
func_06()567dcc97e7SSerge Pavlov void func_06() {
577dcc97e7SSerge Pavlov C1<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<char>::s_func_2' required here, but no definition is available}}
587dcc97e7SSerge Pavlov // 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}}
597dcc97e7SSerge Pavlov }
607dcc97e7SSerge Pavlov
func_07(C1<int> * x)617dcc97e7SSerge Pavlov void func_07(C1<int> *x) {
627dcc97e7SSerge Pavlov x->meth_1(); // expected-warning{{instantiation of function 'C1<int>::meth_1' required here, but no definition is available}}
637dcc97e7SSerge Pavlov // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::meth_1' is explicitly instantiated in another translation unit}}
647dcc97e7SSerge Pavlov }
657dcc97e7SSerge Pavlov
func_08(C1<int> * x)667dcc97e7SSerge Pavlov void func_08(C1<int> *x) {
677dcc97e7SSerge Pavlov x->meth_2();
687dcc97e7SSerge Pavlov }
697dcc97e7SSerge Pavlov
func_09(C1<char> * x)707dcc97e7SSerge Pavlov void func_09(C1<char> *x) {
717dcc97e7SSerge Pavlov x->meth_1(); // expected-warning{{instantiation of function 'C1<char>::meth_1' required here, but no definition is available}}
727dcc97e7SSerge Pavlov // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::meth_1' is explicitly instantiated in another translation unit}}
737dcc97e7SSerge Pavlov }
747dcc97e7SSerge Pavlov
func_10()757dcc97e7SSerge Pavlov char func_10() {
767dcc97e7SSerge Pavlov return C1<int>::s_tvar_2<char>;
777dcc97e7SSerge Pavlov }
787dcc97e7SSerge Pavlov
func_11()797dcc97e7SSerge Pavlov char func_11() {
807dcc97e7SSerge Pavlov 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}}
817dcc97e7SSerge Pavlov // 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}}
827dcc97e7SSerge Pavlov }
837dcc97e7SSerge Pavlov
func_12()847dcc97e7SSerge Pavlov void func_12() {
857dcc97e7SSerge Pavlov C1<int>::s_tfunc_2<char>();
867dcc97e7SSerge Pavlov }
877dcc97e7SSerge Pavlov
func_13()887dcc97e7SSerge Pavlov void func_13() {
897dcc97e7SSerge Pavlov C1<int>::s_tfunc_2<long>(); // expected-warning{{instantiation of function 'C1<int>::s_tfunc_2<long>' required here, but no definition is available}}
907dcc97e7SSerge Pavlov // 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}}
917dcc97e7SSerge Pavlov }
927dcc97e7SSerge Pavlov
func_14()937dcc97e7SSerge Pavlov char func_14() {
947dcc97e7SSerge Pavlov return C1<int>::C2<long>::s_var_2;
957dcc97e7SSerge Pavlov }
967dcc97e7SSerge Pavlov
func_15()977dcc97e7SSerge Pavlov char func_15() {
987dcc97e7SSerge Pavlov 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}}
997dcc97e7SSerge Pavlov // 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}}
1007dcc97e7SSerge Pavlov }
1017dcc97e7SSerge Pavlov
func_16()1027dcc97e7SSerge Pavlov void func_16() {
1037dcc97e7SSerge Pavlov C1<int>::C2<long>::s_func_2();
1047dcc97e7SSerge Pavlov }
1057dcc97e7SSerge Pavlov
func_17()1067dcc97e7SSerge Pavlov void func_17() {
1077dcc97e7SSerge Pavlov 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}}
1087dcc97e7SSerge Pavlov // 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}}
1097dcc97e7SSerge Pavlov }
1107dcc97e7SSerge Pavlov
func_18(C1<int>::C2<long> * x)1117dcc97e7SSerge Pavlov void func_18(C1<int>::C2<long> *x) {
1127dcc97e7SSerge Pavlov x->meth_2();
1137dcc97e7SSerge Pavlov }
1147dcc97e7SSerge Pavlov
func_19(C1<int>::C2<char> * x)1157dcc97e7SSerge Pavlov void func_19(C1<int>::C2<char> *x) {
1167dcc97e7SSerge Pavlov x->meth_2(); // expected-warning{{instantiation of function 'C1<int>::C2<char>::meth_2' required here, but no definition is available}}
1177dcc97e7SSerge Pavlov // 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}}
1187dcc97e7SSerge Pavlov }
1197dcc97e7SSerge Pavlov
func_20()1207dcc97e7SSerge Pavlov char func_20() {
1217dcc97e7SSerge Pavlov return C1<int>::C2<long>::s_tvar_2<char>;
1227dcc97e7SSerge Pavlov }
1237dcc97e7SSerge Pavlov
func_21()1247dcc97e7SSerge Pavlov char func_21() {
1257dcc97e7SSerge Pavlov 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}}
1267dcc97e7SSerge Pavlov // 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}}
1277dcc97e7SSerge Pavlov }
1287dcc97e7SSerge Pavlov
func_22(C1<int>::C2<long> * x)1297dcc97e7SSerge Pavlov void func_22(C1<int>::C2<long> *x) {
1307dcc97e7SSerge Pavlov x->tmeth_2<char>();
1317dcc97e7SSerge Pavlov }
1327dcc97e7SSerge Pavlov
func_23(C1<int>::C2<long> * x)1337dcc97e7SSerge Pavlov void func_23(C1<int>::C2<long> *x) {
1347dcc97e7SSerge Pavlov x->tmeth_2<int>(); // expected-warning{{instantiation of function 'C1<int>::C2<long>::tmeth_2<int>' required here, but no definition is available}}
1357dcc97e7SSerge Pavlov // 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}}
1367dcc97e7SSerge Pavlov }
1377dcc97e7SSerge Pavlov
138cfa5dc4aSRichard Smith namespace test_24 {
139cfa5dc4aSRichard Smith template <typename T> struct X {
140cfa5dc4aSRichard Smith friend void g(int);
operator inttest_24::X141cfa5dc4aSRichard Smith operator int() { return 0; }
142cfa5dc4aSRichard Smith };
h(X<int> x)143cfa5dc4aSRichard Smith void h(X<int> x) { g(x); } // no warning for use of 'g' despite the declaration having been instantiated from a template
144cfa5dc4aSRichard Smith }
145cfa5dc4aSRichard Smith
146*2adab1bcSNick Lewycky #define INCLUDE
147*2adab1bcSNick Lewycky #include "undefined-template.cpp"
func_25(SystemHeader<char> * x)148*2adab1bcSNick Lewycky void func_25(SystemHeader<char> *x) {
149*2adab1bcSNick Lewycky x->meth();
150*2adab1bcSNick Lewycky }
151*2adab1bcSNick Lewycky
main()1527dcc97e7SSerge Pavlov int main() {
1537dcc97e7SSerge Pavlov return 0;
1547dcc97e7SSerge Pavlov }
155*2adab1bcSNick Lewycky #else
156*2adab1bcSNick Lewycky #pragma clang system_header
157*2adab1bcSNick Lewycky template <typename T> struct SystemHeader { T meth(); };
158*2adab1bcSNick Lewycky #endif
159