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 bool operator()(const Expr &x) { return std::visit([=](const auto &y) { return (*this)(y); }, x.u); } + bool operator()(const Expr &x) { + if (IsNullPointer(x)) { + return true; + } + return std::visit([this](const auto &y) { return (*this)(y); }, x.u); + } template bool operator()(const A *x) { return x && (*this)(*x); } template bool operator()(const std::optional &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{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()}) { + unavailable.find(symbol.name()) == unavailable.cend()) { + if (IsAllocatable(symbol)) { + // Set all remaining allocatables to explicit NULL() + result.Add(symbol, Expr{NullPointer{}}); + } else if (const auto *details{ + symbol.detailsIf()}) { 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