[flang] Fix CHARACTER length folding problem

Do not rewrite LEN(x) or x%len to the expression that specifies
the length of x when that length is not a constant expression.
Its value may have changed since the value of the expression was
first captured in the definition of the object.

Reviewed By: tskeith, sscalpone

Differential Revision: https://reviews.llvm.org/D83352
This commit is contained in:
peter klausler 2020-07-07 15:30:47 -07:00
parent 22596e7b2f
commit 8f0f9eaddf
5 changed files with 25 additions and 20 deletions

View file

@ -146,7 +146,7 @@ public:
DynamicType ResultTypeForMultiply(const DynamicType &) const;
bool IsAssumedLengthCharacter() const;
bool IsUnknownLengthCharacter() const;
bool IsNonConstantLengthCharacter() const;
bool IsTypelessIntrinsicArgument() const;
constexpr bool IsAssumedType() const { // TYPE(*)
return kind_ == AssumedTypeKind;

View file

@ -612,7 +612,9 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
if (iter != scope->end()) {
const Symbol &symbol{*iter->second};
const auto *details{symbol.detailsIf<semantics::TypeParamDetails>()};
if (details && details->init()) {
if (details && details->init() &&
(details->attr() == common::TypeParamAttr::Kind ||
IsConstantExpr(*details->init()))) {
Expr<SomeInteger> expr{*details->init()};
return Fold(context,
Expr<IntKIND>{

View file

@ -205,7 +205,7 @@ auto GetLowerBoundHelper::operator()(const Symbol &symbol0) -> Result {
if (j++ == dimension_) {
if (const auto &bound{shapeSpec.lbound().GetExplicit()}) {
return Fold(context_, common::Clone(*bound));
} else if (semantics::IsDescriptor(symbol)) {
} else if (IsDescriptor(symbol)) {
return ExtentExpr{DescriptorInquiry{NamedEntity{symbol0},
DescriptorInquiry::Field::LowerBound, dimension_}};
} else {
@ -230,7 +230,7 @@ auto GetLowerBoundHelper::operator()(const Component &component) -> Result {
if (j++ == dimension_) {
if (const auto &bound{shapeSpec.lbound().GetExplicit()}) {
return Fold(context_, common::Clone(*bound));
} else if (semantics::IsDescriptor(symbol)) {
} else if (IsDescriptor(symbol)) {
return ExtentExpr{
DescriptorInquiry{NamedEntity{common::Clone(component)},
DescriptorInquiry::Field::LowerBound, dimension_}};

View file

@ -22,17 +22,21 @@
// IsDescriptor() predicate: true when a symbol is implemented
// at runtime with a descriptor.
// TODO there's probably a better place for this predicate than here
namespace Fortran::semantics {
static bool IsDescriptor(const ObjectEntityDetails &details) {
if (const auto *type{details.type()}) {
static bool IsDescriptor(const DeclTypeSpec *type) {
if (type) {
if (auto dynamicType{evaluate::DynamicType::From(*type)}) {
if (dynamicType->RequiresDescriptor()) {
return true;
}
return dynamicType->RequiresDescriptor();
}
}
return false;
}
static bool IsDescriptor(const ObjectEntityDetails &details) {
if (IsDescriptor(details.type())) {
return true;
}
// TODO: Automatic (adjustable) arrays - are they descriptors?
for (const ShapeSpec &shapeSpec : details.shape()) {
const auto &lb{shapeSpec.lbound().GetExplicit()};
@ -62,6 +66,7 @@ bool IsDescriptor(const Symbol &symbol) {
symbol.attrs().test(Attr::EXTERNAL)) &&
IsDescriptor(d);
},
[&](const EntityDetails &d) { return IsDescriptor(d.type()); },
[](const AssocEntityDetails &d) {
if (const auto &expr{d.expr()}) {
if (expr->Rank() > 0) {
@ -149,7 +154,7 @@ bool DynamicType::IsAssumedLengthCharacter() const {
charLength_->isAssumed();
}
bool DynamicType::IsUnknownLengthCharacter() const {
bool DynamicType::IsNonConstantLengthCharacter() const {
if (category_ != TypeCategory::Character) {
return false;
} else if (!charLength_) {
@ -471,7 +476,7 @@ DynamicType DynamicType::ResultTypeForMultiply(const DynamicType &that) const {
}
bool DynamicType::RequiresDescriptor() const {
return IsPolymorphic() || IsUnknownLengthCharacter() ||
return IsPolymorphic() || IsNonConstantLengthCharacter() ||
(derived_ && CountNonConstantLenParameters(*derived_) > 0);
}

View file

@ -8,6 +8,7 @@
#include "flang/Evaluate/variable.h"
#include "flang/Common/idioms.h"
#include "flang/Evaluate/check-expression.h"
#include "flang/Evaluate/fold.h"
#include "flang/Evaluate/tools.h"
#include "flang/Parser/char-block.h"
@ -259,16 +260,13 @@ static std::optional<Expr<SubscriptInteger>> SymbolLEN(const Symbol &sym) {
if (const semantics::ParamValue * len{dyType->charLength()}) {
if (len->isExplicit()) {
if (auto intExpr{len->GetExplicit()}) {
return ConvertToType<SubscriptInteger>(*std::move(intExpr));
} else {
// There was an error constructing this symbol's type. It should
// have a length expression, but we couldn't retrieve it
return std::nullopt;
if (IsConstantExpr(*intExpr)) {
return ConvertToType<SubscriptInteger>(*std::move(intExpr));
}
}
} else {
return Expr<SubscriptInteger>{
DescriptorInquiry{NamedEntity{sym}, DescriptorInquiry::Field::Len}};
}
return Expr<SubscriptInteger>{
DescriptorInquiry{NamedEntity{sym}, DescriptorInquiry::Field::Len}};
}
}
return std::nullopt;