[flang-commits] [flang] [Flang] Avoid deep template recursion (PR #233865)

Michael Kruse via flang-commits flang-commits at lists.llvm.org
Wed Oct 21 01:21:08 PDT 2026


https://github.com/Meinersbur updated https://github.com/llvm/llvm-project/pull/233865

>From 3c041a3cb9d7be1f5e6bf737148ea4260014d1dd Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Tue, 20 Oct 2026 16:16:29 +0200
Subject: [PATCH 1/3] Avoid template recursion

---
 .../Optimizer/Builder/Runtime/RTBuilder.h     | 40 +++++++++----------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index 67bdf6867251a5..44cf292e6a9d82 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -27,7 +27,9 @@
 #include "mlir/IR/MLIRContext.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include <cstddef>
 #include <cstdint>
+#include <utility>
 
 #ifdef _MSC_VER
 // On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
@@ -762,32 +764,28 @@ template <char... Cs>
 using RuntimeIdentifier = std::integer_sequence<char, Cs...>;
 
 namespace details {
-template <typename T, T... As, T... Bs>
-static constexpr std::integer_sequence<T, As..., Bs...>
-concat(std::integer_sequence<T, As...>, std::integer_sequence<T, Bs...>) {
-  return {};
+template <typename T, std::size_t N>
+static constexpr std::size_t leadingNonZero(const T (&arr)[N]) {
+  std::size_t i = 0;
+  while (i < N && arr[i] != 0)
+    ++i;
+  return i;
 }
-template <typename T, T... As, T... Bs, typename... Cs>
-static constexpr auto concat(std::integer_sequence<T, As...>,
-                             std::integer_sequence<T, Bs...>, Cs...) {
-  return concat(std::integer_sequence<T, As..., Bs...>{}, Cs{}...);
-}
-template <typename T>
-static constexpr std::integer_sequence<T> concat(std::integer_sequence<T>) {
-  return {};
-}
-template <typename T, T a>
-static constexpr auto filterZero(std::integer_sequence<T, a>) {
-  if constexpr (a != 0) {
-    return std::integer_sequence<T, a>{};
-  } else {
-    return std::integer_sequence<T>{};
-  }
+template <typename T, T... b>
+struct LeadingNonZero {
+  static constexpr T arr[] = {b...};
+  static constexpr std::size_t value = leadingNonZero(arr);
+};
+template <typename T, T... b, std::size_t... I>
+static constexpr auto take(std::integer_sequence<T, b...>,
+                           std::index_sequence<I...>) {
+  return std::integer_sequence<T, LeadingNonZero<T, b...>::arr[I]...>{};
 }
 template <typename T, T... b>
 static constexpr auto filter(std::integer_sequence<T, b...>) {
   if constexpr (sizeof...(b) > 0) {
-    return details::concat(filterZero(std::integer_sequence<T, b>{})...);
+    return take(std::integer_sequence<T, b...>{},
+                std::make_index_sequence<LeadingNonZero<T, b...>::value>{});
   } else {
     return std::integer_sequence<T>{};
   }

>From 18acc21332efd9f577bd34ce48b446657bdb0ad2 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Tue, 20 Oct 2026 16:41:18 +0200
Subject: [PATCH 2/3] Avoid change noise

---
 flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index 44cf292e6a9d82..e80577ee006195 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -27,9 +27,7 @@
 #include "mlir/IR/MLIRContext.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
-#include <cstddef>
 #include <cstdint>
-#include <utility>
 
 #ifdef _MSC_VER
 // On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t

>From 30411fa9da42ecead9aa9d7a71b0a991f72315e9 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Wed, 21 Oct 2026 09:53:56 +0200
Subject: [PATCH 3/3] Address review by @eugeneepshteyn

---
 flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index e80577ee006195..07bb0fea2ef61d 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -27,7 +27,9 @@
 #include "mlir/IR/MLIRContext.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include <cstddef>
 #include <cstdint>
+#include <utility>
 
 #ifdef _MSC_VER
 // On Windows* OS GetCurrentProcessId returns DWORD aka uint32_t
@@ -779,6 +781,12 @@ static constexpr auto take(std::integer_sequence<T, b...>,
                            std::index_sequence<I...>) {
   return std::integer_sequence<T, LeadingNonZero<T, b...>::arr[I]...>{};
 }
+
+/// This is a helper for the mkRTKey macro; FirMacroExpandKey encodes runtime
+/// function names fixed-width template sequences of exactly 50 characters. This
+/// filter function removes the trailing '\0' characters. This is deliberately
+/// non-recursive because 50 nested template expansions might hit compiler
+/// limits, such as msvc's C1202.
 template <typename T, T... b>
 static constexpr auto filter(std::integer_sequence<T, b...>) {
   if constexpr (sizeof...(b) > 0) {



More information about the flang-commits mailing list