From 4eccba942ea450b7b20653944648dd2ec734ae5d Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 26 Feb 2019 15:59:25 -0800 Subject: [PATCH] [flang] Clean up DynamicType, link it to symbol table character length Original-commit: flang-compiler/f18@833f5f52e24895ccd48a35dbcc999633fc7d26b4 Reviewed-on: https://github.com/flang-compiler/f18/pull/304 Tree-same-pre-rewrite: false --- flang/lib/evaluate/characteristics.cc | 26 ++---------------------- flang/lib/evaluate/characteristics.h | 15 +++++++------- flang/lib/evaluate/constant.h | 4 +--- flang/lib/evaluate/expression.cc | 2 +- flang/lib/evaluate/expression.h | 4 +--- flang/lib/evaluate/fold.cc | 2 +- flang/lib/evaluate/type.cc | 25 +++++++++++++++++++---- flang/lib/evaluate/type.h | 28 +++++++++++++++++--------- flang/lib/semantics/expression.cc | 38 ++++++++++++++++++++++------------- 9 files changed, 77 insertions(+), 67 deletions(-) diff --git a/flang/lib/evaluate/characteristics.cc b/flang/lib/evaluate/characteristics.cc index 182ed28..4db93a2 100644 --- a/flang/lib/evaluate/characteristics.cc +++ b/flang/lib/evaluate/characteristics.cc @@ -31,18 +31,7 @@ std::ostream &DummyDataObject::Dump(std::ostream &o) const { if (intent != common::Intent::Default) { o << "INTENT(" << common::EnumToString(intent) << ')'; } - // TODO pmk WIP: generalize this too - if (type.category == common::TypeCategory::Character) { - if (characterLength.get() == nullptr) { - o << type.AsFortran(":"s); - } else { - std::stringstream ss; - characterLength->AsFortran(ss); - o << type.AsFortran(ss.str()); - } - } else { - o << type.AsFortran(); - } + o << type.AsFortran(); if (!shape.empty()) { char sep{'('}; for (const auto &expr : shape) { @@ -86,18 +75,7 @@ bool FunctionResult::operator==(const FunctionResult &that) const { std::ostream &FunctionResult::Dump(std::ostream &o) const { attrs.Dump(o, EnumToString); - if (type.category == TypeCategory::Character) { - if (characterLength.get() == nullptr) { - o << type.AsFortran("*"s); - } else { - std::stringstream ss; - characterLength->AsFortran(o); - o << type.AsFortran(ss.str()); - } - } else { - o << type.AsFortran(); - } - return o << " rank " << rank; + return o << type.AsFortran() << " rank " << rank; } bool Procedure::operator==(const Procedure &that) const { diff --git a/flang/lib/evaluate/characteristics.h b/flang/lib/evaluate/characteristics.h index 8495e2a..0f309d89 100644 --- a/flang/lib/evaluate/characteristics.h +++ b/flang/lib/evaluate/characteristics.h @@ -21,10 +21,10 @@ #include "expression.h" #include "type.h" +#include "../common/enum-set.h" #include "../common/fortran.h" #include "../common/idioms.h" #include "../common/indirection.h" -#include "../common/enum-set.h" #include #include #include @@ -42,10 +42,9 @@ namespace Fortran::evaluate::characteristics { // 15.3.2.2 struct DummyDataObject { - ENUM_CLASS(Attr, AssumedRank, Optional, Allocatable, Asynchronous, - Contiguous, Value, Volatile, Polymorphic, Pointer, Target) + ENUM_CLASS(Attr, AssumedRank, Optional, Allocatable, Asynchronous, Contiguous, + Value, Volatile, Polymorphic, Pointer, Target) DynamicType type; - std::unique_ptr> characterLength; std::vector>> shape; std::vector> coshape; common::Intent intent{common::Intent::Default}; @@ -70,14 +69,14 @@ struct AlternateReturn { }; // 15.3.2.1 -using DummyArgument = std::variant; +using DummyArgument = + std::variant; // 15.3.3 struct FunctionResult { - ENUM_CLASS(Attr, Polymorphic, Allocatable, Pointer, Contiguous, - ProcedurePointer) + ENUM_CLASS( + Attr, Polymorphic, Allocatable, Pointer, Contiguous, ProcedurePointer) DynamicType type; - std::unique_ptr> characterLength; int rank{0}; common::EnumSet attrs; bool operator==(const FunctionResult &) const; diff --git a/flang/lib/evaluate/constant.h b/flang/lib/evaluate/constant.h index 9a455fc..aa81ea1 100644 --- a/flang/lib/evaluate/constant.h +++ b/flang/lib/evaluate/constant.h @@ -149,9 +149,7 @@ public: return *derivedTypeSpec_; } - DynamicType GetType() const { - return DynamicType{TypeCategory::Derived, 0, derivedTypeSpec_}; - } + DynamicType GetType() const { return DynamicType{derivedTypeSpec()}; } private: const semantics::DerivedTypeSpec *derivedTypeSpec_; diff --git a/flang/lib/evaluate/expression.cc b/flang/lib/evaluate/expression.cc index b321b10..ba46905 100644 --- a/flang/lib/evaluate/expression.cc +++ b/flang/lib/evaluate/expression.cc @@ -262,7 +262,7 @@ bool StructureConstructor::operator==(const StructureConstructor &that) const { } DynamicType StructureConstructor::GetType() const { - return {TypeCategory::Derived, 0, derivedTypeSpec_}; + return DynamicType{*derivedTypeSpec_}; } StructureConstructor &StructureConstructor::Add( diff --git a/flang/lib/evaluate/expression.h b/flang/lib/evaluate/expression.h index 36f7aab..26316ef 100644 --- a/flang/lib/evaluate/expression.h +++ b/flang/lib/evaluate/expression.h @@ -473,9 +473,7 @@ public: const semantics::DerivedTypeSpec &derivedTypeSpec() const { return *derivedTypeSpec_; } - DynamicType GetType() const { - return DynamicType{TypeCategory::Derived, 0, derivedTypeSpec_}; - } + DynamicType GetType() const { return DynamicType{derivedTypeSpec()}; } std::ostream &AsFortran(std::ostream &) const; private: diff --git a/flang/lib/evaluate/fold.cc b/flang/lib/evaluate/fold.cc index 39889dc..1ca68e8 100644 --- a/flang/lib/evaluate/fold.cc +++ b/flang/lib/evaluate/fold.cc @@ -357,7 +357,7 @@ Expr> FoldOperation( if (value->isExplicit()) { return Fold(context, Expr{Convert( - value->GetExplicit().value())}); + Expr{value->GetExplicit().value()})}); } } } diff --git a/flang/lib/evaluate/type.cc b/flang/lib/evaluate/type.cc index 5863574..0d71b34 100644 --- a/flang/lib/evaluate/type.cc +++ b/flang/lib/evaluate/type.cc @@ -91,7 +91,7 @@ namespace Fortran::evaluate { bool DynamicType::operator==(const DynamicType &that) const { return category == that.category && kind == that.kind && - derived == that.derived; + charLength == that.charLength && derived == that.derived; } std::optional GetSymbolType(const semantics::Symbol *symbol) { @@ -101,11 +101,16 @@ std::optional GetSymbolType(const semantics::Symbol *symbol) { if (auto kind{ToInt64(intrinsic->kind())}) { TypeCategory category{intrinsic->category()}; if (IsValidKindOfIntrinsicType(category, *kind)) { - return DynamicType{category, static_cast(*kind)}; + if (category == TypeCategory::Character) { + const auto &charType{type->characterTypeSpec()}; + return DynamicType{static_cast(*kind), charType.length()}; + } else { + return DynamicType{category, static_cast(*kind)}; + } } } } else if (const auto *derived{type->AsDerived()}) { - return DynamicType{TypeCategory::Derived, 0, derived}; + return DynamicType{*derived}; } } } @@ -116,6 +121,18 @@ std::string DynamicType::AsFortran() const { if (derived != nullptr) { CHECK(category == TypeCategory::Derived); return "TYPE("s + derived->typeSymbol().name().ToString() + ')'; + } else if (charLength != nullptr) { + std::string result{"CHARACTER(KIND="s + std::to_string(kind) + ",LEN="}; + if (charLength->isAssumed()) { + result += ",LEN=*"; + } else if (charLength->isDeferred()) { + result += ",LEN=:"; + } else if (const auto &length{charLength->GetExplicit()}) { + std::stringstream ss; + length->AsFortran(ss << ",LEN="); + result += ss.str(); + } + return result + ')'; } else { return EnumToString(category) + '(' + std::to_string(kind) + ')'; } @@ -124,7 +141,7 @@ std::string DynamicType::AsFortran() const { std::string DynamicType::AsFortran(std::string &&charLenExpr) const { if (!charLenExpr.empty() && category == TypeCategory::Character) { return "CHARACTER(KIND=" + std::to_string(kind) + - ",len=" + std::move(charLenExpr) + ')'; + ",LEN=" + std::move(charLenExpr) + ')'; } else { return AsFortran(); } diff --git a/flang/lib/evaluate/type.h b/flang/lib/evaluate/type.h index b84786c..f9dbb5b 100644 --- a/flang/lib/evaluate/type.h +++ b/flang/lib/evaluate/type.h @@ -38,6 +38,7 @@ namespace Fortran::semantics { class DerivedTypeSpec; +class ParamValue; class Symbol; bool IsDescriptor(const Symbol &); } @@ -54,21 +55,30 @@ using SubscriptInteger = Type; using LogicalResult = Type; using LargestReal = Type; -// DynamicType is suitable for use as the result type for -// GetType() functions and member functions; consequently, -// it must be capable of being used in a constexpr context. -// So it does *not* hold anything requiring a destructor, -// such as a CHARACTER length type parameter expression. -// Those must be derived via LEN() member functions or packaged -// elsewhere (e.g. as in ArrayConstructor). +// DynamicType is meant to be suitable for use as the result type for +// GetType() functions and member functions; consequently, it must be +// capable of being used in a constexpr context. So it does *not* +// directly hold anything requiring a destructor, such as an arbitrary +// CHARACTER length type parameter expression. Those must be derived +// via LEN() member functions, packaged elsewhere (e.g. as in +// ArrayConstructor), or copied from a parameter spec in the symbol table +// if one is supplied. struct DynamicType { + constexpr DynamicType() = default; + constexpr DynamicType(TypeCategory cat, int k) : category{cat}, kind{k} {} + constexpr DynamicType(int k, const semantics::ParamValue &pv) + : category{TypeCategory::Character}, kind{k}, charLength{&pv} {} + explicit constexpr DynamicType(const semantics::DerivedTypeSpec &dt) + : category{TypeCategory::Derived}, derived{&dt} {} + bool operator==(const DynamicType &) const; std::string AsFortran() const; std::string AsFortran(std::string &&charLenExpr) const; DynamicType ResultTypeForMultiply(const DynamicType &) const; - TypeCategory category; + TypeCategory category{TypeCategory::Integer}; // overridable default int kind{0}; // set only for intrinsic types + const semantics::ParamValue *charLength{nullptr}; const semantics::DerivedTypeSpec *derived{nullptr}; // TYPE(T), CLASS(T) }; @@ -264,7 +274,7 @@ public: CLASS_BOILERPLATE(SomeKind) explicit SomeKind(const semantics::DerivedTypeSpec &dts) : spec_{&dts} {} - DynamicType GetType() const { return DynamicType{category, 0, spec_}; } + DynamicType GetType() const { return DynamicType{spec()}; } const semantics::DerivedTypeSpec &spec() const { return *spec_; } bool operator==(const SomeKind &) const; std::string AsFortran() const; diff --git a/flang/lib/semantics/expression.cc b/flang/lib/semantics/expression.cc index 317faeb..596a041 100644 --- a/flang/lib/semantics/expression.cc +++ b/flang/lib/semantics/expression.cc @@ -115,9 +115,22 @@ struct CallAndArguments { }; struct DynamicTypeWithLength : public DynamicType { + std::optional> LEN() const; std::optional> length; }; +std::optional> DynamicTypeWithLength::LEN() const { + if (length.has_value()) { + return length; + } + if (charLength != nullptr) { + if (const auto &len{charLength->GetExplicit()}) { + return ConvertToType(common::Clone(*len)); + } + } + return std::nullopt; +} + std::optional AnalyzeTypeSpec( ExpressionAnalysisContext &context, const std::optional &spec) { @@ -129,24 +142,22 @@ std::optional AnalyzeTypeSpec( if (const semantics::IntrinsicTypeSpec * intrinsic{typeSpec->AsIntrinsic()}) { TypeCategory category{intrinsic->category()}; - if (auto kind{ToInt64(intrinsic->kind())}) { - DynamicTypeWithLength result{{category, static_cast(*kind)}}; + if (auto optKind{ToInt64(intrinsic->kind())}) { + int kind{static_cast(*optKind)}; if (category == TypeCategory::Character) { const semantics::CharacterTypeSpec &cts{ typeSpec->characterTypeSpec()}; - const semantics::ParamValue len{cts.length()}; + const semantics::ParamValue &len{cts.length()}; // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() & // type guards, but not in array constructors. - if (len.GetExplicit().has_value()) { - Expr copy{*len.GetExplicit()}; - result.length = ConvertToType(std::move(copy)); - } + return DynamicTypeWithLength{DynamicType{kind, len}}; + } else { + return DynamicTypeWithLength{DynamicType{category, kind}}; } - return result; } } else if (const semantics::DerivedTypeSpec * derived{typeSpec->AsDerived()}) { - return DynamicTypeWithLength{{TypeCategory::Derived, 0, derived}}; + return DynamicTypeWithLength{DynamicType{*derived}}; } } } @@ -1178,7 +1189,7 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) { if (static_cast(*type_) == static_cast(xType)) { values_.Push(std::move(*x)); - if (auto thisLen{ToInt64(xType.length)}) { + if (auto thisLen{ToInt64(xType.LEN())}) { if (constantLength_.has_value()) { if (exprContext_.context().warnOnNonstandardUsage() && *thisLen != *constantLength_) { @@ -1191,11 +1202,11 @@ void ArrayConstructorContext::Push(MaybeExpr &&x) { // length of the array constructor's character elements, not the // first, when there is no explicit type. *constantLength_ = *thisLen; - type_->length = std::move(xType.length); + type_->length = xType.LEN(); } } else { constantLength_ = *thisLen; - type_->length = std::move(xType.length); + type_->length = xType.LEN(); } } } else { @@ -1333,9 +1344,8 @@ struct ArrayConstructorTypeVisitor { *type.derived, MakeSpecific(std::move(values))}); } else if (type.kind == T::kind) { if constexpr (T::category == TypeCategory::Character) { - CHECK(type.length.has_value()); return AsMaybeExpr(ArrayConstructor{ - std::move(*type.length), MakeSpecific(std::move(values))}); + type.LEN().value(), MakeSpecific(std::move(values))}); } else { return AsMaybeExpr( ArrayConstructor{MakeSpecific(std::move(values))}); -- 2.7.4