[flang-commits] [flang] c78b528 - [flang][runtime] Handle conflicts for derived types with dynamic components.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Thu Jul 27 13:56:23 PDT 2023


Author: Slava Zakharin
Date: 2023-07-27T13:56:13-07:00
New Revision: c78b528f99ba3824fc939f05cd21ebd53d6e816b

URL: https://github.com/llvm/llvm-project/commit/c78b528f99ba3824fc939f05cd21ebd53d6e816b
DIFF: https://github.com/llvm/llvm-project/commit/c78b528f99ba3824fc939f05cd21ebd53d6e816b.diff

LOG: [flang][runtime] Handle conflicts for derived types with dynamic components.

When creating a temporary for conflicting LHS and RHS we have to deep copy
the dynamic (allocatable, automatic) components from RHS to the temp.
Otherwise, the conflict may still be present between LHS and temp.

gfortran/regression/alloc_comp_assign_1.f90 is an example where the current
runtime code produces wrong result:
https://github.com/llvm/llvm-test-suite/blob/7b5b5dcbf9bdde729a14722eb67f9c3ab01647c7/Fortran/gfortran/regression/alloc_comp_assign_1.f90#L50

Reviewed By: klausler, tblah

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

Added: 
    

Modified: 
    flang/runtime/assign.cpp
    flang/runtime/derived.cpp
    flang/runtime/derived.h

Removed: 
    


################################################################################
diff  --git a/flang/runtime/assign.cpp b/flang/runtime/assign.cpp
index 8c1ee296c02ac8..c0d50e4e7ead47 100644
--- a/flang/runtime/assign.cpp
+++ b/flang/runtime/assign.cpp
@@ -285,16 +285,31 @@ static void Assign(
       newFrom.raw().attribute = CFI_attribute_allocatable;
       auto stat{ReturnError(terminator, newFrom.Allocate())};
       if (stat == StatOk) {
-        char *toAt{newFrom.OffsetElement()};
-        std::size_t fromElements{from.Elements()};
-        if (from.IsContiguous()) {
-          std::memcpy(
-              toAt, from.OffsetElement(), fromElements * fromElementBytes);
+        if (HasDynamicComponent(from)) {
+          // If 'from' has allocatable/automatic component, we cannot
+          // just make a shallow copy of the descriptor member.
+          // This will still leave data overlap in 'to' and 'newFrom'.
+          // For example:
+          //   type t
+          //     character, allocatable :: c(:)
+          //   end type t
+          //   type(t) :: x(3)
+          //   x(2:3) = x(1:2)
+          // We have to make a deep copy into 'newFrom' in this case.
+          RTNAME(AssignTemporary)
+          (newFrom, from, terminator.sourceFileName(), terminator.sourceLine());
         } else {
-          SubscriptValue fromAt[maxRank];
-          for (from.GetLowerBounds(fromAt); fromElements-- > 0;
-               toAt += fromElementBytes, from.IncrementSubscripts(fromAt)) {
-            std::memcpy(toAt, from.Element<char>(fromAt), fromElementBytes);
+          char *toAt{newFrom.OffsetElement()};
+          std::size_t fromElements{from.Elements()};
+          if (from.IsContiguous()) {
+            std::memcpy(
+                toAt, from.OffsetElement(), fromElements * fromElementBytes);
+          } else {
+            SubscriptValue fromAt[maxRank];
+            for (from.GetLowerBounds(fromAt); fromElements-- > 0;
+                 toAt += fromElementBytes, from.IncrementSubscripts(fromAt)) {
+              std::memcpy(toAt, from.Element<char>(fromAt), fromElementBytes);
+            }
           }
         }
         Assign(to, newFrom, terminator,

diff  --git a/flang/runtime/derived.cpp b/flang/runtime/derived.cpp
index 814fcfa1e1e7dd..ac9b1c5906f424 100644
--- a/flang/runtime/derived.cpp
+++ b/flang/runtime/derived.cpp
@@ -258,4 +258,22 @@ void Destroy(const Descriptor &descriptor, bool finalize,
   }
 }
 
+bool HasDynamicComponent(const Descriptor &descriptor) {
+  if (const DescriptorAddendum * addendum{descriptor.Addendum()}) {
+    if (const auto *derived = addendum->derivedType()) {
+      const Descriptor &componentDesc{derived->component()};
+      std::size_t myComponents{componentDesc.Elements()};
+      for (std::size_t k{0}; k < myComponents; ++k) {
+        const auto &comp{
+            *componentDesc.ZeroBasedIndexedElement<typeInfo::Component>(k)};
+        if (comp.genre() == typeInfo::Component::Genre::Allocatable ||
+            comp.genre() == typeInfo::Component::Genre::Automatic) {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
 } // namespace Fortran::runtime

diff  --git a/flang/runtime/derived.h b/flang/runtime/derived.h
index d655a672a84d45..894cdfd9a598c3 100644
--- a/flang/runtime/derived.h
+++ b/flang/runtime/derived.h
@@ -31,5 +31,9 @@ void Finalize(const Descriptor &, const typeInfo::DerivedType &derived);
 // Does not deallocate the original descriptor.
 void Destroy(const Descriptor &, bool finalize, const typeInfo::DerivedType &);
 
+// Return true if the passed descriptor is for a derived type
+// entity that has a dynamic (allocatable, automatic) component.
+bool HasDynamicComponent(const Descriptor &);
+
 } // namespace Fortran::runtime
 #endif // FORTRAN_RUNTIME_DERIVED_H_


        


More information about the flang-commits mailing list