1*20e90495SChuanqi Xu// RUN: rm -rf %t 2*20e90495SChuanqi Xu// RUN: mkdir -p %t 3*20e90495SChuanqi Xu// RUN: split-file %s %t 4*20e90495SChuanqi Xu// 5*20e90495SChuanqi Xu// RUN: %clang_cc1 -std=c++20 %t/type_traits.cppm -emit-module-interface -o %t/type_traits.pcm 6*20e90495SChuanqi Xu// RUN: %clang_cc1 -std=c++20 %t/test.cpp -fprebuilt-module-path=%t -verify 7*20e90495SChuanqi Xu 8*20e90495SChuanqi Xu//--- type_traits.cppm 9*20e90495SChuanqi Xuexport module type_traits; 10*20e90495SChuanqi Xu 11*20e90495SChuanqi Xuexport template <typename T> 12*20e90495SChuanqi Xuconstexpr bool is_pod_v = __is_pod(T); 13*20e90495SChuanqi Xu 14*20e90495SChuanqi Xu//--- test.cpp 15*20e90495SChuanqi Xu// expected-no-diagnostics 16*20e90495SChuanqi Xuimport type_traits; 17*20e90495SChuanqi Xu// Base is either void or wrapper<T>. 18*20e90495SChuanqi Xutemplate <class Base> struct wrapper : Base {}; 19*20e90495SChuanqi Xutemplate <> struct wrapper<void> {}; 20*20e90495SChuanqi Xu 21*20e90495SChuanqi Xu// wrap<0>::type<T> is wrapper<T>, wrap<1>::type<T> is wrapper<wrapper<T>>, 22*20e90495SChuanqi Xu// and so on. 23*20e90495SChuanqi Xutemplate <int N> 24*20e90495SChuanqi Xustruct wrap { 25*20e90495SChuanqi Xu template <class Base> 26*20e90495SChuanqi Xu using type = wrapper<typename wrap<N-1>::template type<Base>>; 27*20e90495SChuanqi Xu}; 28*20e90495SChuanqi Xu 29*20e90495SChuanqi Xutemplate <> 30*20e90495SChuanqi Xustruct wrap<0> { 31*20e90495SChuanqi Xu template <class Base> 32*20e90495SChuanqi Xu using type = wrapper<Base>; 33*20e90495SChuanqi Xu}; 34*20e90495SChuanqi Xu 35*20e90495SChuanqi Xuinline constexpr int kMaxRank = 40; 36*20e90495SChuanqi Xutemplate <int N, class Base = void> 37*20e90495SChuanqi Xuusing rank = typename wrap<N>::template type<Base>; 38*20e90495SChuanqi Xuusing rank_selector_t = rank<kMaxRank>; 39*20e90495SChuanqi Xu 40*20e90495SChuanqi Xustatic_assert(is_pod_v<rank_selector_t>, "Must be POD"); 41