Index: flang/include/flang/Evaluate/tools.h =================================================================== --- flang/include/flang/Evaluate/tools.h +++ flang/include/flang/Evaluate/tools.h @@ -1076,6 +1076,11 @@ std::optional> DataConstantConversionExtension( FoldingContext &, const DynamicType &, const Expr &); +// Convert Hollerith or short character to a another type as if the +// Hollerith data had been BOZ. +std::optional> HollerithToBOZ( + FoldingContext &, const Expr &, const DynamicType &); + } // namespace Fortran::evaluate namespace Fortran::semantics { Index: flang/lib/Evaluate/tools.cpp =================================================================== --- flang/lib/Evaluate/tools.cpp +++ flang/lib/Evaluate/tools.cpp @@ -1125,6 +1125,25 @@ IsAllocatableOrPointerObject(expr, context); } +std::optional> HollerithToBOZ(FoldingContext &context, + const Expr &expr, const DynamicType &type) { + if (std::optional chValue{GetScalarConstantValue(expr)}) { + // Pad on the right with spaces when short, truncate the right if long. + // TODO: big-endian targets + auto bytes{static_cast( + ToInt64(type.MeasureSizeInBytes(context, false)).value())}; + BOZLiteralConstant bits{0}; + for (std::size_t j{0}; j < bytes; ++j) { + char ch{j >= chValue->size() ? ' ' : chValue->at(j)}; + BOZLiteralConstant chBOZ{static_cast(ch)}; + bits = bits.IOR(chBOZ.SHIFTL(8 * j)); + } + return ConvertToType(type, Expr{bits}); + } else { + return std::nullopt; + } +} + } // namespace Fortran::evaluate namespace Fortran::semantics { Index: flang/lib/Semantics/check-call.cpp =================================================================== --- flang/lib/Semantics/check-call.cpp +++ flang/lib/Semantics/check-call.cpp @@ -176,6 +176,17 @@ ConvertIntegerActual(actual, dummy.type, actualType, messages); } bool typesCompatible{dummy.type.type().IsTkCompatibleWith(actualType.type())}; + if (!typesCompatible && dummy.type.Rank() == 0) { + // Extension: pass Hollerith literal to scalar as if it had been BOZ + if (auto converted{ + evaluate::HollerithToBOZ(context, actual, dummy.type.type())}) { + messages.Say( + "passing Hollerith or character literal as if it were BOZ"_port_en_US); + actual = *converted; + actualType.type() = dummy.type.type(); + typesCompatible = true; + } + } if (typesCompatible) { if (isElemental) { } else if (dummy.type.attrs().test( Index: flang/lib/Semantics/data-to-inits.cpp =================================================================== --- flang/lib/Semantics/data-to-inits.cpp +++ flang/lib/Semantics/data-to-inits.cpp @@ -274,24 +274,11 @@ if (auto converted{evaluate::ConvertToType(type, SomeExpr{expr})}) { return {std::make_pair(std::move(*converted), false)}; } - if (std::optional chValue{ - evaluate::GetScalarConstantValue(expr)}) { - // Allow DATA initialization with Hollerith and kind=1 CHARACTER like - // (most) other Fortran compilers do. Pad on the right with spaces - // when short, truncate the right if long. - // TODO: big-endian targets - auto bytes{static_cast(evaluate::ToInt64( - type.MeasureSizeInBytes(exprAnalyzer_.GetFoldingContext(), false)) - .value())}; - evaluate::BOZLiteralConstant bits{0}; - for (std::size_t j{0}; j < bytes; ++j) { - char ch{j >= chValue->size() ? ' ' : chValue->at(j)}; - evaluate::BOZLiteralConstant chBOZ{static_cast(ch)}; - bits = bits.IOR(chBOZ.SHIFTL(8 * j)); - } - if (auto converted{evaluate::ConvertToType(type, SomeExpr{bits})}) { - return {std::make_pair(std::move(*converted), true)}; - } + // Allow DATA initialization with Hollerith and kind=1 CHARACTER like + // (most) other Fortran compilers do. + if (auto converted{evaluate::HollerithToBOZ( + exprAnalyzer_.GetFoldingContext(), expr, type)}) { + return {std::make_pair(std::move(*converted), true)}; } SemanticsContext &context{exprAnalyzer_.context()}; if (context.IsEnabled(common::LanguageFeature::LogicalIntegerAssignment)) {