<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">