Flang Bug: Incorrect SIZE With LBOUND/UBOUND/SHAPE

by Alex Johnson 51 views

Introduction

This article delves into a bug discovered in the Flang Fortran compiler, specifically affecting the SIZE intrinsic function when used in conjunction with LBOUND, UBOUND, or SHAPE. This issue, observed in Flang version 22.0.0, leads to incorrect results when the actual argument of SIZE is the result of one of these intrinsic functions. The problem arises under specific conditions related to assumed-type and assumed-rank dummy arguments. Let’s examine the details of this bug, its implications, and how it contrasts with previous versions and other compilers.

The Issue: Incorrect SIZE Results

The core of the problem lies in the incorrect evaluation of the SIZE intrinsic function when it receives the result of LBOUND, UBOUND, or SHAPE as its argument. According to the Fortran standard, the LBOUND intrinsic function, for instance, should return an array of rank one and size zero when the ARRAY argument is a scalar variable. However, Flang version 22.0.0 incorrectly returns 1 in such cases, while earlier versions (e.g., 21.1.2) and other compilers like Intel Fortran (ifx) produce the correct result (0).

This discrepancy can lead to significant issues in Fortran programs that rely on the correct behavior of these intrinsic functions for array manipulation and size determination. The impact is particularly pronounced in generic subroutines or functions that handle arrays of varying shapes and sizes.

Conditions for the Bug

The bug manifests itself under the following specific conditions:

  1. The intrinsic function LBOUND, UBOUND, or SHAPE appears in the actual argument of a SIZE intrinsic function reference.
  2. The argument of LBOUND, UBOUND, or SHAPE is a dummy argument with assumed type and assumed rank. An assumed-rank entity is a dummy argument that takes the rank from its actual argument. An assumed-type entity does not have a declared type; its type is taken from its actual argument.
  3. The actual argument corresponding to the assumed-type and assumed-rank dummy argument is a scalar.

When these three conditions are met, Flang 22.0.0 miscalculates the size, leading to incorrect program behavior.

Example Code: test.f90

To illustrate the issue, consider the following Fortran code snippet:

module m
implicit none
contains

subroutine sub(dd)
 implicit none
 type(*)::dd(..)
  print *,'rank(dd)        :',rank(dd)
  print *,'size(dd)        :',size(dd)
  print *,'lbound(dd)      : ',lbound(dd)
  print *,'rank(lbound(dd)):',rank(lbound(dd))
  print *,'size(lbound(dd)):',size(lbound(dd))  ! Incorrect
  if(size(lbound(dd)) /= 0) print*,'NG size(lbound(dd)):' ,size(lbound(dd))
  if(size(ubound(dd)) /= 0) print*,'NG size(ubound(dd)):' ,size(ubound(dd))
  if(size(shape(dd))/=0 )   print*,'NG size(shape(dd)):',size(shape(dd))
end subroutine sub

end module m

use m
integer::scalar
call sub(scalar)
print *,'pass'

In this example, the subroutine sub takes an assumed-type, assumed-rank dummy argument dd. When called with a scalar integer scalar, the LBOUND function should return an array of size 0. However, Flang 22.0.0 incorrectly reports the size as 1.

Observed Behavior

When compiled and executed with Flang 22.0.0, the output is:

$ flang test.f90
$ ./a.out
 rank(dd)        : 0
 size(dd)        : 1
 lbound(dd)      :
 rank(lbound(dd)): 1
 size(lbound(dd)): 1
 NG size(lbound(dd)): 1
 NG size(ubound(dd)): 1
 NG size(shape(dd)): 1
 pass

This output clearly shows that size(lbound(dd)) is incorrectly evaluated as 1.

In contrast, when compiled and executed with Flang version 21.1.6 or Intel Fortran (ifx), the output is correct:

$ /work/groups/ssoft/compiler/llvm/aarch64/21.1.6/bin/flang test.f90
$ ./a.out
 rank(dd)        : 0
 size(dd)        : 1
 lbound(dd)      :
 rank(lbound(dd)): 1
 size(lbound(dd)): 0
 pass
$ ifx test.f90
$ ./a.out
 rank(dd)        :           0
 size(dd)        :           1
 lbound(dd)      :
 rank(lbound(dd)):           1
 size(lbound(dd)):           0
 pass

These results confirm that the bug is specific to Flang 22.0.0 and that other compilers and older versions of Flang behave as expected.

Implications and Impact

The incorrect behavior of the SIZE intrinsic function can lead to several problems:

  1. Incorrect Array Handling: Programs that rely on the size of arrays returned by LBOUND, UBOUND, or SHAPE may misallocate memory, access array elements out of bounds, or perform incorrect calculations.
  2. Logic Errors: Conditional statements that depend on the size of these arrays may execute the wrong branches, leading to unexpected program behavior.
  3. Portability Issues: Code that works correctly with other Fortran compilers or older versions of Flang may fail or produce incorrect results when compiled with Flang 22.0.0.
  4. Debugging Challenges: The bug can be difficult to diagnose, as the incorrect size calculation may not immediately manifest as an error but could lead to subtle and hard-to-track-down issues later in the program's execution.

Fortran Standard Interpretation

The Fortran standard (specifically section 16.9.119 for LBOUND) clearly states the expected behavior:

16.9.119 LBOUND (ARRAY [, DIM, KIND])
:
Result Characteristics. Integer. If KIND is present, the kind type parameter is that specified by the value of
KIND; otherwise the kind type parameter is that of default integer type. The result is scalar if DIM is present;
otherwise, the result is an array of rank one and size n, where n is the rank of ARRAY.

When ARRAY is a scalar, the result of LBOUND should be an array of rank one and size 0. Flang 22.0.0 violates this standard by returning a size of 1.

Conclusion

The bug in Flang version 22.0.0, affecting the SIZE intrinsic function when used with LBOUND, UBOUND, or SHAPE under specific conditions, poses a significant issue for Fortran developers. This article has detailed the conditions under which the bug occurs, provided a concrete example demonstrating the incorrect behavior, and highlighted the potential implications for program correctness and portability. Developers using Flang 22.0.0 should be aware of this issue and consider using older versions of Flang or other Fortran compilers until a fix is available.

For more information on the Fortran standard and intrinsic functions, visit the Fortran standards website. This external resource can provide further details and clarifications on the correct behavior of Fortran features.