aboutsummaryrefslogtreecommitdiff
path: root/clang/test/Modules/explicit-specializations.cppm
blob: 914144018e880869f83dd7df3d6cfe27d87c536e (plain)
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
// Testing that the compiler can select the correct template specialization
// from different template aliasing.
//
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: cd %t
//
// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fprebuilt-module-path=%t \
// RUN:     -fsyntax-only -verify

//--- a.cppm

// For template type parameters
export module a;
export template <class C>
struct S {
    static constexpr bool selected = false;
};

export struct A {};

export template <>
struct S<A> {
    static constexpr bool selected = true;
};

export using B = A;

// For template template parameters

export template <template<typename> typename C>
struct V {
    static constexpr bool selected = false;
};

export template <>
struct V<S> {
    static constexpr bool selected = true;
};

// For template non type parameters
export template <int X>
struct Numbers {
    static constexpr bool selected = false;
    static constexpr int value = X;
};

export template<>
struct Numbers<43> {
    static constexpr bool selected = true;
    static constexpr int value = 43;
};

export template <const int *>
struct Pointers {
    static constexpr bool selected = false;
};

export int IntegralValue = 0;
export template<>
struct Pointers<&IntegralValue> {
    static constexpr bool selected = true;
};

export template <void *>
struct NullPointers {
    static constexpr bool selected = false;
};

export template<>
struct NullPointers<nullptr> {
    static constexpr bool selected = true;
};

export template<int (&)[5]>
struct Array {
    static constexpr bool selected = false;
};

export int array[5];
export template<>
struct Array<array> {
    static constexpr bool selected = true;
};

//--- b.cpp
// expected-no-diagnostics
import a;

// Testing for different qualifiers
static_assert(S<B>::selected);
static_assert(S<::B>::selected);
static_assert(::S<B>::selected);
static_assert(::S<::B>::selected);
typedef A C;
static_assert(S<C>::selected);
static_assert(S<::C>::selected);
static_assert(::S<C>::selected);
static_assert(::S<::C>::selected);

namespace D {
    C getAType();
    typedef C E;
}

static_assert(S<D::E>::selected);
static_assert(S<decltype(D::getAType())>::selected);

// Testing we can select the correct specialization for different
// template template argument alising.

static_assert(V<S>::selected);
static_assert(V<::S>::selected);
static_assert(::V<S>::selected);
static_assert(::V<::S>::selected);

// Testing for template non type parameters
static_assert(Numbers<43>::selected);
static_assert(Numbers<21 * 2 + 1>::selected);
static_assert(Numbers<42 + 1>::selected);
static_assert(Numbers<44 - 1>::selected);
static_assert(Numbers<Numbers<43>::value>::selected);
static_assert(!Numbers<44>::selected);

static_assert(Pointers<&IntegralValue>::selected);
static_assert(!Pointers<nullptr>::selected);
static_assert(NullPointers<nullptr>::selected);
static_assert(!NullPointers<(void*)&IntegralValue>::selected);

static_assert(Array<array>::selected);
int another_array[5];
static_assert(!Array<another_array>::selected);