[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

`