[flang-commits] [flang] 43b304b - [flang] Support DATA statement initialization of numeric with Hollerith/CHARACTER
peter klausler via flang-commits
flang-commits at lists.llvm.org
Fri Aug 7 13:19:59 PDT 2020
Author: peter klausler
Date: 2020-08-07T13:17:36-07:00
New Revision: 43b304b09f892c305861de3113967c2714ab0d02
URL: https://github.com/llvm/llvm-project/commit/43b304b09f892c305861de3113967c2714ab0d02
DIFF: https://github.com/llvm/llvm-project/commit/43b304b09f892c305861de3113967c2714ab0d02.diff
LOG: [flang] Support DATA statement initialization of numeric with Hollerith/CHARACTER
This is a common Fortran language extension.
Differential Revision: https://reviews.llvm.org/D85492
Added:
flang/test/Semantics/data08.f90
Modified:
flang/lib/Semantics/check-data.cpp
flang/test/Semantics/data06.f90
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp
index 1aa52f06f642..49e28ba3a091 100644
--- a/flang/lib/Semantics/check-data.cpp
+++ b/flang/lib/Semantics/check-data.cpp
@@ -287,6 +287,9 @@ class DataInitializationCompiler {
bool InitDesignator(const SomeExpr &);
// Initializes a single object.
bool InitElement(const evaluate::OffsetSymbol &, const SomeExpr &designator);
+ // If the returned flag is true, emit a warning about CHARACTER misusage.
+ std::optional<std::pair<SomeExpr, bool>> ConvertElement(
+ const SomeExpr &, const evaluate::DynamicType &);
DataInitializations &inits_;
evaluate::ExpressionAnalyzer &exprAnalyzer_;
@@ -406,6 +409,32 @@ bool DataInitializationCompiler::InitDesignator(const SomeExpr &designator) {
return folder.isEmpty();
}
+std::optional<std::pair<SomeExpr, bool>>
+DataInitializationCompiler::ConvertElement(
+ const SomeExpr &expr, const evaluate::DynamicType &type) {
+ if (auto converted{evaluate::ConvertToType(type, SomeExpr{expr})}) {
+ return {std::make_pair(std::move(*converted), false)};
+ }
+ if (std::optional<std::string> chValue{evaluate::GetScalarConstantValue<
+ evaluate::Type<TypeCategory::Character, 1>>(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
+ std::size_t bytes{type.MeasureSizeInBytes().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<unsigned char>(ch)};
+ bits = bits.IOR(chBOZ.SHIFTL(8 * j));
+ }
+ if (auto converted{evaluate::ConvertToType(type, SomeExpr{bits})}) {
+ return {std::make_pair(std::move(*converted), true)};
+ }
+ }
+ return std::nullopt;
+}
+
bool DataInitializationCompiler::InitElement(
const evaluate::OffsetSymbol &offsetSymbol, const SomeExpr &designator) {
const Symbol &symbol{offsetSymbol.symbol()};
@@ -491,16 +520,19 @@ bool DataInitializationCompiler::InitElement(
"Initializer for '%s' must not be a procedure"_err_en_US,
DescribeElement());
} else if (auto designatorType{designator.GetType()}) {
- if (auto converted{
- evaluate::ConvertToType(*designatorType, SomeExpr{*expr})}) {
+ if (auto converted{ConvertElement(*expr, *designatorType)}) {
// value non-pointer initialization
if (std::holds_alternative<evaluate::BOZLiteralConstant>(expr->u) &&
designatorType->category() != TypeCategory::Integer) { // 8.6.7(11)
exprAnalyzer_.Say(values_.LocateSource(),
"BOZ literal should appear in a DATA statement only as a value for an integer object, but '%s' is '%s'"_en_US,
DescribeElement(), designatorType->AsFortran());
+ } else if (converted->second) {
+ exprAnalyzer_.context().Say(
+ "DATA statement value initializes '%s' of type '%s' with CHARACTER"_en_US,
+ DescribeElement(), designatorType->AsFortran());
}
- auto folded{evaluate::Fold(context, std::move(*converted))};
+ auto folded{evaluate::Fold(context, std::move(converted->first))};
switch (
GetImage().Add(offsetSymbol.offset(), offsetSymbol.size(), folded)) {
case evaluate::InitialImage::Ok:
diff --git a/flang/test/Semantics/data06.f90 b/flang/test/Semantics/data06.f90
index c21b99e8e484..4743eff3b8b6 100644
--- a/flang/test/Semantics/data06.f90
+++ b/flang/test/Semantics/data06.f90
@@ -39,7 +39,7 @@ real function rfunc(x)
!ERROR: Initializer for 'rt' must not be a procedure
data rt/rfunc/
integer :: jx, jy
- !ERROR: DATA statement value could not be converted to the type 'INTEGER(4)' of the object 'jx'
+ !WARNING: DATA statement value initializes 'jx' of type 'INTEGER(4)' with CHARACTER
data jx/'abc'/
!ERROR: DATA statement value could not be converted to the type 'INTEGER(4)' of the object 'jx'
data jx/t1()/
diff --git a/flang/test/Semantics/data08.f90 b/flang/test/Semantics/data08.f90
new file mode 100644
index 000000000000..86a87f90163f
--- /dev/null
+++ b/flang/test/Semantics/data08.f90
@@ -0,0 +1,17 @@
+! RUN: %f18 -fdebug-dump-symbols -fparse-only %s 2>&1 | FileCheck %s
+! CHECK: DATA statement value initializes 'jx' of type 'INTEGER(4)' with CHARACTER
+! CHECK: DATA statement value initializes 'jy' of type 'INTEGER(4)' with CHARACTER
+! CHECK: DATA statement value initializes 'jz' of type 'INTEGER(4)' with CHARACTER
+! CHECK: DATA statement value initializes 'kx' of type 'INTEGER(8)' with CHARACTER
+! CHECK: jx (InDataStmt) size=4 offset=0: ObjectEntity type: INTEGER(4) init:1684234849_4
+! CHECK: jy (InDataStmt) size=4 offset=4: ObjectEntity type: INTEGER(4) init:543384161_4
+! CHECK: jz (InDataStmt) size=4 offset=8: ObjectEntity type: INTEGER(4) init:1684234849_4
+! CHECK: kx (InDataStmt) size=8 offset=16: ObjectEntity type: INTEGER(8) init:7523094288207667809_8
+
+integer :: jx, jy, jz
+integer(8) :: kx
+data jx/4habcd/
+data jy/3habc/
+data jz/5habcde/
+data kx/'abcdefgh'/
+end
More information about the flang-commits
mailing list