[flang-commits] [flang] 96aa481 - [flang] Make uninitialized allocatable components explicitly NULL() in structure constructors

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Mar 7 16:41:51 PST 2022


Author: Peter Klausler
Date: 2022-03-07T16:41:38-08:00
New Revision: 96aa48100c0b332b6e6821b664ad2fa5615c976a

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

LOG: [flang] Make uninitialized allocatable components explicitly NULL() in structure constructors

When a structure constructor does not initialize an allocatable component,
ensure that the typed expression representation contains an explicit
NULL() for the component.  Expression semantics already copies default
initialized expressions for nonallocatable components into structure
constructors.  This change is expected to simplify lowering.

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

Added: 
    flang/test/Semantics/modfile45.f90

Modified: 
    flang/lib/Evaluate/check-expression.cpp
    flang/lib/Semantics/expression.cpp
    flang/test/Semantics/oldparam02.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp
index 06be4da621bcd..dd8424e7728df 100644
--- a/flang/lib/Evaluate/check-expression.cpp
+++ b/flang/lib/Evaluate/check-expression.cpp
@@ -175,6 +175,12 @@ struct IsActuallyConstantHelper {
   template <typename T> bool operator()(const Expr<T> &x) {
     return std::visit([=](const auto &y) { return (*this)(y); }, x.u);
   }
+  bool operator()(const Expr<SomeType> &x) {
+    if (IsNullPointer(x)) {
+      return true;
+    }
+    return std::visit([this](const auto &y) { return (*this)(y); }, x.u);
+  }
   template <typename A> bool operator()(const A *x) { return x && (*this)(*x); }
   template <typename A> bool operator()(const std::optional<A> &x) {
     return x && (*this)(*x);

diff  --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index 095e191048f2e..2fcc7735c8757 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -1766,7 +1766,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(
                 *symbol);
           }
         } else if (IsAllocatable(*symbol) && IsBareNullPointer(&*value)) {
-          // NULL() with no arguments allowed by 7.5.10 para 6 for ALLOCATABLE
+          // NULL() with no arguments allowed by 7.5.10 para 6 for ALLOCATABLE.
+          result.Add(*symbol, Expr<SomeType>{NullPointer{}});
         } else if (auto symType{DynamicType::From(symbol)}) {
           if (IsAllocatable(*symbol) && symType->IsUnlimitedPolymorphic() &&
               valueType) {
@@ -1795,10 +1796,12 @@ MaybeExpr ExpressionAnalyzer::Analyze(
   // Ensure that unmentioned component objects have default initializers.
   for (const Symbol &symbol : components) {
     if (!symbol.test(Symbol::Flag::ParentComp) &&
-        unavailable.find(symbol.name()) == unavailable.cend() &&
-        !IsAllocatable(symbol)) {
-      if (const auto *details{
-              symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
+        unavailable.find(symbol.name()) == unavailable.cend()) {
+      if (IsAllocatable(symbol)) {
+        // Set all remaining allocatables to explicit NULL()
+        result.Add(symbol, Expr<SomeType>{NullPointer{}});
+      } else if (const auto *details{
+                     symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
         if (details->init()) {
           result.Add(symbol, common::Clone(*details->init()));
         } else { // C799

diff  --git a/flang/test/Semantics/modfile45.f90 b/flang/test/Semantics/modfile45.f90
new file mode 100644
index 0000000000000..ff31c809db8e3
--- /dev/null
+++ b/flang/test/Semantics/modfile45.f90
@@ -0,0 +1,24 @@
+! RUN: %python %S/test_modfile.py %s %flang_fc1
+! Ensures that uninitialized allocatable components in a structure constructor
+! appear with explicit NULL() in the expression representation.
+module m
+  type t
+    real, allocatable :: x1, x2, x3
+  end type
+  type t2
+    type(t) :: a = t(NULL(),x2=NULL())
+  end type
+end module
+
+!Expect: m.mod
+!module m
+!type::t
+!real(4),allocatable::x1
+!real(4),allocatable::x2
+!real(4),allocatable::x3
+!end type
+!type::t2
+!type(t)::a=t(x1=NULL(),x2=NULL(),x3=NULL())
+!end type
+!intrinsic::null
+!end

diff  --git a/flang/test/Semantics/oldparam02.f90 b/flang/test/Semantics/oldparam02.f90
index 4d8746af1b244..d3f56ee8d1d73 100644
--- a/flang/test/Semantics/oldparam02.f90
+++ b/flang/test/Semantics/oldparam02.f90
@@ -12,6 +12,7 @@ subroutine subr(x1,x2,x3,x4,x5)
   !CHECK: error: Must be a constant value
   parameter p2 = x2
   !CHECK: error: Whole assumed-size array 'x3' may not appear here without subscripts
+  !CHECK: error: Must be a constant value
   parameter p3 = x3
   !CHECK: error: Must be a constant value
   parameter p4 = x4


        


More information about the flang-commits mailing list