[flang] fix private pointers and default initialized variables (#118494)
Both OpenMP privatization and DO CONCURRENT LOCAL lowering was incorrect
for pointers and derived type with default initialization.
For pointers, the descriptor was not established with the rank/type
code/element size, leading to undefined behavior if any inquiry was made
to it prior to a pointer assignment (and if/when using the runtime for
pointer assignments, the descriptor must have been established).
For derived type with default initialization, the copies were not
default initialized.
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index f518599..41b73956 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -711,8 +711,8 @@
return bool(shallowLookupSymbol(sym));
}
- bool createHostAssociateVarClone(
- const Fortran::semantics::Symbol &sym) override final {
+ bool createHostAssociateVarClone(const Fortran::semantics::Symbol &sym,
+ bool skipDefaultInit) override final {
mlir::Location loc = genLocation(sym.name());
mlir::Type symType = genType(sym);
const auto *details = sym.detailsIf<Fortran::semantics::HostAssocDetails>();
@@ -769,13 +769,21 @@
// Initialise cloned allocatable
hexv.match(
[&](const fir::MutableBoxValue &box) -> void {
- // Do not process pointers
+ const auto new_box = exv.getBoxOf<fir::MutableBoxValue>();
if (Fortran::semantics::IsPointer(sym.GetUltimate())) {
+ // Establish the pointer descriptors. The rank and type code/size
+ // at least must be set properly for later inquiry of the pointer
+ // to work, and new pointers are always given disassociated status
+ // by flang for safety, even if this is not required by the
+ // language.
+ auto empty = fir::factory::createUnallocatedBox(
+ *builder, loc, new_box->getBoxTy(), box.nonDeferredLenParams(),
+ {});
+ builder->create<fir::StoreOp>(loc, empty, new_box->getAddr());
return;
}
- // Allocate storage for a pointer/allocatble descriptor.
- // No shape/lengths to be passed to the alloca.
- const auto new_box = exv.getBoxOf<fir::MutableBoxValue>();
+ // Copy allocation status of Allocatables, creating new storage if
+ // needed.
// allocate if allocated
mlir::Value isAllocated =
@@ -823,7 +831,22 @@
if_builder.end();
},
[&](const auto &) -> void {
- // Do nothing
+ if (skipDefaultInit)
+ return;
+ // Initialize local/private derived types with default
+ // initialization (Fortran 2023 section 11.1.7.5 and OpenMP 5.2
+ // section 5.3). Pointer and allocatable components, when allowed,
+ // also need to be established so that flang runtime can later work
+ // with them.
+ if (const Fortran::semantics::DeclTypeSpec *declTypeSpec =
+ sym.GetType())
+ if (const Fortran::semantics::DerivedTypeSpec *derivedTypeSpec =
+ declTypeSpec->AsDerived())
+ if (derivedTypeSpec->HasDefaultInitialization(
+ /*ignoreAllocatable=*/false, /*ignorePointer=*/false)) {
+ mlir::Value box = builder->createBox(loc, exv);
+ fir::runtime::genDerivedTypeInitialize(*builder, loc, box);
+ }
});
return bindIfNewSymbol(sym, exv);
@@ -1966,9 +1989,9 @@
Fortran::semantics::SemanticsContext &semanticsContext =
bridge.getSemanticsContext();
for (const Fortran::semantics::Symbol *sym : info.localSymList)
- createHostAssociateVarClone(*sym);
+ createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
for (const Fortran::semantics::Symbol *sym : info.localInitSymList) {
- createHostAssociateVarClone(*sym);
+ createHostAssociateVarClone(*sym, /*skipDefaultInit=*/true);
const auto *hostDetails =
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
assert(hostDetails && "missing locality spec host symbol");
@@ -1986,6 +2009,9 @@
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
copySymbolBinding(hostDetails->symbol(), *sym);
}
+ // Note that allocatable, types with ultimate components, and type
+ // requiring finalization are forbidden in LOCAL/LOCAL_INIT (F2023 C1130),
+ // so no clean-up needs to be generated for these entities.
}
/// Generate FIR for a DO construct. There are six variants: