xref: /llvm-project/clang/test/SemaTemplate/undefined-template.cpp (revision 2adab1bc5685634ff8cf96c173831bb9fc1432cc)
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