[flang][NFC] Document behavior for nonspecified/ambiguous cases
authorpeter klausler <pklausler@nvidia.com>
Mon, 4 Oct 2021 19:40:35 +0000 (12:40 -0700)
committerpeter klausler <pklausler@nvidia.com>
Mon, 11 Oct 2021 18:06:07 +0000 (11:06 -0700)
Add explicit documentation for a couple of cases where the Fortran
standard has been observed to be ambiguous or nonspecific and we've
had to choose the behavior of the implementation from some possible
alternatives (and may be distinct from other implementations).

Differential Revision: https://reviews.llvm.org/D111446

flang/docs/Extensions.md
flang/runtime/derived.cpp

index 3b07cf1..f35954b 100644 (file)
@@ -263,3 +263,69 @@ end
   This Fortran 2008 feature might as well be viewed like an
   extension; no other compiler that we've tested can handle
   it yet.
+
+## Behavior in cases where the standard is ambiguous or indefinite
+
+* When an inner procedure of a subprogram uses the value or an attribute
+  of an undeclared name in a specification expression and that name does
+  not appear in the host, it is not clear in the standard whether that
+  name is an implicitly typed local variable of the inner procedure or a
+  host association with an implicitly typed local variable of the host.
+  For example:
+```
+module module
+ contains
+  subroutine host(j)
+    ! Although "m" never appears in the specification or executable
+    ! parts of this subroutine, both of its contained subroutines
+    ! might be accessing it via host association.
+    integer, intent(in out) :: j
+    call inner1(j)
+    call inner2(j)
+   contains
+    subroutine inner1(n)
+      integer(kind(m)), intent(in) :: n
+      m = n + 1
+    end subroutine
+    subroutine inner2(n)
+      integer(kind(m)), intent(out) :: n
+      n = m + 2
+    end subroutine
+  end subroutine
+end module
+
+program demo
+  use module
+  integer :: k
+  k = 0
+  call host(k)
+  print *, k, " should be 3"
+end
+
+```
+
+  Other Fortran compilers disagree in their interpretations of this example;
+  some seem to treat the references to `m` as if they were host associations
+  to an implicitly typed variable (and print `3`), while others seem to
+  treat them as references to implicitly typed local variabless, and
+  load uninitialized values.
+
+  In f18, we chose to emit an error message for this case since the standard
+  is unclear, the usage is not portable, and the issue can be easily resolved
+  by adding a declaration.
+
+* In subclause 7.5.6.2 of Fortran 2018 the standard defines a partial ordering
+  of the final subroutine calls for finalizable objects, their non-parent
+  components, and then their parent components.
+  (The object is finalized, then the non-parent components of each element,
+  and then the parent component.)
+  Some have argued that the standard permits an implementation
+  to finalize the parent component before finalizing an allocatable component in
+  the context of deallocation, and the next revision of the language may codify
+  this option.
+  In the interest of avoiding needless confusion, this compiler implements what
+  we believe to be the least surprising order of finalization.
+  Specifically: all non-parent components are finalized before
+  the parent, allocatable or not;
+  all finalization takes place before any deallocation;
+  and no object or subobject will be finalized more than once.
index 887d813..f9e34b2 100644 (file)
@@ -208,8 +208,9 @@ void Finalize(
 }
 
 // The order of finalization follows Fortran 2018 7.5.6.2, with
-// elementwise deallocation of non-parent components (and their consequent
-// finalizations) taking place before parent component finalization.
+// elementwise finalization of non-parent components taking place
+// before parent component finalization, and with all finalization
+// preceding any deallocation.
 void Destroy(const Descriptor &descriptor, bool finalize,
     const typeInfo::DerivedType &derived) {
   if (derived.noDestructionNeeded() || !descriptor.IsAllocated()) {