From 95b4e65ecf225865dcb80ba3c916bd4d992e3fb3 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Wed, 27 Mar 2019 15:27:33 -0700 Subject: [PATCH] [flang] Move some AsFortran() implementations into new formatting.cc; use precedence for parentheses Original-commit: flang-compiler/f18@2b5fa051df3c8e183349388181e66e085385396e Reviewed-on: https://github.com/flang-compiler/f18/pull/371 Tree-same-pre-rewrite: false --- flang/lib/FIR/statements.cc | 2 +- flang/lib/evaluate/CMakeLists.txt | 1 + flang/lib/evaluate/call.cc | 31 +-- flang/lib/evaluate/call.h | 3 +- flang/lib/evaluate/complex.h | 1 + flang/lib/evaluate/constant.cc | 84 +------ flang/lib/evaluate/constant.h | 11 +- flang/lib/evaluate/expression.cc | 173 +------------ flang/lib/evaluate/expression.h | 75 +++--- flang/lib/evaluate/fold.cc | 2 +- flang/lib/evaluate/formatting.cc | 390 ++++++++++++++++++++++++++++++ flang/lib/evaluate/formatting.h | 46 ++++ flang/lib/evaluate/real.h | 1 + flang/lib/evaluate/static-data.h | 1 + flang/lib/evaluate/type.h | 101 ++++---- flang/lib/evaluate/variable.cc | 4 +- flang/lib/evaluate/variable.h | 5 +- flang/lib/semantics/mod-file.cc | 8 +- flang/lib/semantics/symbol.cc | 14 +- flang/lib/semantics/type.cc | 10 +- 20 files changed, 572 insertions(+), 391 deletions(-) create mode 100644 flang/lib/evaluate/formatting.cc create mode 100644 flang/lib/evaluate/formatting.h diff --git a/flang/lib/FIR/statements.cc b/flang/lib/FIR/statements.cc index a41d097bbe3f..b1d3bccacb68 100644 --- a/flang/lib/FIR/statements.cc +++ b/flang/lib/FIR/statements.cc @@ -30,7 +30,7 @@ Addressable_impl *GetAddressable(Statement *stmt) { static std::string dump(const Expression &e) { std::stringstream stringStream; - e.AsFortran(stringStream); + stringStream << e.v; return stringStream.str(); } diff --git a/flang/lib/evaluate/CMakeLists.txt b/flang/lib/evaluate/CMakeLists.txt index df8730fa4ca3..f2faa1703ac3 100644 --- a/flang/lib/evaluate/CMakeLists.txt +++ b/flang/lib/evaluate/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(FortranEvaluate decimal.cc expression.cc fold.cc + formatting.cc host.cc integer.cc intrinsics.cc diff --git a/flang/lib/evaluate/call.cc b/flang/lib/evaluate/call.cc index aefb901855fa..102b9fefc92e 100644 --- a/flang/lib/evaluate/call.cc +++ b/flang/lib/evaluate/call.cc @@ -29,16 +29,6 @@ bool ActualArgument::operator==(const ActualArgument &that) const { isAlternateReturn == that.isAlternateReturn && value() == that.value(); } -std::ostream &ActualArgument::AsFortran(std::ostream &o) const { - if (keyword.has_value()) { - o << keyword->ToString() << '='; - } - if (isAlternateReturn) { - o << '*'; - } - return value().AsFortran(o); -} - std::optional ActualArgument::VectorSize() const { if (Rank() != 1) { return std::nullopt; @@ -52,10 +42,6 @@ bool SpecificIntrinsic::operator==(const SpecificIntrinsic &that) const { attrs == that.attrs; } -std::ostream &SpecificIntrinsic::AsFortran(std::ostream &o) const { - return o << name; -} - std::optional ProcedureDesignator::GetType() const { if (const auto *intrinsic{std::get_if(&u)}) { return intrinsic->type; @@ -96,26 +82,11 @@ const Symbol *ProcedureDesignator::GetSymbol() const { u); } -std::ostream &ProcedureRef::AsFortran(std::ostream &o) const { - proc_.AsFortran(o); - char separator{'('}; - for (const auto &arg : arguments_) { - if (arg.has_value()) { - arg->AsFortran(o << separator); - separator = ','; - } - } - if (separator == '(') { - o << '('; - } - return o << ')'; -} - Expr ProcedureRef::LEN() const { // TODO: the results of the intrinsic functions REPEAT and TRIM have // unpredictable lengths; maybe the concept of LEN() has to become dynamic return proc_.LEN(); } -FOR_EACH_SPECIFIC_TYPE(template class FunctionRef) +FOR_EACH_SPECIFIC_TYPE(template class FunctionRef, ) } diff --git a/flang/lib/evaluate/call.h b/flang/lib/evaluate/call.h index 0ae8565cd5cc..5b11df1ca15a 100644 --- a/flang/lib/evaluate/call.h +++ b/flang/lib/evaluate/call.h @@ -17,6 +17,7 @@ #include "common.h" #include "constant.h" +#include "formatting.h" #include "type.h" #include "../common/indirection.h" #include "../parser/char-block.h" @@ -134,6 +135,6 @@ public: std::optional> Fold(FoldingContext &); // for intrinsics }; -FOR_EACH_SPECIFIC_TYPE(extern template class FunctionRef) +FOR_EACH_SPECIFIC_TYPE(extern template class FunctionRef, ) } #endif // FORTRAN_EVALUATE_CALL_H_ diff --git a/flang/lib/evaluate/complex.h b/flang/lib/evaluate/complex.h index 41fcae4d2148..26a47c14435e 100644 --- a/flang/lib/evaluate/complex.h +++ b/flang/lib/evaluate/complex.h @@ -15,6 +15,7 @@ #ifndef FORTRAN_EVALUATE_COMPLEX_H_ #define FORTRAN_EVALUATE_COMPLEX_H_ +#include "formatting.h" #include "real.h" #include diff --git a/flang/lib/evaluate/constant.cc b/flang/lib/evaluate/constant.cc index d09a4d3aa906..2e2cc7340642 100644 --- a/flang/lib/evaluate/constant.cc +++ b/flang/lib/evaluate/constant.cc @@ -15,7 +15,6 @@ #include "constant.h" #include "expression.h" #include "type.h" -#include "../parser/characters.h" #include namespace Fortran::evaluate { @@ -23,59 +22,6 @@ namespace Fortran::evaluate { template ConstantBase::~ConstantBase() {} -static void ShapeAsFortran( - std::ostream &o, const std::vector &shape) { - if (shape.size() > 1) { - o << ",shape="; - char ch{'['}; - for (auto dim : shape) { - o << ch << dim; - ch = ','; - } - o << "])"; - } -} - -template -std::ostream &ConstantBase::AsFortran(std::ostream &o) const { - if (Rank() > 1) { - o << "reshape("; - } - if (Rank() > 0) { - o << '[' << GetType().AsFortran() << "::"; - } - bool first{true}; - for (const auto &value : values_) { - if (first) { - first = false; - } else { - o << ','; - } - if constexpr (Result::category == TypeCategory::Integer) { - o << value.SignedDecimal() << '_' << Result::kind; - } else if constexpr (Result::category == TypeCategory::Real || - Result::category == TypeCategory::Complex) { - value.AsFortran(o, Result::kind); - } else if constexpr (Result::category == TypeCategory::Character) { - o << Result::kind << '_' << parser::QuoteCharacterLiteral(value); - } else if constexpr (Result::category == TypeCategory::Logical) { - if (value.IsTrue()) { - o << ".true."; - } else { - o << ".false."; - } - o << '_' << Result::kind; - } else { - StructureConstructor{AsConstant().derivedTypeSpec(), value}.AsFortran(o); - } - } - if (Rank() > 0) { - o << ']'; - } - ShapeAsFortran(o, shape_); - return o; -} - static std::int64_t SubscriptsToOffset(const std::vector &index, const std::vector &shape) { CHECK(index.size() == shape.size()); @@ -178,32 +124,6 @@ Constant>::SHAPE() const { return ShapeAsConstant(shape_); } -template -std::ostream &Constant>::AsFortran( - std::ostream &o) const { - if (Rank() > 1) { - o << "reshape("; - } - if (Rank() > 0) { - o << '[' << GetType().AsFortran(std::to_string(length_)) << "::"; - } - auto total{static_cast(size())}; - for (std::int64_t j{0}; j < total; ++j) { - ScalarValue value{values_.substr(j * length_, length_)}; - if (j > 0) { - o << ','; - } else if (Rank() == 0) { - o << Result::kind << '_'; - } - o << parser::QuoteCharacterLiteral(value); - } - if (Rank() > 0) { - o << ']'; - } - ShapeAsFortran(o, shape_); - return o; -} - // Constant specialization Constant::Constant(const StructureConstructor &x) : Base{x.values()}, derivedTypeSpec_{&x.derivedTypeSpec()} {} @@ -228,7 +148,5 @@ Constant::Constant(const semantics::DerivedTypeSpec &spec, std::vector &&x, std::vector &&s) : Base{GetValues(std::move(x)), std::move(s)}, derivedTypeSpec_{&spec} {} -FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase) -template class ConstantBase; -FOR_EACH_INTRINSIC_KIND(template class Constant) +INSTANTIATE_CONSTANT_TEMPLATES } diff --git a/flang/lib/evaluate/constant.h b/flang/lib/evaluate/constant.h index cb3396771ea9..78cb69b620f4 100644 --- a/flang/lib/evaluate/constant.h +++ b/flang/lib/evaluate/constant.h @@ -15,6 +15,7 @@ #ifndef FORTRAN_EVALUATE_CONSTANT_H_ #define FORTRAN_EVALUATE_CONSTANT_H_ +#include "formatting.h" #include "type.h" #include #include @@ -55,6 +56,7 @@ public: } bool empty() const { return values_.empty(); } std::size_t size() const { return values_.size(); } + const std::vector &values() const { return values_; } const std::vector &shape() const { return shape_; } ScalarValue operator*() const { @@ -155,8 +157,13 @@ private: const semantics::DerivedTypeSpec *derivedTypeSpec_; }; -FOR_EACH_LENGTHLESS_INTRINSIC_KIND(extern template class ConstantBase) +FOR_EACH_LENGTHLESS_INTRINSIC_KIND(extern template class ConstantBase, ) extern template class ConstantBase; -FOR_EACH_INTRINSIC_KIND(extern template class Constant) +FOR_EACH_INTRINSIC_KIND(extern template class Constant, ) + +#define INSTANTIATE_CONSTANT_TEMPLATES \ + FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase, ) \ + template class ConstantBase; \ + FOR_EACH_INTRINSIC_KIND(template class Constant, ) } #endif // FORTRAN_EVALUATE_CONSTANT_H_ diff --git a/flang/lib/evaluate/expression.cc b/flang/lib/evaluate/expression.cc index d286a707e42b..399881ee48c2 100644 --- a/flang/lib/evaluate/expression.cc +++ b/flang/lib/evaluate/expression.cc @@ -19,8 +19,6 @@ #include "variable.h" #include "../common/idioms.h" #include "../parser/message.h" -#include -#include #include #include @@ -28,136 +26,6 @@ using namespace Fortran::parser::literals; namespace Fortran::evaluate { -// AsFortran() formatting - -template -std::ostream &Operation::AsFortran(std::ostream &o) const { - left().AsFortran(derived().Prefix(o)); - if constexpr (operands > 1) { - right().AsFortran(derived().Infix(o)); - } - return derived().Suffix(o); -} - -template -std::ostream &Convert::AsFortran(std::ostream &o) const { - static_assert(TO::category == TypeCategory::Integer || - TO::category == TypeCategory::Real || - TO::category == TypeCategory::Character || - TO::category == TypeCategory::Logical || !"Convert<> to bad category!"); - if constexpr (TO::category == TypeCategory::Character) { - this->left().AsFortran(o << "achar(iachar(") << ')'; - } else if constexpr (TO::category == TypeCategory::Integer) { - this->left().AsFortran(o << "int("); - } else if constexpr (TO::category == TypeCategory::Real) { - this->left().AsFortran(o << "real("); - } else { - this->left().AsFortran(o << "logical("); - } - return o << ",kind=" << TO::kind << ')'; -} - -template std::ostream &Relational::Infix(std::ostream &o) const { - switch (opr) { - case RelationalOperator::LT: o << '<'; break; - case RelationalOperator::LE: o << "<="; break; - case RelationalOperator::EQ: o << "=="; break; - case RelationalOperator::NE: o << "/="; break; - case RelationalOperator::GE: o << ">="; break; - case RelationalOperator::GT: o << '>'; break; - } - return o; -} - -std::ostream &Relational::AsFortran(std::ostream &o) const { - std::visit([&](const auto &rel) { rel.AsFortran(o); }, u); - return o; -} - -template -std::ostream &LogicalOperation::Infix(std::ostream &o) const { - switch (logicalOperator) { - case LogicalOperator::And: o << ".and."; break; - case LogicalOperator::Or: o << ".or."; break; - case LogicalOperator::Eqv: o << ".eqv."; break; - case LogicalOperator::Neqv: o << ".neqv."; break; - } - return o; -} - -template -std::ostream &Emit( - std::ostream &o, const common::CopyableIndirection> &expr) { - return expr.value().AsFortran(o); -} - -template -std::ostream &Emit(std::ostream &, const ArrayConstructorValues &); - -template -std::ostream &Emit(std::ostream &o, const ImpliedDo &implDo) { - o << '('; - Emit(o, implDo.values()); - o << ',' << ImpliedDoIndex::Result::AsFortran() - << "::" << implDo.name().ToString() << '='; - implDo.lower().AsFortran(o) << ','; - implDo.upper().AsFortran(o) << ','; - implDo.stride().AsFortran(o) << ')'; - return o; -} - -template -std::ostream &Emit(std::ostream &o, const ArrayConstructorValues &values) { - const char *sep{""}; - for (const auto &value : values.values()) { - o << sep; - std::visit([&](const auto &x) { Emit(o, x); }, value.u); - sep = ","; - } - return o; -} - -template -std::ostream &ArrayConstructor::AsFortran(std::ostream &o) const { - o << '[' << GetType().AsFortran() << "::"; - Emit(o, *this); - return o << ']'; -} - -template -std::ostream &ArrayConstructor>::AsFortran( - std::ostream &o) const { - std::stringstream len; - LEN().AsFortran(len); - o << '[' << GetType().AsFortran(len.str()) << "::"; - Emit(o, *this); - return o << ']'; -} - -std::ostream &ArrayConstructor::AsFortran(std::ostream &o) const { - o << '[' << GetType().AsFortran() << "::"; - Emit(o, *this); - return o << ']'; -} - -template -std::ostream &ExpressionBase::AsFortran(std::ostream &o) const { - std::visit( - common::visitors{ - [&](const BOZLiteralConstant &x) { - o << "z'" << x.Hexadecimal() << "'"; - }, - [&](const NullPointer &) { o << "NULL()"; }, - [&](const common::CopyableIndirection &s) { - s.value().AsFortran(o); - }, - [&](const ImpliedDoIndex &i) { o << i.name.ToString(); }, - [&](const auto &x) { x.AsFortran(o); }, - }, - derived().u); - return o; -} - template Expr Expr>::LEN() const { return std::visit( @@ -285,34 +153,6 @@ StructureConstructor &StructureConstructor::Add( return *this; } -std::ostream &StructureConstructor::AsFortran(std::ostream &o) const { - DerivedTypeSpecAsFortran(o, *derivedTypeSpec_); - if (values_.empty()) { - o << '('; - } else { - char ch{'('}; - for (const auto &[symbol, value] : values_) { - value.value().AsFortran(o << ch << symbol->name().ToString() << '='); - ch = ','; - } - } - return o << ')'; -} - -std::ostream &DerivedTypeSpecAsFortran( - std::ostream &o, const semantics::DerivedTypeSpec &spec) { - o << spec.typeSymbol().name().ToString(); - if (!spec.parameters().empty()) { - char ch{'('}; - for (const auto &[name, value] : spec.parameters()) { - value.GetExplicit()->AsFortran(o << ch << name.ToString() << '='); - ch = ','; - } - o << ')'; - } - return o; -} - GenericExprWrapper::~GenericExprWrapper() = default; bool GenericExprWrapper::operator==(const GenericExprWrapper &that) const { @@ -335,17 +175,6 @@ Expr Expr::LEN() const { return std::visit([](const auto &kx) { return kx.LEN(); }, u); } -// Template instantiations to resolve the "extern template" declarations -// that appear in expression.h. - -FOR_EACH_INTRINSIC_KIND(template class Expr) -FOR_EACH_CATEGORY_TYPE(template class Expr) -FOR_EACH_INTEGER_KIND(template struct Relational) -FOR_EACH_REAL_KIND(template struct Relational) -FOR_EACH_CHARACTER_KIND(template struct Relational) -template struct Relational; -FOR_EACH_TYPE_AND_KIND(template class ExpressionBase) -FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues) -FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor) +INSTANTIATE_EXPRESSION_TEMPLATES } DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper) diff --git a/flang/lib/evaluate/expression.h b/flang/lib/evaluate/expression.h index 002e04ddaf99..a803de082fcc 100644 --- a/flang/lib/evaluate/expression.h +++ b/flang/lib/evaluate/expression.h @@ -24,6 +24,7 @@ #include "common.h" #include "constant.h" +#include "formatting.h" #include "type.h" #include "variable.h" #include "../lib/common/Fortran.h" @@ -194,9 +195,9 @@ public: protected: // Overridable functions for AsFortran() - static std::ostream &Prefix(std::ostream &o) { return o << '('; } - static std::ostream &Infix(std::ostream &o) { return o << ','; } - static std::ostream &Suffix(std::ostream &o) { return o << ')'; } + static const char *Prefix() { return ""; } + static const char *Infix() { return ""; } + static const char *Suffix() { return ""; } private: Container operand_; @@ -239,7 +240,7 @@ template struct Negate : public Operation, A, A> { using Operand = A; using Base = Operation; using Base::Base; - static std::ostream &Prefix(std::ostream &o) { return o << "(-"; } + static const char *Prefix() { return "-"; } }; template @@ -255,9 +256,7 @@ struct ComplexComponent ComplexComponent(bool isImaginary, Expr &&x) : Base{std::move(x)}, isImaginaryPart{isImaginary} {} - std::ostream &Suffix(std::ostream &o) const { - return o << (isImaginaryPart ? "%IM)" : "%RE)"); - } + const char *Suffix() const { return isImaginaryPart ? "%IM)" : "%RE)"; } bool isImaginaryPart{true}; }; @@ -269,7 +268,7 @@ struct Not : public Operation, Type, using Operand = Result; using Base = Operation; using Base::Base; - static std::ostream &Prefix(std::ostream &o) { return o << "(.NOT."; } + static const char *Prefix() { return ".NOT."; } }; // Character lengths are determined by context in Fortran and do not @@ -285,7 +284,7 @@ struct SetLength using LengthOperand = SubscriptInteger; using Base = Operation; using Base::Base; - static std::ostream &Prefix(std::ostream &o) { return o << "%SET_LENGTH("; } + static const char *Prefix() { return "%SET_LENGTH("; } }; // Binary operations @@ -295,7 +294,7 @@ template struct Add : public Operation, A, A, A> { using Operand = A; using Base = Operation; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << '+'; } + static const char *Infix() { return "+"; } }; template struct Subtract : public Operation, A, A, A> { @@ -303,7 +302,7 @@ template struct Subtract : public Operation, A, A, A> { using Operand = A; using Base = Operation; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << '-'; } + static const char *Infix() { return "-"; } }; template struct Multiply : public Operation, A, A, A> { @@ -311,7 +310,7 @@ template struct Multiply : public Operation, A, A, A> { using Operand = A; using Base = Operation; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << '*'; } + static const char *Infix() { return "*"; } }; template struct Divide : public Operation, A, A, A> { @@ -319,7 +318,7 @@ template struct Divide : public Operation, A, A, A> { using Operand = A; using Base = Operation; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << '/'; } + static const char *Infix() { return "/"; } }; template struct Power : public Operation, A, A, A> { @@ -327,7 +326,7 @@ template struct Power : public Operation, A, A, A> { using Operand = A; using Base = Operation; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << "**"; } + static const char *Infix() { return "**"; } }; template @@ -337,7 +336,7 @@ struct RealToIntPower : public Operation, A, A, SomeInteger> { using BaseOperand = A; using ExponentOperand = SomeInteger; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << "**"; } + static const char *Infix() { return "**"; } }; template struct Extremum : public Operation, A, A, A> { @@ -352,8 +351,8 @@ template struct Extremum : public Operation, A, A, A> { Expr &&x, Expr &&y, Ordering ord = Ordering::Greater) : Base{std::move(x), std::move(y)}, ordering{ord} {} - std::ostream &Prefix(std::ostream &o) const { - return o << (ordering == Ordering::Less ? "MIN(" : "MAX("); + const char *Prefix() const { + return ordering == Ordering::Less ? "MIN(" : "MAX("; } Ordering ordering{Ordering::Greater}; @@ -379,7 +378,7 @@ struct Concat using Operand = Result; using Base = Operation; using Base::Base; - static std::ostream &Infix(std::ostream &o) { return o << "//"; } + static const char *Infix() { return "//"; } }; ENUM_CLASS(LogicalOperator, And, Or, Eqv, Neqv) @@ -398,7 +397,7 @@ struct LogicalOperation LogicalOperation(LogicalOperator opr, Expr &&x, Expr &&y) : Base{std::move(x), std::move(y)}, logicalOperator{opr} {} - std::ostream &Infix(std::ostream &) const; + const char *Infix() const; LogicalOperator logicalOperator; }; @@ -588,9 +587,9 @@ public: common::CombineVariants u; }; -FOR_EACH_INTEGER_KIND(extern template class Expr) -FOR_EACH_REAL_KIND(extern template class Expr) -FOR_EACH_COMPLEX_KIND(extern template class Expr) +FOR_EACH_INTEGER_KIND(extern template class Expr, ) +FOR_EACH_REAL_KIND(extern template class Expr, ) +FOR_EACH_COMPLEX_KIND(extern template class Expr, ) template class Expr> @@ -609,7 +608,7 @@ public: u; }; -FOR_EACH_CHARACTER_KIND(extern template class Expr) +FOR_EACH_CHARACTER_KIND(extern template class Expr, ) // The Relational class template is a helper for constructing logical // expressions with polymorphism over the cross product of the possible @@ -634,7 +633,7 @@ struct Relational : public Operation, LogicalResult, A, A> { Relational(RelationalOperator r, Expr &&a, Expr &&b) : Base{std::move(a), std::move(b)}, opr{r} {} - std::ostream &Infix(std::ostream &) const; + const char *Infix() const; RelationalOperator opr; }; @@ -655,9 +654,9 @@ public: common::MapTemplate u; }; -FOR_EACH_INTEGER_KIND(extern template struct Relational) -FOR_EACH_REAL_KIND(extern template struct Relational) -FOR_EACH_CHARACTER_KIND(extern template struct Relational) +FOR_EACH_INTEGER_KIND(extern template struct Relational, ) +FOR_EACH_REAL_KIND(extern template struct Relational, ) +FOR_EACH_CHARACTER_KIND(extern template struct Relational, ) extern template struct Relational; // Logical expressions of a kind bigger than LogicalResult @@ -686,7 +685,7 @@ public: u; }; -FOR_EACH_LOGICAL_KIND(extern template class Expr) +FOR_EACH_LOGICAL_KIND(extern template class Expr, ) // StructureConstructor pairs a StructureConstructorValues instance // (a map associating symbols with expressions) with a derived type @@ -823,9 +822,21 @@ struct GenericExprWrapper { std::ostream &DerivedTypeSpecAsFortran( std::ostream &, const semantics::DerivedTypeSpec &); -FOR_EACH_CATEGORY_TYPE(extern template class Expr) -FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase) -FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructorValues) -FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructor) +FOR_EACH_CATEGORY_TYPE(extern template class Expr, ) +FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, ) +FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructorValues, ) +FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructor, ) + +// Template instantiations to resolve these "extern template" declarations. +#define INSTANTIATE_EXPRESSION_TEMPLATES \ + FOR_EACH_INTRINSIC_KIND(template class Expr, ) \ + FOR_EACH_CATEGORY_TYPE(template class Expr, ) \ + FOR_EACH_INTEGER_KIND(template struct Relational, ) \ + FOR_EACH_REAL_KIND(template struct Relational, ) \ + FOR_EACH_CHARACTER_KIND(template struct Relational, ) \ + template struct Relational; \ + FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \ + FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \ + FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) } #endif // FORTRAN_EVALUATE_EXPRESSION_H_ diff --git a/flang/lib/evaluate/fold.cc b/flang/lib/evaluate/fold.cc index 9da28c96592f..927041599b55 100644 --- a/flang/lib/evaluate/fold.cc +++ b/flang/lib/evaluate/fold.cc @@ -1355,7 +1355,7 @@ Expr ExpressionBase::Rewrite(FoldingContext &context, Expr &&expr) { std::move(expr.u)); } -FOR_EACH_TYPE_AND_KIND(template class ExpressionBase) +FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) // Constant expression predicate IsConstantExpr(). // This code determines whether an expression is a "constant expression" diff --git a/flang/lib/evaluate/formatting.cc b/flang/lib/evaluate/formatting.cc new file mode 100644 index 000000000000..c638578e1d2e --- /dev/null +++ b/flang/lib/evaluate/formatting.cc @@ -0,0 +1,390 @@ +// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "formatting.h" +#include "call.h" +#include "constant.h" +#include "expression.h" +#include "../parser/characters.h" +#include "../semantics/symbol.h" + +namespace Fortran::evaluate { + +static void ShapeAsFortran( + std::ostream &o, const std::vector &shape) { + if (shape.size() > 1) { + o << ",shape="; + char ch{'['}; + for (auto dim : shape) { + o << ch << dim; + ch = ','; + } + o << "])"; + } +} + +template +std::ostream &ConstantBase::AsFortran(std::ostream &o) const { + if (Rank() > 1) { + o << "reshape("; + } + if (Rank() > 0) { + o << '[' << GetType().AsFortran() << "::"; + } + bool first{true}; + for (const auto &value : values_) { + if (first) { + first = false; + } else { + o << ','; + } + if constexpr (Result::category == TypeCategory::Integer) { + o << value.SignedDecimal() << '_' << Result::kind; + } else if constexpr (Result::category == TypeCategory::Real || + Result::category == TypeCategory::Complex) { + value.AsFortran(o, Result::kind); + } else if constexpr (Result::category == TypeCategory::Character) { + o << Result::kind << '_' << parser::QuoteCharacterLiteral(value); + } else if constexpr (Result::category == TypeCategory::Logical) { + if (value.IsTrue()) { + o << ".true."; + } else { + o << ".false."; + } + o << '_' << Result::kind; + } else { + StructureConstructor{AsConstant().derivedTypeSpec(), value}.AsFortran(o); + } + } + if (Rank() > 0) { + o << ']'; + } + ShapeAsFortran(o, shape_); + return o; +} + +template +std::ostream &Constant>::AsFortran( + std::ostream &o) const { + if (Rank() > 1) { + o << "reshape("; + } + if (Rank() > 0) { + o << '[' << GetType().AsFortran(std::to_string(length_)) << "::"; + } + auto total{static_cast(size())}; + for (std::int64_t j{0}; j < total; ++j) { + ScalarValue value{values_.substr(j * length_, length_)}; + if (j > 0) { + o << ','; + } else if (Rank() == 0) { + o << Result::kind << '_'; + } + o << parser::QuoteCharacterLiteral(value); + } + if (Rank() > 0) { + o << ']'; + } + ShapeAsFortran(o, shape_); + return o; +} + +std::ostream &ActualArgument::AsFortran(std::ostream &o) const { + if (keyword.has_value()) { + o << keyword->ToString() << '='; + } + if (isAlternateReturn) { + o << '*'; + } + return value().AsFortran(o); +} + +std::ostream &SpecificIntrinsic::AsFortran(std::ostream &o) const { + return o << name; +} + +std::ostream &ProcedureRef::AsFortran(std::ostream &o) const { + proc_.AsFortran(o); + char separator{'('}; + for (const auto &arg : arguments_) { + if (arg.has_value()) { + arg->AsFortran(o << separator); + separator = ','; + } + } + if (separator == '(') { + o << '('; + } + return o << ')'; +} + +// Operator precedence formatting; insert parentheses around operands +// only when necessary. + +enum class Precedence { + Primary, // don't parenthesize + Parenthesize, // (x), (real, imaginary) + DefinedUnary, + Negate, + Power, // ** which is right-associative + Multiplicative, // *, / + Additive, // +, -, // + Relational, + Logical, // .OR., .AND., .EQV., .NEQV. + NOT, // yes, this binds less tightly in Fortran than .OR./.AND./&c. do + DefinedBinary +}; + +template constexpr Precedence ToPrecedence{Precedence::Primary}; + +template +constexpr Precedence ToPrecedence>{Precedence::Parenthesize}; +template +constexpr Precedence ToPrecedence>{ + Precedence::Parenthesize}; +template +constexpr Precedence ToPrecedence>{Precedence::Negate}; +template +constexpr Precedence ToPrecedence>{Precedence::Power}; +template +constexpr Precedence ToPrecedence>{Precedence::Power}; +template +constexpr Precedence ToPrecedence>{Precedence::Multiplicative}; +template +constexpr Precedence ToPrecedence>{Precedence::Multiplicative}; +template +constexpr Precedence ToPrecedence>{Precedence::Additive}; +template +constexpr Precedence ToPrecedence>{Precedence::Additive}; +template +constexpr Precedence ToPrecedence>{Precedence::Additive}; +template +constexpr Precedence ToPrecedence>{Precedence::Relational}; +template +constexpr Precedence ToPrecedence>{Precedence::Logical}; +template +constexpr Precedence ToPrecedence>{Precedence::NOT}; + +template +static constexpr Precedence GetPrecedence(const Expr &expr) { + return std::visit( + [](const auto &x) { return ToPrecedence>; }, + expr.u); +} +template +static constexpr Precedence GetPrecedence(const Expr> &expr) { + return std::visit([](const auto &x) { return GetPrecedence(x); }, expr.u); +} +static constexpr Precedence GetPrecedence(const Expr &expr) { + return std::visit( + [](const auto &x) { return ToPrecedence>; }, + expr.u); +} +static constexpr Precedence GetPrecedence(const Expr &expr) { + return std::visit( + common::visitors{ + [](const BOZLiteralConstant &) { return Precedence::Primary; }, + [](const NullPointer &) { return Precedence::Primary; }, + [](const auto &x) { return GetPrecedence(x); }, + }, + expr.u); +} + +template +std::ostream &Operation::AsFortran(std::ostream &o) const { + static constexpr Precedence lhsPrec{ToPrecedence>}; + o << derived().Prefix(); + if constexpr (operands == 1) { + bool parens{lhsPrec != Precedence::Primary}; + if (parens) { + o << '('; + } + o << left(); + if (parens) { + o << ')'; + } + } else { + static constexpr Precedence thisPrec{ToPrecedence}; + bool lhsParens{lhsPrec == Precedence::Parenthesize || lhsPrec > thisPrec || + (lhsPrec == thisPrec && lhsPrec == Precedence::Power)}; + if (lhsParens) { + o << '('; + } + o << left(); + if (lhsParens) { + o << ')'; + } + static constexpr Precedence rhsPrec{ToPrecedence>}; + bool rhsParens{rhsPrec == Precedence::Parenthesize || rhsPrec > thisPrec}; + if (rhsParens) { + o << '('; + } + o << derived().Infix() << right(); + if (rhsParens) { + o << ')'; + } + } + return o << derived().Suffix(); +} + +template +std::ostream &Convert::AsFortran(std::ostream &o) const { + static_assert(TO::category == TypeCategory::Integer || + TO::category == TypeCategory::Real || + TO::category == TypeCategory::Character || + TO::category == TypeCategory::Logical || !"Convert<> to bad category!"); + if constexpr (TO::category == TypeCategory::Character) { + this->left().AsFortran(o << "achar(iachar(") << ')'; + } else if constexpr (TO::category == TypeCategory::Integer) { + this->left().AsFortran(o << "int("); + } else if constexpr (TO::category == TypeCategory::Real) { + this->left().AsFortran(o << "real("); + } else { + this->left().AsFortran(o << "logical("); + } + return o << ",kind=" << TO::kind << ')'; +} + +template const char *Relational::Infix() const { + switch (opr) { + case RelationalOperator::LT: return "<"; + case RelationalOperator::LE: return "<="; + case RelationalOperator::EQ: return "=="; + case RelationalOperator::NE: return "/="; + case RelationalOperator::GE: return ">="; + case RelationalOperator::GT: return ">"; + } + return nullptr; +} + +std::ostream &Relational::AsFortran(std::ostream &o) const { + std::visit([&](const auto &rel) { rel.AsFortran(o); }, u); + return o; +} + +template const char *LogicalOperation::Infix() const { + switch (logicalOperator) { + case LogicalOperator::And: return ".and."; + case LogicalOperator::Or: return ".or."; + case LogicalOperator::Eqv: return ".eqv."; + case LogicalOperator::Neqv: return ".neqv."; + } + return nullptr; +} + +template +std::ostream &Emit( + std::ostream &o, const common::CopyableIndirection> &expr) { + return expr.value().AsFortran(o); +} + +template +std::ostream &Emit(std::ostream &, const ArrayConstructorValues &); + +template +std::ostream &Emit(std::ostream &o, const ImpliedDo &implDo) { + o << '('; + Emit(o, implDo.values()); + o << ',' << ImpliedDoIndex::Result::AsFortran() + << "::" << implDo.name().ToString() << '='; + implDo.lower().AsFortran(o) << ','; + implDo.upper().AsFortran(o) << ','; + implDo.stride().AsFortran(o) << ')'; + return o; +} + +template +std::ostream &Emit(std::ostream &o, const ArrayConstructorValues &values) { + const char *sep{""}; + for (const auto &value : values.values()) { + o << sep; + std::visit([&](const auto &x) { Emit(o, x); }, value.u); + sep = ","; + } + return o; +} + +template +std::ostream &ArrayConstructor::AsFortran(std::ostream &o) const { + o << '[' << GetType().AsFortran() << "::"; + Emit(o, *this); + return o << ']'; +} + +template +std::ostream &ArrayConstructor>::AsFortran( + std::ostream &o) const { + std::stringstream len; + LEN().AsFortran(len); + o << '[' << GetType().AsFortran(len.str()) << "::"; + Emit(o, *this); + return o << ']'; +} + +std::ostream &ArrayConstructor::AsFortran(std::ostream &o) const { + o << '[' << GetType().AsFortran() << "::"; + Emit(o, *this); + return o << ']'; +} + +template +std::ostream &ExpressionBase::AsFortran(std::ostream &o) const { + std::visit( + common::visitors{ + [&](const BOZLiteralConstant &x) { + o << "z'" << x.Hexadecimal() << "'"; + }, + [&](const NullPointer &) { o << "NULL()"; }, + [&](const common::CopyableIndirection &s) { + s.value().AsFortran(o); + }, + [&](const ImpliedDoIndex &i) { o << i.name.ToString(); }, + [&](const auto &x) { x.AsFortran(o); }, + }, + derived().u); + return o; +} + +std::ostream &StructureConstructor::AsFortran(std::ostream &o) const { + DerivedTypeSpecAsFortran(o, *derivedTypeSpec_); + if (values_.empty()) { + o << '('; + } else { + char ch{'('}; + for (const auto &[symbol, value] : values_) { + value.value().AsFortran(o << ch << symbol->name().ToString() << '='); + ch = ','; + } + } + return o << ')'; +} + +std::ostream &DerivedTypeSpecAsFortran( + std::ostream &o, const semantics::DerivedTypeSpec &spec) { + o << spec.typeSymbol().name().ToString(); + if (!spec.parameters().empty()) { + char ch{'('}; + for (const auto &[name, value] : spec.parameters()) { + value.GetExplicit()->AsFortran(o << ch << name.ToString() << '='); + ch = ','; + } + o << ')'; + } + return o; +} + +INSTANTIATE_CONSTANT_TEMPLATES +INSTANTIATE_EXPRESSION_TEMPLATES +// TODO variable templates and call templates? +} diff --git a/flang/lib/evaluate/formatting.h b/flang/lib/evaluate/formatting.h new file mode 100644 index 000000000000..21dd0fe5fa54 --- /dev/null +++ b/flang/lib/evaluate/formatting.h @@ -0,0 +1,46 @@ +// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef FORTRAN_EVALUATE_FORMATTING_H_ +#define FORTRAN_EVALUATE_FORMATTING_H_ + +#include "../common/indirection.h" +#include +#include +#include + +namespace Fortran::evaluate { + +template +auto operator<<(std::ostream &o, const A &x) -> decltype(x.AsFortran(o)) { + return x.AsFortran(o); +} + +template +auto operator<<( + std::ostream &o, const Fortran::common::Indirection &x) + -> decltype(o << x.value()) { + return o << x.value(); +} + +template +auto operator<<(std::ostream &o, const std::optional &x) + -> decltype(o << *x) { + if (x.has_value()) { + o << *x; + } + return o; +} +} +#endif // FORTRAN_EVALUATE_FORMATTING_H_ diff --git a/flang/lib/evaluate/real.h b/flang/lib/evaluate/real.h index 27ece24617eb..591e69a46388 100644 --- a/flang/lib/evaluate/real.h +++ b/flang/lib/evaluate/real.h @@ -16,6 +16,7 @@ #define FORTRAN_EVALUATE_REAL_H_ #include "common.h" +#include "formatting.h" #include "integer.h" #include "rounding-bits.h" #include diff --git a/flang/lib/evaluate/static-data.h b/flang/lib/evaluate/static-data.h index 118bd3874337..6c8bf52aaf62 100644 --- a/flang/lib/evaluate/static-data.h +++ b/flang/lib/evaluate/static-data.h @@ -17,6 +17,7 @@ // Represents constant static data objects +#include "formatting.h" #include "type.h" #include "../common/idioms.h" #include diff --git a/flang/lib/evaluate/type.h b/flang/lib/evaluate/type.h index 1bdd3965e4e0..7d6fff03a743 100644 --- a/flang/lib/evaluate/type.h +++ b/flang/lib/evaluate/type.h @@ -24,6 +24,7 @@ #include "common.h" #include "complex.h" +#include "formatting.h" #include "integer.h" #include "logical.h" #include "real.h" @@ -317,58 +318,60 @@ template struct TypeOfHelper { template using TypeOf = typename TypeOfHelper::type; // For generating "[extern] template class", &c. boilerplate -#define EXPAND_FOR_EACH_INTEGER_KIND(M, P) \ - M(P, 1) M(P, 2) M(P, 4) M(P, 8) M(P, 16) -#define EXPAND_FOR_EACH_REAL_KIND(M, P) \ - M(P, 2) M(P, 3) M(P, 4) M(P, 8) M(P, 10) M(P, 16) -#define EXPAND_FOR_EACH_COMPLEX_KIND(M, P) EXPAND_FOR_EACH_REAL_KIND(M, P) -#define EXPAND_FOR_EACH_CHARACTER_KIND(M, P) M(P, 1) M(P, 2) M(P, 4) -#define EXPAND_FOR_EACH_LOGICAL_KIND(M, P) M(P, 1) M(P, 2) M(P, 4) M(P, 8) -#define TEMPLATE_INSTANTIATION(P, ARG) P; +#define EXPAND_FOR_EACH_INTEGER_KIND(M, P, S) \ + M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) M(P, S, 16) +#define EXPAND_FOR_EACH_REAL_KIND(M, P, S) \ + M(P, S, 2) M(P, S, 3) M(P, S, 4) M(P, S, 8) M(P, S, 10) M(P, S, 16) +#define EXPAND_FOR_EACH_COMPLEX_KIND(M, P, S) EXPAND_FOR_EACH_REAL_KIND(M, P, S) +#define EXPAND_FOR_EACH_CHARACTER_KIND(M, P, S) M(P, S, 1) M(P, S, 2) M(P, S, 4) +#define EXPAND_FOR_EACH_LOGICAL_KIND(M, P, S) \ + M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) +#define TEMPLATE_INSTANTIATION(P, S, ARG) P S; -#define FOR_EACH_INTEGER_KIND_HELP(PREFIX, K) \ - PREFIX>; -#define FOR_EACH_REAL_KIND_HELP(PREFIX, K) PREFIX>; -#define FOR_EACH_COMPLEX_KIND_HELP(PREFIX, K) \ - PREFIX>; -#define FOR_EACH_CHARACTER_KIND_HELP(PREFIX, K) \ - PREFIX>; -#define FOR_EACH_LOGICAL_KIND_HELP(PREFIX, K) \ - PREFIX>; +#define FOR_EACH_INTEGER_KIND_HELP(PREFIX, SUFFIX, K) \ + PREFIX> SUFFIX; +#define FOR_EACH_REAL_KIND_HELP(PREFIX, SUFFIX, K) \ + PREFIX> SUFFIX; +#define FOR_EACH_COMPLEX_KIND_HELP(PREFIX, SUFFIX, K) \ + PREFIX> SUFFIX; +#define FOR_EACH_CHARACTER_KIND_HELP(PREFIX, SUFFIX, K) \ + PREFIX> SUFFIX; +#define FOR_EACH_LOGICAL_KIND_HELP(PREFIX, SUFFIX, K) \ + PREFIX> SUFFIX; -#define FOR_EACH_INTEGER_KIND(PREFIX) \ - EXPAND_FOR_EACH_INTEGER_KIND(FOR_EACH_INTEGER_KIND_HELP, PREFIX) -#define FOR_EACH_REAL_KIND(PREFIX) \ - EXPAND_FOR_EACH_REAL_KIND(FOR_EACH_REAL_KIND_HELP, PREFIX) -#define FOR_EACH_COMPLEX_KIND(PREFIX) \ - EXPAND_FOR_EACH_COMPLEX_KIND(FOR_EACH_COMPLEX_KIND_HELP, PREFIX) -#define FOR_EACH_CHARACTER_KIND(PREFIX) \ - EXPAND_FOR_EACH_CHARACTER_KIND(FOR_EACH_CHARACTER_KIND_HELP, PREFIX) -#define FOR_EACH_LOGICAL_KIND(PREFIX) \ - EXPAND_FOR_EACH_LOGICAL_KIND(FOR_EACH_LOGICAL_KIND_HELP, PREFIX) +#define FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \ + EXPAND_FOR_EACH_INTEGER_KIND(FOR_EACH_INTEGER_KIND_HELP, PREFIX, SUFFIX) +#define FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \ + EXPAND_FOR_EACH_REAL_KIND(FOR_EACH_REAL_KIND_HELP, PREFIX, SUFFIX) +#define FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \ + EXPAND_FOR_EACH_COMPLEX_KIND(FOR_EACH_COMPLEX_KIND_HELP, PREFIX, SUFFIX) +#define FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX) \ + EXPAND_FOR_EACH_CHARACTER_KIND(FOR_EACH_CHARACTER_KIND_HELP, PREFIX, SUFFIX) +#define FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) \ + EXPAND_FOR_EACH_LOGICAL_KIND(FOR_EACH_LOGICAL_KIND_HELP, PREFIX, SUFFIX) -#define FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX) \ - FOR_EACH_INTEGER_KIND(PREFIX) \ - FOR_EACH_REAL_KIND(PREFIX) \ - FOR_EACH_COMPLEX_KIND(PREFIX) \ - FOR_EACH_LOGICAL_KIND(PREFIX) -#define FOR_EACH_INTRINSIC_KIND(PREFIX) \ - FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX) \ - FOR_EACH_CHARACTER_KIND(PREFIX) -#define FOR_EACH_SPECIFIC_TYPE(PREFIX) \ - FOR_EACH_INTRINSIC_KIND(PREFIX) \ - PREFIX; +#define FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \ + FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \ + FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \ + FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \ + FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) +#define FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \ + FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \ + FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX) +#define FOR_EACH_SPECIFIC_TYPE(PREFIX, SUFFIX) \ + FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \ + PREFIX SUFFIX; -#define FOR_EACH_CATEGORY_TYPE(PREFIX) \ - PREFIX; \ - PREFIX; \ - PREFIX; \ - PREFIX; \ - PREFIX; \ - PREFIX; \ - PREFIX; -#define FOR_EACH_TYPE_AND_KIND(PREFIX) \ - FOR_EACH_INTRINSIC_KIND(PREFIX) \ - FOR_EACH_CATEGORY_TYPE(PREFIX) +#define FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX) \ + PREFIX SUFFIX; \ + PREFIX SUFFIX; \ + PREFIX SUFFIX; \ + PREFIX SUFFIX; \ + PREFIX SUFFIX; \ + PREFIX SUFFIX; \ + PREFIX SUFFIX; +#define FOR_EACH_TYPE_AND_KIND(PREFIX, SUFFIX) \ + FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \ + FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX) } #endif // FORTRAN_EVALUATE_TYPE_H_ diff --git a/flang/lib/evaluate/variable.cc b/flang/lib/evaluate/variable.cc index ecdbbd37b63d..8fa75e93d5df 100644 --- a/flang/lib/evaluate/variable.cc +++ b/flang/lib/evaluate/variable.cc @@ -684,6 +684,6 @@ bool ProcedureRef::operator==(const ProcedureRef &that) const { } EXPAND_FOR_EACH_INTEGER_KIND( - TEMPLATE_INSTANTIATION, template class TypeParamInquiry) -FOR_EACH_SPECIFIC_TYPE(template class Designator) + TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) +FOR_EACH_SPECIFIC_TYPE(template class Designator, ) } diff --git a/flang/lib/evaluate/variable.h b/flang/lib/evaluate/variable.h index 28f3ac8f3ac1..8a946e8c0adf 100644 --- a/flang/lib/evaluate/variable.h +++ b/flang/lib/evaluate/variable.h @@ -23,6 +23,7 @@ #include "call.h" #include "common.h" +#include "formatting.h" #include "static-data.h" #include "type.h" #include "../common/idioms.h" @@ -129,7 +130,7 @@ private: }; EXPAND_FOR_EACH_INTEGER_KIND( - TEMPLATE_INSTANTIATION, extern template class TypeParamInquiry) + TEMPLATE_INSTANTIATION, extern template class TypeParamInquiry, ) // R921 subscript-triplet class Triplet { @@ -354,7 +355,7 @@ public: Variant u; }; -FOR_EACH_CHARACTER_KIND(extern template class Designator) +FOR_EACH_CHARACTER_KIND(extern template class Designator, ) template struct Variable { using Result = T; diff --git a/flang/lib/semantics/mod-file.cc b/flang/lib/semantics/mod-file.cc index ffa522a260a1..5901b9260b55 100644 --- a/flang/lib/semantics/mod-file.cc +++ b/flang/lib/semantics/mod-file.cc @@ -437,13 +437,13 @@ void PutTypeParam(std::ostream &os, const Symbol &symbol) { void PutInit(std::ostream &os, const MaybeExpr &init) { if (init) { - init->AsFortran(os << '='); + os << '=' << init; } } void PutInit(std::ostream &os, const MaybeIntExpr &init) { if (init) { - init->AsFortran(os << '='); + os << '=' << init; } } @@ -453,7 +453,7 @@ void PutBound(std::ostream &os, const Bound &x) { } else if (x.isDeferred()) { os << ':'; } else { - x.GetExplicit()->AsFortran(os); + os << x.GetExplicit(); } } @@ -482,7 +482,7 @@ std::ostream &PutAttrs(std::ostream &os, Attrs attrs, const MaybeExpr &bindName, attrs.set(Attr::PUBLIC, false); // no need to write PUBLIC attrs.set(Attr::EXTERNAL, false); // no need to write EXTERNAL if (bindName) { - bindName->AsFortran(os << before << "bind(c, name=") << ')' << after; + os << before << "bind(c, name=" << bindName << ')' << after; attrs.set(Attr::BIND_C, false); } for (std::size_t i{0}; i < Attr_enumSize; ++i) { diff --git a/flang/lib/semantics/symbol.cc b/flang/lib/semantics/symbol.cc index 16c57b5ffa20..34189b27a4e4 100644 --- a/flang/lib/semantics/symbol.cc +++ b/flang/lib/semantics/symbol.cc @@ -53,7 +53,7 @@ std::ostream &operator<<(std::ostream &os, const SubprogramDetails &x) { os << " isInterface"; } if (x.bindName_) { - x.bindName_->AsFortran(os << " bindName:"); + os << " bindName:" << x.bindName_; } if (x.result_) { os << " result:" << x.result_.value()->name(); @@ -275,7 +275,7 @@ std::ostream &operator<<(std::ostream &os, const EntityDetails &x) { os << " type: " << *x.type(); } if (x.bindName_) { - x.bindName_->AsFortran(os << " bindName:"); + os << " bindName:" << x.bindName_; } return os; } @@ -289,7 +289,7 @@ std::ostream &operator<<(std::ostream &os, const ObjectEntityDetails &x) { } } if (x.init_) { - x.init_->AsFortran(os << " init:"); + os << " init:" << x.init_; } return os; } @@ -297,7 +297,7 @@ std::ostream &operator<<(std::ostream &os, const ObjectEntityDetails &x) { std::ostream &operator<<(std::ostream &os, const AssocEntityDetails &x) { os << *static_cast(&x); if (x.expr().has_value()) { - x.expr()->AsFortran(os << ' '); + os << ' ' << x.expr(); } return os; } @@ -309,7 +309,7 @@ std::ostream &operator<<(std::ostream &os, const ProcEntityDetails &x) { os << ' ' << *type; } if (x.bindName()) { - x.bindName()->AsFortran(os << " bindName:"); + os << " bindName:" << x.bindName(); } if (x.passName_) { os << " passName:" << *x.passName_; @@ -369,7 +369,7 @@ std::ostream &operator<<(std::ostream &os, const Details &details) { } os << ')'; if (x.bindName()) { - x.bindName()->AsFortran(os << " bindName:"); + os << " bindName:" << x.bindName(); } if (x.isFunction()) { os << " result("; @@ -432,7 +432,7 @@ std::ostream &operator<<(std::ostream &os, const Details &details) { } os << ' ' << common::EnumToString(x.attr()); if (x.init()) { - x.init()->AsFortran(os << " init:"); + os << " init:" << x.init(); } }, [&](const MiscDetails &x) { diff --git a/flang/lib/semantics/type.cc b/flang/lib/semantics/type.cc index 808674b903fb..826fcb2645cc 100644 --- a/flang/lib/semantics/type.cc +++ b/flang/lib/semantics/type.cc @@ -101,7 +101,7 @@ void DerivedTypeSpec::Instantiate( maybeDynamicType->category == TypeCategory::Integer && !evaluate::ToInt64(expr).has_value()) { std::stringstream fortran; - expr->AsFortran(fortran); + fortran << expr; if (auto *msg{foldingContext.messages().Say( "Value of kind type parameter '%s' (%s) is not " "scalar INTEGER constant"_err_en_US, @@ -168,7 +168,7 @@ std::ostream &operator<<(std::ostream &o, const Bound &x) { } else if (x.isDeferred()) { o << ':'; } else if (x.expr_) { - x.expr_->AsFortran(o); + o << x.expr_; } else { o << ""; } @@ -231,7 +231,7 @@ std::ostream &operator<<(std::ostream &o, const ParamValue &x) { } else if (!x.GetExplicit()) { o << ""; } else { - x.GetExplicit()->AsFortran(o); + o << x.GetExplicit(); } return o; } @@ -246,7 +246,7 @@ std::ostream &operator<<(std::ostream &os, const IntrinsicTypeSpec &x) { if (auto k{evaluate::ToInt64(x.kind())}) { return os << '(' << *k << ')'; // emit unsuffixed kind code } else { - return x.kind().AsFortran(os << '(') << ')'; + return os << '(' << x.kind() << ')'; } } @@ -255,7 +255,7 @@ std::ostream &operator<<(std::ostream &os, const CharacterTypeSpec &x) { if (auto k{evaluate::ToInt64(x.kind())}) { return os << *k << ')'; // emit unsuffixed kind code } else { - return x.kind().AsFortran(os) << ')'; + return os << x.kind() << ')'; } }