huangcm
2025-07-01 2af87f2bbd5ba07d377b5a7f0ee0e96053f2d424
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
// RUN: %clang_cc1 -triple i686-pc-win32 -fsyntax-only -verify %s -DMS
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu-pc-win32 -fsyntax-only -verify %s
 
template<typename T>
class X0 {
public:
  void f(T t);
  
  struct Inner {
    void g(T t);
  };
};
 
template<typename T>
void X0<T>::f(T t) {
  t = 17; // expected-error{{incompatible}}
}
 
extern template class X0<int>;
 
extern template class X0<int*>;
 
template<typename T>
void X0<T>::Inner::g(T t) {
#ifdef MS
  t = 17; // expected-error{{assigning to 'long *' from incompatible}} expected-error{{assigning to 'int *' from incompatible}}
#else
  t = 17; // expected-error{{assigning to 'long *' from incompatible}}
#endif
}
 
void test_intptr(X0<int*> xi, X0<int*>::Inner xii) {
  xi.f(0);
#ifdef MS
  xii.g(0); // expected-note {{instantiation}}
#else
  xii.g(0);
#endif
}
 
extern template class X0<long*>; 
 
void test_longptr(X0<long*> xl, X0<long*>::Inner xli) {
  xl.f(0);
  xli.g(0);
}
 
template class X0<long*>; // expected-note 2{{instantiation}}
 
template<typename T>
class X1 {
public:
  void f(T t) { t += 2; }
  
  void g(T t);
};
 
template<typename T>
void X1<T>::g(T t) { 
  t += 2; 
}
 
extern template class X1<void*>;
 
void g_X1(X1<void*> x1, void *ptr) {
  x1.g(ptr);
}
 
extern template void X1<const void*>::g(const void*);
 
void g_X1_2(X1<const void *> x1, const void *ptr) {
  x1.g(ptr);
}