diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index ad44de71ee828..dd024a0a1ec79 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -595,14 +595,17 @@ static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter, // Creates zero initializer for globals without initializers, this is a common // and expected behavior (although not required by the standard) if (!globalIsInitialized(global)) { - // TODO: For BIND(C) variables, an initial value may be given in another - // compilation unit (on the C side), and setting an zero init here creates - // linkage conflicts. See if there is a way to get it zero initialized if - // not initialized elsewhere. MLIR also used to drop globals without - // initializers that are not used in the file, but this may not be true - // anymore. + // Fortran does not provide means to specify that a BIND(C) module + // uninitialized variables will be defined in C. + // Add the common linkage to those to allow some level of support + // for this use case. Note that this use case will not work if the Fortran + // module code is placed in a shared library since, at least for the ELF + // format, common symbols are assigned a section in shared libraries. + // The best is still to declare C defined variables in a Fortran module file + // with no other definitions, and to never link the resulting module object + // file. if (sym.attrs().test(Fortran::semantics::Attr::BIND_C)) - TODO(loc, "BIND(C) module variable linkage"); + global.setLinkName(builder.createCommonLinkage()); Fortran::lower::createGlobalInitialization( builder, global, [&](fir::FirOpBuilder &builder) { mlir::Value initValue = builder.create(loc, symTy); diff --git a/flang/test/Lower/HLFIR/bindc-module-var.f90 b/flang/test/Lower/HLFIR/bindc-module-var.f90 new file mode 100644 index 0000000000000..20848078b3eba --- /dev/null +++ b/flang/test/Lower/HLFIR/bindc-module-var.f90 @@ -0,0 +1,29 @@ +! Test BIND(C) module variable lowering +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + +module some_c_module + integer, bind(c, name="i_var") :: i = 1 + integer, bind(c, name="i_var_no_init") :: i_no_init + integer, bind(c) :: j_var = 2 + integer, bind(c) :: j_var_no_init +end module + +! CHECK-LABEL: fir.global @i_var : i32 { +! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32 +! CHECK: fir.has_value %[[VAL_0]] : i32 +! CHECK: } + +! CHECK-LABEL: fir.global common @i_var_no_init : i32 { +! CHECK: %[[VAL_0:.*]] = fir.zero_bits i32 +! CHECK: fir.has_value %[[VAL_0]] : i32 +! CHECK: } + +! CHECK-LABEL: fir.global @j_var : i32 { +! CHECK: %[[VAL_0:.*]] = arith.constant 2 : i32 +! CHECK: fir.has_value %[[VAL_0]] : i32 +! CHECK: } + +! CHECK-LABEL: fir.global common @j_var_no_init : i32 { +! CHECK: %[[VAL_0:.*]] = fir.zero_bits i32 +! CHECK: fir.has_value %[[VAL_0]] : i32 +! CHECK: }