diff --git a/flang/include/flang/Evaluate/variable.h b/flang/include/flang/Evaluate/variable.h --- a/flang/include/flang/Evaluate/variable.h +++ b/flang/include/flang/Evaluate/variable.h @@ -303,15 +303,16 @@ public: CLASS_BOILERPLATE(Substring) - Substring(DataRef &&parent, std::optional> &&lower, + Substring(DataRef &&parent, int kind, + std::optional> &&lower, std::optional> &&upper) - : parent_{std::move(parent)} { + : parent_{std::move(parent)}, kind_{kind} { SetBounds(lower, upper); } - Substring(StaticDataObject::Pointer &&parent, + Substring(StaticDataObject::Pointer &&parent, int kind, std::optional> &&lower, std::optional> &&upper) - : parent_{std::move(parent)} { + : parent_{std::move(parent)}, kind_{kind} { SetBounds(lower, upper); } @@ -321,11 +322,15 @@ Substring &set_upper(Expr &&); const Parent &parent() const { return parent_; } Parent &parent() { return parent_; } + int kind() { return kind_; } int Rank() const; template const A *GetParentIf() const { return std::get_if(&parent_); } + std::optional GetType() const { + return DynamicType(TypeCategory::Character, kind_); + } BaseObject GetBaseObject() const; const Symbol *GetLastSymbol() const; std::optional> LEN() const; @@ -338,6 +343,7 @@ void SetBounds(std::optional> &, std::optional> &); Parent parent_; + int kind_{0}; std::optional lower_, upper_; }; diff --git a/flang/lib/Evaluate/fold-designator.cpp b/flang/lib/Evaluate/fold-designator.cpp --- a/flang/lib/Evaluate/fold-designator.cpp +++ b/flang/lib/Evaluate/fold-designator.cpp @@ -339,12 +339,12 @@ return std::visit( [&](const auto &x) -> std::optional> { using T = typename std::decay_t::Result; - return AsGenericExpr(Designator{ - Substring{ExtractDataRef(std::move(*cExpr)).value(), - std::optional>{ - 1 + (offset / T::kind)}, - std::optional>{ - 1 + ((offset + size - 1) / T::kind)}}}); + return AsGenericExpr(Designator{Substring{ + ExtractDataRef(std::move(*cExpr)).value(), T::kind, + std::optional>{ + 1 + (offset / T::kind)}, + std::optional>{ + 1 + ((offset + size - 1) / T::kind)}}}); }, cExpr->u); } diff --git a/flang/lib/Evaluate/fold.cpp b/flang/lib/Evaluate/fold.cpp --- a/flang/lib/Evaluate/fold.cpp +++ b/flang/lib/Evaluate/fold.cpp @@ -189,10 +189,11 @@ auto upper{Fold(context, substring.upper())}; if (const DataRef * dataRef{substring.GetParentIf()}) { return Substring{FoldOperation(context, DataRef{*dataRef}), - std::move(lower), std::move(upper)}; + substring.kind(), std::move(lower), std::move(upper)}; } else { auto p{*substring.GetParentIf()}; - return Substring{std::move(p), std::move(lower), std::move(upper)}; + return Substring{ + std::move(p), substring.kind(), std::move(lower), std::move(upper)}; } } diff --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp --- a/flang/lib/Evaluate/variable.cpp +++ b/flang/lib/Evaluate/variable.cpp @@ -562,10 +562,18 @@ template std::optional Designator::GetType() const { if constexpr (IsLengthlessIntrinsicType) { - return {Result::GetType()}; + return Result::GetType(); + } else if constexpr (Result::category == TypeCategory::Character) { + if (const Symbol * symbol{GetLastSymbol()}) { + return DynamicType::From(symbol); + } else if (const Substring * substring{std::get_if(&u)}) { + // Only really needed for character literal substrings + return substring->GetType(); + } } else { return DynamicType::From(GetLastSymbol()); } + return std::nullopt; } static NamedEntity AsNamedEntity(const SymbolVector &x) { diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -785,8 +785,8 @@ if (dynamicType->category() == TypeCategory::Character) { return WrapperHelper(dynamicType->kind(), - Substring{std::move(checked.value()), std::move(first), - std::move(last)}); + Substring{std::move(checked.value()), dynamicType->kind(), + std::move(first), std::move(last)}); } } Say("substring may apply only to CHARACTER"_err_en_US); @@ -826,7 +826,9 @@ staticData->set_alignment(Result::kind) .set_itemBytes(Result::kind) .Push(cp->GetScalarValue().value()); - Substring substring{std::move(staticData), std::move(lower.value()), + CHECK(string->GetType()); + Substring substring{std::move(staticData), + string->GetType()->kind(), std::move(lower.value()), std::move(upper.value())}; return AsGenericExpr( Expr{Designator{std::move(substring)}}); diff --git a/flang/test/Semantics/resolve49.f90 b/flang/test/Semantics/resolve49.f90 --- a/flang/test/Semantics/resolve49.f90 +++ b/flang/test/Semantics/resolve49.f90 @@ -11,6 +11,10 @@ ! Test substring program p2 + type t1(n1,n2) + integer,kind :: n1,n2 + integer :: c2(iachar('ABCDEFGHIJ'(n1:n1))) + end type character :: a(10) character :: b(5) integer :: n @@ -21,6 +25,7 @@ a(n:7) = b a(n+3:) = b a(:n+2) = b + n = Iachar(1_'ABCDEFGHIJ'(1:1)) end ! Test pointer assignment with bounds