<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/154820>154820</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
clang frontend in clang 20 uses >60GB of RAM (and crashes with OOM) to compile a small template meta-program that compiles fine in clang 18 and 19
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
dwith-ts
</td>
</tr>
</table>
<pre>
Hi,
I have a condensed template meta-program below which causes clang 20.1.0 to use a large amount of memory (verified that it uses more than 60GB) and then it crashes with out-of-memory on my machine.
The program compiles without problems with clang 18 and clang 19. I used C++17 option for all compilers.
For a quick try, here is the godbolt link: https://godbolt.org/z/67vejdxMe
Code example:
`#include <tuple>
#include <cstdint>
template<typename...> struct TypeList{};
template<typename T1, typename T2> struct Pair {
using FirstType = T1;
using SecondType = T2;
};
template <typename T1, typename T2>
T2 remove_from_start;
template <typename T1, typename T2>
using RemoveFromStart = decltype(remove_from_start<T1, T2>);
template <typename T, typename... Rest1, typename... Rest2>
RemoveFromStart<TypeList<Rest1...>, TypeList<Rest2...>>
remove_from_start<TypeList<T, Rest1...>,
TypeList<T, Rest2...>>;
template <typename T>
constexpr std::int32_t size_of = -1;
template <template <class...> class L, typename... Ts>
constexpr std::int32_t size_of<L<Ts...>> = sizeof...(Ts);
template <bool>
struct CheckingArgNr;
template <typename AllRows_T, typename AllCols_T, typename... Others_T>
using CheckConstructorArgs = typename CheckingArgNr<(
sizeof...(Others_T) > 0)>::template Result<1, AllRows_T, AllCols_T, TypeList<>, AllCols_T, Others_T...>::FirstType;
template <typename RowsT, typename AllRowsT>
using IsStartOf = std::bool_constant<size_of<AllRowsT> - size_of<RemoveFromStart<RowsT, AllRowsT>> == size_of<RowsT>>;
template <bool>
struct RemoveFromStartOfOr;
template <>
struct RemoveFromStartOfOr<true> {
template <typename StartList_T, typename FullList_T, typename>
using type = RemoveFromStart<StartList_T, FullList_T>;
};
template <>
struct RemoveFromStartOfOr<false> {
template <typename, typename, typename Fallback_T>
using type = Fallback_T;
};
template <>
struct CheckingArgNr<true> {
template <typename Pair_T>
using RowList = typename Pair_T::FirstType;
template <typename Pair_T>
using ColList = typename Pair_T::SecondType;
template <std::int32_t counter_v,
typename RemainingRows_T,
typename AllCols_T,
typename CurrentRows_T,
typename RemainingCols_T,
typename CurrentPair_T,
typename... Others_T>
using NextArgumentResult = typename CheckingArgNr<(sizeof...(Others_T) > 0)>::template Result<
counter_v + 1,
typename RemoveFromStartOfOr< //
std::is_same<ColList<CurrentPair_T>,
RemainingCols_T>::value
>::template type<RowList<CurrentPair_T>,
RemainingRows_T,
RemainingRows_T>,
AllCols_T,
std::conditional_t<std::is_same<ColList<CurrentPair_T>, RemainingCols_T>::value, TypeList<>, RowList<CurrentPair_T>>,
typename RemoveFromStartOfOr<not std::is_same<ColList<CurrentPair_T>, RemainingCols_T>::value>::
template type<ColList<CurrentPair_T>, RemainingCols_T, AllCols_T>,
Others_T...>;
template <typename RemainingRows_T,
typename AllCols_T,
typename CurrentRows_T,
typename RemainingCols_T,
typename CurrentPair_T>
static constexpr bool current_argument_check =
IsStartOf<ColList<CurrentPair_T>, RemainingCols_T>::value &&
(((size_of<CurrentRows_T> == 0) && IsStartOf<RowList<CurrentPair_T>, RemainingRows_T>::value &&
std::is_same<RemainingCols_T, AllCols_T>::value) ||
std::is_same<RowList<CurrentPair_T>, CurrentRows_T>::value);
template <std::int32_t counter_v,
typename RemainingRows_T,
typename AllCols_T,
typename CurrentRows_T,
typename RemainingCols_T,
typename CurrentPair_T,
typename... Others_T>
using Result = std::conditional_t<
current_argument_check<RemainingRows_T, AllCols_T, CurrentRows_T, RemainingCols_T, CurrentPair_T>,
NextArgumentResult<counter_v,
RemainingRows_T,
AllCols_T,
CurrentRows_T,
RemainingCols_T,
CurrentPair_T,
Others_T...>,
Pair<std::false_type, std::integral_constant<std::int32_t, counter_v>>>;
};
template <>
struct CheckingArgNr<false> {
template <std::int32_t counter_v,
typename RemainingRows_T,
typename AllCols_T,
typename CurrentRows_T,
typename RemainingCols_T>
using Result = Pair<
std::bool_constant<(size_of<RemainingRows_T> == 0)>,
std::integral_constant<std::int32_t, (size_of<RemainingRows_T> == 0) ? -1 : counter_v>>;
};
struct A; struct B; struct C; struct D; struct E; struct F; struct G;
struct H; struct I; struct J;
int main() {
using RowList1 = TypeList<A, B, H, I>;
using ColList1 = TypeList<A, B, C, D, F, G>;
// this already crashes / uses a huge amount of memory with clang 20
using Result = CheckConstructorArgs<RowList1, ColList1,
Pair<A, A>, Pair<A, B>, Pair<A, C>, Pair<A, D>,
Pair<A, F>, Pair<A, G>,
Pair<B, A>, Pair<B, B>, Pair<B, C>, Pair<B, D>,
Pair<B, F>, Pair<B, G>,
Pair<H, A>, Pair<H, B>, Pair<H, C>,
Pair<H, D>,
Pair<H, F>, Pair<H, G>,
Pair<I, A>, Pair<I, B>, Pair<I, C>,
Pair<I, D>,
Pair<I, F>, Pair<I, G>
>;
// // even larger example
// using RowList2 = TypeList<A, B, H, I>;
// using ColList2 = TypeList<A, B, C, D, E, F, G, J>;
// using Result = CheckConstructorArgs<RowList2, ColList2,
// Pair<A, A>, Pair<A, B>, Pair<A, C>, Pair<A, D>, Pair<A, E>, Pair<A, F>, Pair<A, G>, Pair<A, J>, //
// Pair<B, A>, Pair<B, B>, Pair<B, C>, Pair<B, D>, Pair<B, E>, Pair<B, F>, Pair<B, G>, Pair<B, J>, //
// Pair<H, A>, Pair<H, B>, Pair<H, C>, Pair<H, D>, Pair<H, E>, Pair<H, F>, Pair<H, G>, Pair<H, J>, //
// Pair<I, A>, Pair<I, B>, Pair<I, C>, Pair<I, D>, Pair<I, E>, Pair<I, F>, Pair<I, G>, Pair<I, J>
// >;
}`
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWc1y4roSfhqx6Qpl5CTAgoVxIGFq5uRWTvaUsAX4jGzlSnIyOU9_S_KfZIRJMrO5VIqYltT9dav_ZBEps0NB6QLdLNHN3YiU6sjFIn3L1PFKydGOp--LhwzhGFAQoSDawJG8UiCQ8CKlhaQpKJq_MKIo5FSRqxfBD4LksKOMv8HbMUuOkJBSUgkJI8UBcDCejANQHEqpGTEiDhRIzstCAd9DTnMu3gHh2SsV2T7TEo5EQabAcMm5oJpSwG1wv0R4DqTQU2ihpySCyCOVoBUAXqorvr-qOfIC8nfISXLMCjqu1Hk-UmgQJzx_yVi9lpdKD-wYzWtmFfrJzIirf8zHsNGoUogRXiK8nEyBv6iMF7DnAghjDVcha4lrTYf_llnyE5R415Y9UkEhk1oHOPB0x5kClhU_URjBUakXicII4TXC63p0zMUB4fW_CK9vp6_0n_TXD1pxj3lKgf4i-QujelUQodsA4TArElamFFAYq9KMrfSYM5BIlWaFqoeCqNlXveb9hRYkp-PxGIUrkEqUiYLn9xf6PZMKTZdoeofC5dl18DzRinY_scXmPyQToHkEEQBAKbPiAOtMSKUFAArv9PLQHf-bagfsJuBavAcHXAKi_QCDoDl_pdu94PlWKiLUlxhV6J4Mr7Xg-d-ak4GY0oTp6QjPPKLiil_FBs8vyLZFj8djeKJSTXzEGlUPjxbX7F0Ym8XVzhoI7giuRwwfbX8v-G6Nweay1At9MyzWF9Q1whNeSEV_vQiQKtXOHUZZoUK8VSCzf-mW742dryZ-btZzwoiUtS-bZ_jeN96z_KhQFMbftVay1cbA0KN8r2l49iztLe0B23HOKll1PMRHmvzMikMkDn-JYctEjD3xN7l1HEJTY856VK3UozpSoemWqxppsdZSC-ciEgdpFGjZ9fDECM9qV7B1bHnjOWgbBEblVWWyFvwTlSXTTmC81YHvoLbcpXZLZ7gR1phcy2gzxjlDtwppmScWq4iWYTbSxMpj5VXt7uvt2hqvIDpXxp0XWEzgyvKO0-BrAdhyK79pXKde2g16HeHEd3qyHvePfg-6vChWoqQGVJ2ZvaY0C_RG9VxwXTJ2Sm6SSGVg1STvUwP12FrcWkM0if6TWu0Jk7ZaPq0cyI5WhLEdSX42EXSiiT1hqBwNxfvHDK-LZh_GE3_TVnKjt5noCZFPsI45G2bd1eNWYYf7SfZMdL9Hxfa1LhDWpwtUmpOsyIpDmyUMW1-eO8ciLoWghfIzaPl_lE2tscvmNLM2VvuL_lKROJS5RmAy38XM-hsptcXemhYQXsLEVstW3RMdAFWfqed3Oya30gRvXHuBfnLs0Vb5vkEbsK-ElbQzq2PlU41Ml2SS37C0859Tx4HPLahqjgu2726tgbTnZ7rpJ2yrHF__mOWGzeYvhwPGce1zYccLrj690xfwNr8ci_c393MCnPrv6tdvBZrk489t_ozii_ivJhffvK_mmTqZSEVUlkDXiuqyD0k1dUvqBLNNdDYxPUQQdd3L720mIHyr_4JIH8irv649cfXvGpjAZCyz0gEyGNG-GPQCqT8er73kNnZQzQFNY_3XcvQxHATcV9_lj8IlgM8ZL5bCP-Ctf8hFB-ufh835UmiVv7N5sytgXte2N_jMsaGvrS-RnCkmp7VaHxTPNymD5aOaPZBCnI9vj_z7cWEbnE8vMVaT9UrbBU07vK1eS8TOEZceBHEPOj231Qs6-9RnFJ2A4auNb783__9rIM-5fG12p2voHySdzHqaC-3c2u3np3fsE1IAhWu4mgAKo9ON7p9u6i2N9P7Xz0vrObae76znlfW8tp7vaz-qfz5YQxvr-VsrPysUaGVMiZpD60LOyWhSvSvsmqlIm2Spvx7016ZVrXfuGVgY6687c0rVX_duE1K106COmQTCBCXpe_uKWg-YN9oEjqXvFbj12hkHfsfyvb3p6pZ5ydKo0DTBtS8aDaK6ktm0pYcWe2h3J424Pbr2rLg_t2LpwbL0YFl6sCwHsSw9WJaDWB48WB48WB4sLGe4nEX14EH1MIhq40G18aDaDKLaDKLaeFBtWlTGmy3frj27dXH6SovqLke0FxDWLCcO8YfjsLe-9uWB9V04rqyYxLFOFX6eH44mbEUTbm7EGl6nEfAHYsuhrTy0gShzaN-aA22N9yzyPxWJDm3loQ3EpEPrIz8P_SuB6wtXh7by0AYC16F92OhfCW5fSDu0lYd2Nrh7tG-ovh5sQtyO--kdug1G6SJM5-GcjOhiMr25mQWT6TUeHRdpgvEsDSbX4STF1_N9sr_dJel8N50mwS29CUbZAgf4JpjhyWR2jTEe40k6mQUpCa_TJKDpHF0Hui1hY8Ze8zEXh1EmZUkXk5vrGQ5GjOwok-a-GmNTHBHG6OZuJBZ6wdWuPEh0HbBMKtmxUJlidFHV0r3ghaJFClnRVteqEKNwdRvcL3UJfop-6F7J3PXaV8qPjz90f6F4c7ELBGROGDtzDW6urtub5X1W0E5sfZc8mY9KwRa9m95MHcvdOOE5wmutRv1PM_6HJgrhtTGLRHhdW-Z1gf8XAAD__5QvegM">