xref: /llvm-project/clang/test/Modules/explicit-specializations.cppm (revision 9b808a4beb8e6c8255b412fdd6f5a3e20cbcf270)
1// Testing that the compiler can select the correct template specialization
2// from different template aliasing.
3//
4// RUN: rm -rf %t
5// RUN: split-file %s %t
6// RUN: cd %t
7//
8// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
9// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fprebuilt-module-path=%t \
10// RUN:     -fsyntax-only -verify
11
12//--- a.cppm
13
14// For template type parameters
15export module a;
16export template <class C>
17struct S {
18    static constexpr bool selected = false;
19};
20
21export struct A {};
22
23export template <>
24struct S<A> {
25    static constexpr bool selected = true;
26};
27
28export using B = A;
29
30// For template template parameters
31
32export template <template<typename> typename C>
33struct V {
34    static constexpr bool selected = false;
35};
36
37export template <>
38struct V<S> {
39    static constexpr bool selected = true;
40};
41
42// For template non type parameters
43export template <int X>
44struct Numbers {
45    static constexpr bool selected = false;
46    static constexpr int value = X;
47};
48
49export template<>
50struct Numbers<43> {
51    static constexpr bool selected = true;
52    static constexpr int value = 43;
53};
54
55export template <const int *>
56struct Pointers {
57    static constexpr bool selected = false;
58};
59
60export int IntegralValue = 0;
61export template<>
62struct Pointers<&IntegralValue> {
63    static constexpr bool selected = true;
64};
65
66export template <void *>
67struct NullPointers {
68    static constexpr bool selected = false;
69};
70
71export template<>
72struct NullPointers<nullptr> {
73    static constexpr bool selected = true;
74};
75
76export template<int (&)[5]>
77struct Array {
78    static constexpr bool selected = false;
79};
80
81export int array[5];
82export template<>
83struct Array<array> {
84    static constexpr bool selected = true;
85};
86
87//--- b.cpp
88// expected-no-diagnostics
89import a;
90
91// Testing for different qualifiers
92static_assert(S<B>::selected);
93static_assert(S<::B>::selected);
94static_assert(::S<B>::selected);
95static_assert(::S<::B>::selected);
96typedef A C;
97static_assert(S<C>::selected);
98static_assert(S<::C>::selected);
99static_assert(::S<C>::selected);
100static_assert(::S<::C>::selected);
101
102namespace D {
103    C getAType();
104    typedef C E;
105}
106
107static_assert(S<D::E>::selected);
108static_assert(S<decltype(D::getAType())>::selected);
109
110// Testing we can select the correct specialization for different
111// template template argument alising.
112
113static_assert(V<S>::selected);
114static_assert(V<::S>::selected);
115static_assert(::V<S>::selected);
116static_assert(::V<::S>::selected);
117
118// Testing for template non type parameters
119static_assert(Numbers<43>::selected);
120static_assert(Numbers<21 * 2 + 1>::selected);
121static_assert(Numbers<42 + 1>::selected);
122static_assert(Numbers<44 - 1>::selected);
123static_assert(Numbers<Numbers<43>::value>::selected);
124static_assert(!Numbers<44>::selected);
125
126static_assert(Pointers<&IntegralValue>::selected);
127static_assert(!Pointers<nullptr>::selected);
128static_assert(NullPointers<nullptr>::selected);
129static_assert(!NullPointers<(void*)&IntegralValue>::selected);
130
131static_assert(Array<array>::selected);
132int another_array[5];
133static_assert(!Array<another_array>::selected);
134