@@ -511,6 +511,9 @@ fir::GlobalOp Fortran::lower::defineGlobal(
511511 Fortran::semantics::IsProcedurePointer (sym))
512512 TODO (loc, " procedure pointer globals" );
513513
514+ const auto *oeDetails =
515+ sym.detailsIf <Fortran::semantics::ObjectEntityDetails>();
516+
514517 // If this is an array, check to see if we can use a dense attribute
515518 // with a tensor mlir type. This optimization currently only supports
516519 // Fortran arrays of integer, real, complex, or logical. The tensor
@@ -520,12 +523,10 @@ fir::GlobalOp Fortran::lower::defineGlobal(
520523 mlir::Type eleTy = mlir::cast<fir::SequenceType>(symTy).getElementType ();
521524 if (mlir::isa<mlir::IntegerType, mlir::FloatType, mlir::ComplexType,
522525 fir::LogicalType>(eleTy)) {
523- const auto *details =
524- sym.detailsIf <Fortran::semantics::ObjectEntityDetails>();
525- if (details->init ()) {
526+ if (oeDetails && oeDetails->init ()) {
526527 global = Fortran::lower::tryCreatingDenseGlobal (
527528 builder, loc, symTy, globalName, linkage, isConst,
528- details ->init ().value (), dataAttr);
529+ oeDetails ->init ().value (), dataAttr);
529530 if (global) {
530531 global.setVisibility (mlir::SymbolTable::Visibility::Public);
531532 return global;
@@ -539,10 +540,8 @@ fir::GlobalOp Fortran::lower::defineGlobal(
539540 isConst, var.isTarget (), dataAttr);
540541 if (Fortran::semantics::IsAllocatableOrPointer (sym) &&
541542 !Fortran::semantics::IsProcedure (sym)) {
542- const auto *details =
543- sym.detailsIf <Fortran::semantics::ObjectEntityDetails>();
544- if (details && details->init ()) {
545- auto expr = *details->init ();
543+ if (oeDetails && oeDetails->init ()) {
544+ auto expr = *oeDetails->init ();
546545 createGlobalInitialization (builder, global, [&](fir::FirOpBuilder &b) {
547546 mlir::Value box =
548547 Fortran::lower::genInitialDataTarget (converter, loc, symTy, expr);
@@ -558,15 +557,14 @@ fir::GlobalOp Fortran::lower::defineGlobal(
558557 fir::HasValueOp::create (b, loc, box);
559558 });
560559 }
561- } else if (const auto *details =
562- sym.detailsIf <Fortran::semantics::ObjectEntityDetails>()) {
563- if (details->init ()) {
560+ } else if (oeDetails) {
561+ if (oeDetails->init ()) {
564562 createGlobalInitialization (
565563 builder, global, [&](fir::FirOpBuilder &builder) {
566564 Fortran::lower::StatementContext stmtCtx (
567565 /* cleanupProhibited=*/ true );
568566 fir::ExtendedValue initVal = genInitializerExprValue (
569- converter, loc, details ->init ().value (), stmtCtx);
567+ converter, loc, oeDetails ->init ().value (), stmtCtx);
570568 mlir::Value castTo =
571569 builder.createConvert (loc, symTy, fir::getBase (initVal));
572570 fir::HasValueOp::create (builder, loc, castTo);
@@ -615,28 +613,32 @@ fir::GlobalOp Fortran::lower::defineGlobal(
615613 TODO (loc, " global" ); // Something else
616614 }
617615 // Creates zero initializer for globals without initializers, this is a common
618- // and expected behavior (although not required by the standard)
616+ // and expected behavior (although not required by the standard).
617+ // Exception: CDEFINED globals are treated as "extern" in C and don't need
618+ // initializer.
619619 if (!globalIsInitialized (global)) {
620- // Fortran does not provide means to specify that a BIND(C) module
621- // uninitialized variables will be defined in C.
622- // Add the common linkage to those to allow some level of support
623- // for this use case. Note that this use case will not work if the Fortran
624- // module code is placed in a shared library since, at least for the ELF
625- // format, common symbols are assigned a section in shared libraries.
626- // The best is still to declare C defined variables in a Fortran module file
627- // with no other definitions, and to never link the resulting module object
628- // file.
629- if (sym.attrs ().test (Fortran::semantics::Attr::BIND_C))
630- global.setLinkName (builder.createCommonLinkage ());
631- createGlobalInitialization (
632- builder, global, [&](fir::FirOpBuilder &builder) {
633- mlir::Value initValue;
634- if (converter.getLoweringOptions ().getInitGlobalZero ())
635- initValue = fir::ZeroOp::create (builder, loc, symTy);
636- else
637- initValue = fir::UndefOp::create (builder, loc, symTy);
638- fir::HasValueOp::create (builder, loc, initValue);
639- });
620+ if (!oeDetails || !oeDetails->isCDefined ()) {
621+ // Fortran does not provide means to specify that a BIND(C) module
622+ // uninitialized variables will be defined in C.
623+ // Add the common linkage to those to allow some level of support
624+ // for this use case. Note that this use case will not work if the Fortran
625+ // module code is placed in a shared library since, at least for the ELF
626+ // format, common symbols are assigned a section in shared libraries. The
627+ // best is still to declare C defined variables in a Fortran module file
628+ // with no other definitions, and to never link the resulting module
629+ // object file.
630+ if (sym.attrs ().test (Fortran::semantics::Attr::BIND_C))
631+ global.setLinkName (builder.createCommonLinkage ());
632+ createGlobalInitialization (
633+ builder, global, [&](fir::FirOpBuilder &builder) {
634+ mlir::Value initValue;
635+ if (converter.getLoweringOptions ().getInitGlobalZero ())
636+ initValue = fir::ZeroOp::create (builder, loc, symTy);
637+ else
638+ initValue = fir::UndefOp::create (builder, loc, symTy);
639+ fir::HasValueOp::create (builder, loc, initValue);
640+ });
641+ }
640642 }
641643 // Set public visibility to prevent global definition to be optimized out
642644 // even if they have no initializer and are unused in this compilation unit.
0 commit comments