是否允许为另一个过程的可选参数传递一个不存在的假定形状数组?

Is passing an absent assumed-shape array for an optional argument of another procedure allowed?

在这个最小的例子中,是否允许将 test_wrapper 的可选伪参数 y 传递给相应的可选伪参数 [=] 而不是 present 的实际参数11=] 共 test?

program main
    implicit none
    real :: x = 5.0
    call test_wrapper(x)

contains
    subroutine test_wrapper(x, y)
        implicit none
        real, intent(in) :: x
        real, dimension(:), intent(out), optional :: y
        call test(x, y)
    end subroutine test_wrapper

    subroutine test(x, y)
        implicit none
        real, intent(in) :: x
        real, dimension(:), intent(out), optional :: y
        if (present(y)) then
            y = x
        end if
    end subroutine test
end program

UndefinedBehaviourSanitizer 引发错误,表明它不是:https://godbolt.org/z/nKj1h6G9r

this Fortran standards document(第 15.5.2.12 节,“参数存在和对参数不存在的限制”第 311 页)中它说:

  1. An optional dummy argument that is not present is subject to the following restrictions.
    1. If it is a data object, it shall not be referenced or be defined. If it is of a type that has default initialization, the initialization has no effect.
    2. [...]
    3. [...]
    4. [...]
    5. A designator with it as the base object and with one or more subobject selectors shall not be supplied as an actual argument.
    6. [...]
    7. If it is a pointer, it shall not be allocated, deallocated, nullified, pointerassigned, or supplied as an actual argument corresponding to an optional nonpointer dummy argument.
    8. If it is allocatable, it shall not be allocated, deallocated, or supplied as an actual argument corresponding to an optional nonallocatable dummy argument.
    9. [...]
  2. Except as noted in the list above, it may be supplied as an actual argument corresponding to an optional dummy argument, which is then also considered not to be present.

我正在努力阅读该列表中的标准语,所以也许其中一个我不完全理解的项目禁止对假定形状数组进行此操作?但在我看来,none 的限制适用于这种情况。

但有趣的是,UBSan 似乎仅在使用 dimension(:) 时才会引发错误,即如果 y 是假定形状数组。 dimension(2)dimension(n) 以及添加的大小参数 nallocatablepointer 之类的任何其他内容似乎都不会触发 UBSan。

对于缺少可选伪参数的假定形状的使用没有额外的限制。允许将不存在的假设形状数组参数作为另一个过程中可选伪参数的实际参数,除非另一个限制阻止它。 (随后的虚拟参数将被视为不存在。)

如前所述,none 列出的限制提到了“假定形状”。特别是,您引用的 none(如 Ian Bush 评论)适用于这种情况。这使得“除了上面列表中提到的,它可能会被提供......”是宽容的。

如果要进一步检查,每个子程序的假定形状参数y是一个普通虚拟变量(并遵守15.5.2.4的规则).

gfortran 7 没有抱怨。可能是这个版本不理解-std=f2018.

有关

为了完整起见,让我们 运行 了解为什么限制(所有,而不仅仅是问题中引用的限制)不适用。我不会引用这些限制,所以好奇的人需要查找那些不在问题中的文本。

  1. y 不存在时既没有被引用也没有被定义(显示为实参不是引用或定义)。
  2. y 都没有出现在指针赋值中(也不是指针)。
  3. y 都不是过程或过程指针。
  4. test_wrapper
  5. y 未用作非可选伪参数的实际参数; testy 未用作实参。
  6. test_wrapper中实际参数是y本身,而不是y的子对象; test 中的 y 未用作实参。
  7. 虽然是数组,但 y 都没有使用实际参数来引用基本过程。
  8. y 都不是指针。
  9. y 均不可分配。
  10. y 都没有长度类型参数(尤其是没有被查询过)。
  11. y 均未用作选择器。
  12. 过程指示符中均未使用 y
  13. 程序组件引用中均未使用 y

下面更简单的程序显示了相同的问题:

program main
    implicit none
    call test_wrapper

contains
    subroutine test_wrapper(y)
        real, dimension(1), intent(out), optional :: y
        call test(y)
    end subroutine test_wrapper

    subroutine test(y)
        real, dimension(:), intent(out), optional :: y
        if (present(y)) y=0  ! Used to silence unrelated warning
    end subroutine test
end program