[flang-commits] [flang] [llvm] [Flang] KIND De-templatization (PR #216960)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Wed Oct 21 15:53:52 PDT 2026


================
@@ -1950,159 +2008,172 @@ template <typename DERIVED, typename RESULT, typename LEFT, typename RIGHT>
 auto ApplyElementwise(
     FoldingContext &context, Operation<DERIVED, RESULT, LEFT, RIGHT> &operation)
     -> std::optional<Expr<RESULT>> {
+  const int kind{operation.kind()};
   return ApplyElementwise(context, operation,
       std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)>{
-          [](Expr<LEFT> &&left, Expr<RIGHT> &&right) {
-            return Expr<RESULT>{DERIVED{std::move(left), std::move(right)}};
+          [kind](Expr<LEFT> &&left, Expr<RIGHT> &&right) {
+            return Expr<RESULT>{
+                DERIVED{kind, std::move(left), std::move(right)}};
           }});
 }
 
 // Unary operations
 
 template <typename TO, typename FROM>
-common::IfNoLvalue<std::optional<TO>, FROM> ConvertString(FROM &&s) {
-  if constexpr (std::is_same_v<TO, FROM>) {
+common::IfNoLvalue<std::optional<TO>, FROM> ConvertString(
+    int toKind, FROM &&s) {
+  const int fromKind{s.kind()};
+  if (std::is_same_v<TO, FROM> && toKind == fromKind) {
     return std::make_optional<TO>(std::move(s));
+  } else if (auto result{s.ToAscii(toKind)}; !result.IsNull()) {
----------------
eugeneepshteyn wrote:

(This comment was generated with the help of AI)

This makes non-ASCII CHARACTER conversions between kinds fold to blanks. `ToAscii` returns `Zero(kind)`, a non-null empty string, both for a null input and when a character is above 127, so this condition is always true and the `nullopt` branch is unreachable. The previous `ConvertString` returned `nullopt` for any character above 127, which left the conversion to run time or made a constant expression non-constant.

```fortran
program p
  character(kind=4, len=8) :: first
  first = '3.14 = π'
  print *, ichar(first(1:1)), len_trim(first)
end program
```

Before this PR this prints `51 8`; with it, `32 0`: the variable is all blanks. Initializations that the base compiler rejects with "cannot be computed as a constant value" are now accepted with blank values, e.g. `character(kind=4,len=3), parameter :: p = 'é!'`, the same in DATA, in a component default initializer (which then blanks every object of the type), in a structure constructor and in a typed array constructor; kind 2↔4 conversions are affected as well. Non-ASCII conversion between kinds is processor dependent, but this is not NFC, and folding now disagrees with the run-time conversion. Could `ToAscii` report failure in a way that cannot be confused with the legal value `''`? Please also add tests for these forms; `Integration/debug-char-type-1.f90` has the assignment above but checks only the debug info.


https://github.com/llvm/llvm-project/pull/216960


More information about the flang-commits mailing list