[flang-commits] [flang] c4f67ea - [flang] Allow DATA initialization of derived types w/ allocatable components

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Feb 14 10:44:00 PST 2022


Author: Peter Klausler
Date: 2022-02-14T10:43:49-08:00
New Revision: c4f67ea12e95449c975c8bec43d2330b2a6ad8a8

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

LOG: [flang] Allow DATA initialization of derived types w/ allocatable components

While one cannot of course statically initialize an allocatable component
of an instance of a derived type, its mere presence should not prevent
DATA initialization of the other nonallocatable components.  Semantics
was treating the existence of an allocatable component as a case of
"default initialization", which it is, but not one that should run
afoul of C877.  Add another Boolean argument to IsInitialized() to allow
for a more nuanced test.

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

Added: 
    

Modified: 
    flang/include/flang/Semantics/tools.h
    flang/include/flang/Semantics/type.h
    flang/lib/Evaluate/initial-image.cpp
    flang/lib/Semantics/check-data.cpp
    flang/lib/Semantics/tools.cpp
    flang/lib/Semantics/type.cpp
    flang/test/Semantics/data04.f90
    flang/test/Semantics/data06.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index c52ee29c82c43..93676a4e39310 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -107,7 +107,8 @@ bool CanBeTypeBoundProc(const Symbol *);
 // attribute, or a derived type component default value.)
 bool HasDeclarationInitializer(const Symbol &);
 // Is the symbol explicitly or implicitly initialized in any way?
-bool IsInitialized(const Symbol &, bool ignoreDATAstatements = false);
+bool IsInitialized(const Symbol &, bool ignoreDATAstatements = false,
+    bool ignoreAllocatable = false);
 // Is the symbol a component subject to deallocation or finalization?
 bool IsDestructible(const Symbol &, const Symbol *derivedType = nullptr);
 bool HasIntrinsicTypeName(const Symbol &);

diff  --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h
index ecc7362147b60..f616d088a1bd5 100644
--- a/flang/include/flang/Semantics/type.h
+++ b/flang/include/flang/Semantics/type.h
@@ -265,7 +265,7 @@ class DerivedTypeSpec {
 
   bool MightBeParameterized() const;
   bool IsForwardReferenced() const;
-  bool HasDefaultInitialization() const;
+  bool HasDefaultInitialization(bool ignoreAllocatable = false) const;
   bool HasDestruction() const;
   bool HasFinalization() const;
 

diff  --git a/flang/lib/Evaluate/initial-image.cpp b/flang/lib/Evaluate/initial-image.cpp
index 6abca5704fbb6..298c1f7c4f65f 100644
--- a/flang/lib/Evaluate/initial-image.cpp
+++ b/flang/lib/Evaluate/initial-image.cpp
@@ -115,7 +115,7 @@ class AsConstantHelper {
                 typedValue[j].emplace(component, std::move(*value));
               }
             }
-          } else {
+          } else if (!IsAllocatable(component)) {
             auto componentType{DynamicType::From(component)};
             CHECK(componentType.has_value());
             auto componentExtents{GetConstantExtents(context_, component)};

diff  --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp
index fac8d9949a9a7..af04f84de88cf 100644
--- a/flang/lib/Semantics/check-data.cpp
+++ b/flang/lib/Semantics/check-data.cpp
@@ -62,7 +62,9 @@ class DataVarChecker : public evaluate::AllTraverse<DataVarChecker, true> {
                 : IsDummy(symbol)              ? "Dummy argument"
                 : IsFunctionResult(symbol)     ? "Function result"
                 : IsAllocatable(symbol)        ? "Allocatable"
-                : IsInitialized(symbol, true)  ? "Default-initialized"
+                : IsInitialized(symbol, true /*ignore DATA*/,
+                      true /*ignore allocatable components*/)
+                ? "Default-initialized"
                 : IsProcedure(symbol) && !IsPointer(symbol) ? "Procedure"
                 // remaining checks don't apply to components
                 : !isFirstSymbol                   ? nullptr

diff  --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index 02877df091c65..3b1ad208f81f3 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -558,10 +558,13 @@ bool HasDeclarationInitializer(const Symbol &symbol) {
   }
 }
 
-bool IsInitialized(const Symbol &symbol, bool ignoreDataStatements) {
-  if (IsAllocatable(symbol) ||
-      (!ignoreDataStatements && symbol.test(Symbol::Flag::InDataStmt)) ||
-      HasDeclarationInitializer(symbol)) {
+bool IsInitialized(
+    const Symbol &symbol, bool ignoreDataStatements, bool ignoreAllocatable) {
+  if (!ignoreAllocatable && IsAllocatable(symbol)) {
+    return true;
+  } else if (!ignoreDataStatements && symbol.test(Symbol::Flag::InDataStmt)) {
+    return true;
+  } else if (HasDeclarationInitializer(symbol)) {
     return true;
   } else if (IsNamedConstant(symbol) || IsFunctionResult(symbol) ||
       IsPointer(symbol)) {
@@ -569,12 +572,7 @@ bool IsInitialized(const Symbol &symbol, bool ignoreDataStatements) {
   } else if (const auto *object{symbol.detailsIf<ObjectEntityDetails>()}) {
     if (!object->isDummy() && object->type()) {
       if (const auto *derived{object->type()->AsDerived()}) {
-        DirectComponentIterator directs{*derived};
-        return bool{std::find_if(
-            directs.begin(), directs.end(), [](const Symbol &component) {
-              return IsAllocatable(component) ||
-                  HasDeclarationInitializer(component);
-            })};
+        return derived->HasDefaultInitialization(ignoreAllocatable);
       }
     }
   }

diff  --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp
index edd87221f6364..a92b936949bfb 100644
--- a/flang/lib/Semantics/type.cpp
+++ b/flang/lib/Semantics/type.cpp
@@ -177,10 +177,12 @@ bool DerivedTypeSpec::IsForwardReferenced() const {
   return typeSymbol_.get<DerivedTypeDetails>().isForwardReferenced();
 }
 
-bool DerivedTypeSpec::HasDefaultInitialization() const {
+bool DerivedTypeSpec::HasDefaultInitialization(bool ignoreAllocatable) const {
   DirectComponentIterator components{*this};
-  return bool{std::find_if(components.begin(), components.end(),
-      [&](const Symbol &component) { return IsInitialized(component); })};
+  return bool{std::find_if(
+      components.begin(), components.end(), [&](const Symbol &component) {
+        return IsInitialized(component, true, ignoreAllocatable);
+      })};
 }
 
 bool DerivedTypeSpec::HasDestruction() const {

diff  --git a/flang/test/Semantics/data04.f90 b/flang/test/Semantics/data04.f90
index aa085feb3a14e..79bec29f9807d 100644
--- a/flang/test/Semantics/data04.f90
+++ b/flang/test/Semantics/data04.f90
@@ -58,7 +58,7 @@ subroutine CheckObject(i)
         integer, allocatable :: allocVal
         integer, allocatable :: elt(:)
         integer val
-        type(specialNumbers) numsArray(5)
+        type(specialNumbers) numsArray(10)
       end type
       type(large) largeNumber
       type(large), allocatable :: allocatableLarge
@@ -69,8 +69,7 @@ subroutine CheckObject(i)
         real :: x
       end type
       type(small), pointer :: sp
-      !C877
-      !ERROR: Default-initialized 'largenumber' must not be initialized in a DATA statement
+      !This case is ok.
       DATA(largeNumber % numsArray(j) % headOfTheList, j = 1, 10) / 10 * NULL() /
       !C877
       !ERROR: Data object must not contain pointer 'headofthelist' as a non-rightmost part
@@ -80,12 +79,12 @@ subroutine CheckObject(i)
       DATA(largeNumber % numsArray(j) % ptoarray(1), j = 1, 10) / 10 * 1 /
       !C877
       !ERROR: Rightmost data object pointer 'ptochar' must not be subscripted
-      DATA largeNumber % numsArray(0) % ptochar(1:2) / 'ab' /
+      DATA largeNumber % numsArray(1) % ptochar(1:2) / 'ab' /
       !C876
-      !ERROR: Default-initialized 'largenumber' must not be initialized in a DATA statement
+      !ERROR: Allocatable 'elt' must not be initialized in a DATA statement
       DATA(largeNumber % elt(j) , j = 1, 10) / 10 * 1/
       !C876
-      !ERROR: Default-initialized 'largearray' must not be initialized in a DATA statement
+      !ERROR: Allocatable 'allocval' must not be initialized in a DATA statement
       DATA(largeArray(j) % allocVal , j = 1, 10) / 10 * 1/
       !C876
       !ERROR: Allocatable 'allocatablelarge' must not be initialized in a DATA statement

diff  --git a/flang/test/Semantics/data06.f90 b/flang/test/Semantics/data06.f90
index 9a5b2d8c48236..bf32fd8f3404b 100644
--- a/flang/test/Semantics/data06.f90
+++ b/flang/test/Semantics/data06.f90
@@ -7,6 +7,12 @@ subroutine s1
   type(t1) :: t1x
   !ERROR: Default-initialized 't1x' must not be initialized in a DATA statement
   data t1x%j / 777 /
+  type :: t2
+    integer, allocatable :: j
+    integer :: k
+  end type t2
+  type(t2) :: t2x
+  data t2x%k / 777 / ! allocatable component is ok
   integer :: ja = 888
   !ERROR: Default-initialized 'ja' must not be initialized in a DATA statement
   data ja / 999 /


        


More information about the flang-commits mailing list