[clang] Track function template instantiation from definition (#12526… · llvm/llvm-project@deb63e7 (original) (raw)
``
1
`+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s
`
``
2
+
``
3
`+
namespace t1 {
`
``
4
`+
template struct A {
`
``
5
`+
template friend auto cica(const A&, C) {
`
``
6
`+
return N;
`
``
7
`+
}
`
``
8
`+
};
`
``
9
+
``
10
`+
template<> struct A<0> {
`
``
11
`+
template friend auto cica(const A<0>&, C);
`
``
12
`+
// expected-note@-1 {{declared here}}
`
``
13
`+
};
`
``
14
+
``
15
`+
void test() {
`
``
16
`+
cica(A<0>{}, 0);
`
``
17
`+
// expected-error@-1 {{function 'cica' with deduced return type cannot be used before it is defined}}
`
``
18
+
``
19
`+
(void)A<1>{};
`
``
20
`+
cica(A<0>{}, 0);
`
``
21
`+
}
`
``
22
`+
} // namespace t1
`
``
23
`+
namespace t2 {
`
``
24
`+
template struct A {
`
``
25
`+
template friend auto cica(const A&, C) {
`
``
26
`+
return N;
`
``
27
`+
}
`
``
28
`+
};
`
``
29
+
``
30
`+
template<> struct A<0> {
`
``
31
`+
template friend auto cica(const A<0>&, C);
`
``
32
`+
};
`
``
33
+
``
34
`+
template <int N, class = decltype(cica(A{}, nullptr))>
`
``
35
`+
void MakeCica();
`
``
36
`+
// expected-note@-1 {{candidate function}}
`
``
37
+
``
38
`+
template void MakeCica(A<N+1> = {});
`
``
39
`+
// expected-note@-1 {{candidate function}}
`
``
40
+
``
41
`+
void test() {
`
``
42
`+
MakeCica<0>();
`
``
43
+
``
44
`+
MakeCica<0>();
`
``
45
`+
// expected-error@-1 {{call to 'MakeCica' is ambiguous}}
`
``
46
`+
}
`
``
47
`+
} // namespace t2
`
``
48
`+
namespace t3 {
`
``
49
`+
template struct A {
`
``
50
`+
template friend auto cica(const A&, C) {
`
``
51
`+
return N-1;
`
``
52
`+
}
`
``
53
`+
};
`
``
54
+
``
55
`+
template<> struct A<0> {
`
``
56
`+
template friend auto cica(const A<0>&, C);
`
``
57
`+
};
`
``
58
+
``
59
`+
template <int N, class AT, class = decltype(cica(AT{}, nullptr))>
`
``
60
`+
static constexpr bool MakeCica(int);
`
``
61
+
``
62
`+
template <int N, class AT>
`
``
63
`+
static constexpr bool MakeCica(short, A<N+1> = {});
`
``
64
+
``
65
`+
template <int N, class AT = A, class Val = decltype(MakeCica<N, AT>(0))>
`
``
66
`+
static constexpr bool has_cica = Val{};
`
``
67
+
``
68
`+
constexpr bool cica2 = has_cica<0> || has_cica<0>;
`
``
69
`+
} // namespace t3
`
``
70
`+
namespace t4 {
`
``
71
`+
template struct A {
`
``
72
`+
template friend auto cica(const A&, C);
`
``
73
`+
};
`
``
74
+
``
75
`+
template<> struct A<0> {
`
``
76
`+
template friend auto cica(const A<0>&, C) {
`
``
77
`+
C a;
`
``
78
`+
}
`
``
79
`+
};
`
``
80
+
``
81
`+
template struct A<1>;
`
``
82
+
``
83
`+
void test() {
`
``
84
`+
cica(A<0>{}, 0);
`
``
85
`+
}
`
``
86
`+
} // namespace t4
`
``
87
`+
namespace regression1 {
`
``
88
`+
template class A;
`
``
89
+
``
90
`+
template [[gnu::abi_tag("TAG")]] void foo(A);
`
``
91
+
``
92
`+
template struct A {
`
``
93
`+
friend void foo <>(A);
`
``
94
`+
};
`
``
95
+
``
96
`+
template struct A;
`
``
97
+
``
98
`+
template [[gnu::abi_tag("TAG")]] void foo(A) {}
`
``
99
+
``
100
`+
template void foo(A);
`
``
101
`+
} // namespace regression1
`
``
102
`+
namespace regression2 {
`
``
103
`+
template struct A {
`
``
104
`+
template static void f() {
`
``
105
`+
A::f();
`
``
106
`+
}
`
``
107
`+
};
`
``
108
`+
template <> template void A::f() {
`
``
109
`+
static_assert(__is_same(T, long));
`
``
110
`+
}
`
``
111
`+
template void A::f();
`
``
112
`+
} // namespace regression2
`