reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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