llvm-capstone/clang/test/Modules/explicit-specializations.cppm
Chuanqi Xu 9b808a4beb [NFC] [Modules] Add a test case for selecting specializations with aliased template args
This a test for https://github.com/llvm/llvm-project/pull/76774. In the
review comments, we're concerning about the case that ODRHash may
produce the different hash values for semantical same template
arguments. For example, if the template argument in a specialization is
not qualified and the semantical same template argument in the instantiation
point is qualified, we should be able to select that template
specialization. And this patch tests this behavior: we should be able to select
the correct specialization with semantical same template arguments.
2024-01-08 14:46:11 +08:00

134 lines
3.0 KiB
C++

// 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);