[flang] Pass tests

Original-commit: flang-compiler/f18@ffb057f262
Reviewed-on: https://github.com/flang-compiler/f18/pull/371
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-04-01 12:30:08 -07:00
parent b35f4a98e2
commit 9e9b9f0776
9 changed files with 98 additions and 91 deletions

View File

@ -30,7 +30,7 @@ Addressable_impl *GetAddressable(Statement *stmt) {
static std::string dump(const Expression &e) { static std::string dump(const Expression &e) {
std::stringstream stringStream; std::stringstream stringStream;
stringStream << e.v; stringStream << e;
return stringStream.str(); return stringStream.str();
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. // Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -133,50 +133,52 @@ std::ostream &ProcedureRef::AsFortran(std::ostream &o) const {
// Operator precedence formatting; insert parentheses around operands // Operator precedence formatting; insert parentheses around operands
// only when necessary. // only when necessary.
enum class Precedence { enum class Precedence { // in increasing order of precedence
Primary, // don't parenthesize DefinedBinary,
Constant, // parenthesize if negative integer/real operand NOT, // which binds *less* tightly in Fortran than logicals & relations
Parenthesize, // (x), (real, imaginary)
DefinedUnary,
Negate,
Power, // ** which is right-associative
Multiplicative, // *, /
Additive, // +, -, //
Relational,
Logical, // .OR., .AND., .EQV., .NEQV. Logical, // .OR., .AND., .EQV., .NEQV.
NOT, // yes, this binds less tightly in Fortran than .OR./.AND./&c. do Relational,
DefinedBinary Additive, // +, -, //
Multiplicative, // *, /
Power, // **, which is right-associative unlike the other dyadic operators
Negate,
DefinedUnary,
Parenthesize, // (x), (real, imaginary)
Constant, // parenthesize if negative integer/real operand
Primary, // don't parenthesize
}; };
template<typename A> constexpr Precedence ToPrecedence{Precedence::Primary}; template<typename A> constexpr Precedence ToPrecedence{Precedence::Primary};
template<typename T> constexpr Precedence ToPrecedence<Constant<T>>{Precedence::Constant};
template<int KIND>
constexpr Precedence ToPrecedence<Not<KIND>>{Precedence::NOT};
template<int KIND>
constexpr Precedence ToPrecedence<LogicalOperation<KIND>>{Precedence::Logical};
template<typename T>
constexpr Precedence ToPrecedence<Relational<T>>{Precedence::Relational};
template<int KIND>
constexpr Precedence ToPrecedence<Concat<KIND>>{Precedence::Additive};
template<typename T>
constexpr Precedence ToPrecedence<Subtract<T>>{Precedence::Additive};
template<typename T>
constexpr Precedence ToPrecedence<Add<T>>{Precedence::Additive};
template<typename T>
constexpr Precedence ToPrecedence<Divide<T>>{Precedence::Multiplicative};
template<typename T>
constexpr Precedence ToPrecedence<Multiply<T>>{Precedence::Multiplicative};
template<typename T>
constexpr Precedence ToPrecedence<RealToIntPower<T>>{Precedence::Power};
template<typename T>
constexpr Precedence ToPrecedence<Power<T>>{Precedence::Power};
template<typename T>
constexpr Precedence ToPrecedence<Negate<T>>{Precedence::Negate};
template<typename T>
constexpr Precedence ToPrecedence<Constant<T>>{Precedence::Constant};
template<typename T> template<typename T>
constexpr Precedence ToPrecedence<Parentheses<T>>{Precedence::Parenthesize}; constexpr Precedence ToPrecedence<Parentheses<T>>{Precedence::Parenthesize};
template<int KIND> template<int KIND>
constexpr Precedence ToPrecedence<ComplexConstructor<KIND>>{ constexpr Precedence ToPrecedence<ComplexConstructor<KIND>>{
Precedence::Parenthesize}; Precedence::Parenthesize};
template<typename T>
constexpr Precedence ToPrecedence<Negate<T>>{Precedence::Negate};
template<typename T>
constexpr Precedence ToPrecedence<Power<T>>{Precedence::Power};
template<typename T>
constexpr Precedence ToPrecedence<RealToIntPower<T>>{Precedence::Power};
template<typename T>
constexpr Precedence ToPrecedence<Multiply<T>>{Precedence::Multiplicative};
template<typename T>
constexpr Precedence ToPrecedence<Divide<T>>{Precedence::Multiplicative};
template<typename T>
constexpr Precedence ToPrecedence<Add<T>>{Precedence::Additive};
template<typename T>
constexpr Precedence ToPrecedence<Subtract<T>>{Precedence::Additive};
template<int KIND>
constexpr Precedence ToPrecedence<Concat<KIND>>{Precedence::Additive};
template<typename T>
constexpr Precedence ToPrecedence<Relational<T>>{Precedence::Relational};
template<int KIND>
constexpr Precedence ToPrecedence<LogicalOperation<KIND>>{Precedence::Logical};
template<int KIND>
constexpr Precedence ToPrecedence<Not<KIND>>{Precedence::NOT};
template<typename T> template<typename T>
static constexpr Precedence GetPrecedence(const Expr<T> &expr) { static constexpr Precedence GetPrecedence(const Expr<T> &expr) {
@ -203,55 +205,45 @@ static constexpr Precedence GetPrecedence(const Expr<SomeType> &expr) {
expr.u); expr.u);
} }
template<typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
static constexpr TypeCategory cat{T::category};
if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) {
if (expr.Rank() == 0) {
if (const auto *p{UnwrapExpr<Constant<T>>(expr)}) {
CHECK(p->size() == 1);
return (**p).IsNegative();
}
}
}
return false;
}
template<TypeCategory CAT>
static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
return std::visit(
[](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u);
}
template<typename D, typename R, typename... O> template<typename D, typename R, typename... O>
std::ostream &Operation<D, R, O...>::AsFortran(std::ostream &o) const { std::ostream &Operation<D, R, O...>::AsFortran(std::ostream &o) const {
static constexpr Precedence lhsPrec{ToPrecedence<Operand<0>>}; Precedence lhsPrec{GetPrecedence(left())};
o << derived().Prefix(); o << derived().Prefix();
if constexpr (operands == 1) { if constexpr (operands == 1) {
bool parens{lhsPrec != Precedence::Primary}; bool parens{lhsPrec < Precedence::Constant};
if (parens) { o << (parens ? "(" : "") << left() << (parens ? ")" : "");
o << '(';
}
o << left();
if (parens) {
o << ')';
}
} else { } else {
static constexpr Precedence thisPrec{ToPrecedence<D>}; static constexpr Precedence thisPrec{ToPrecedence<D>};
bool lhsParens{lhsPrec == Precedence::Parenthesize || lhsPrec > thisPrec || bool lhsParens{lhsPrec == Precedence::Parenthesize || lhsPrec < thisPrec ||
(lhsPrec == thisPrec && lhsPrec == Precedence::Power)}; (lhsPrec == thisPrec && lhsPrec == Precedence::Power) ||
if constexpr (lhsPrec == Precedence::Constant && thisPrec != Precedence::Additive) { (thisPrec != Precedence::Additive && lhsPrec == Precedence::Constant &&
static constexpr TypeCategory cat{Operand<0>::Result::category}; IsNegatedScalarConstant(left()))};
if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { o << (lhsParens ? "(" : "") << left() << (lhsParens ? ")" : "");
const auto *p{UnwrapExpr<Constant<Operand<0>>>(left())}; o << derived().Infix();
CHECK(p != nullptr); Precedence rhsPrec{GetPrecedence(right())};
lhsParens |= p->size() == 1 && (*p)->IsNegative(); bool rhsParens{rhsPrec == Precedence::Parenthesize ||
} rhsPrec == Precedence::Negate || rhsPrec < thisPrec ||
} (rhsPrec == Precedence::Constant && IsNegatedScalarConstant(right()))};
if (lhsParens) { o << (rhsParens ? "(" : "") << right() << (rhsParens ? ")" : "");
o << '(';
}
o << left();
if (lhsParens) {
o << ')';
}
static constexpr Precedence rhsPrec{ToPrecedence<Operand<1>>};
bool rhsParens{rhsPrec == Precedence::Parenthesize || rhsPrec == Precedence::Negate || rhsPrec > thisPrec};
if constexpr (rhsPrec == Precedence::Constant) {
static constexpr TypeCategory cat{Operand<1>::Result::category};
if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) {
const auto *p{UnwrapExpr<Constant<Operand<1>>>(right())};
CHECK(p != nullptr);
rhsParens |= p->size() == 1 && (*p)->IsNegative();
}
}
if (rhsParens) {
o << '(';
}
o << derived().Infix() << right();
if (rhsParens) {
o << ')';
}
} }
return o << derived().Suffix(); return o << derived().Suffix();
} }
@ -323,7 +315,8 @@ std::ostream &EmitArray(std::ostream &o, const ImpliedDo<T> &implDo) {
} }
template<typename T> template<typename T>
std::ostream &EmitArray(std::ostream &o, const ArrayConstructorValues<T> &values) { std::ostream &EmitArray(
std::ostream &o, const ArrayConstructorValues<T> &values) {
const char *sep{""}; const char *sep{""};
for (const auto &value : values.values()) { for (const auto &value : values.values()) {
o << sep; o << sep;
@ -498,7 +491,9 @@ std::ostream &Triplet::AsFortran(std::ostream &o) const {
return o; return o;
} }
std::ostream &Subscript::AsFortran(std::ostream &o) const { return EmitVar(o, u); } std::ostream &Subscript::AsFortran(std::ostream &o) const {
return EmitVar(o, u);
}
std::ostream &ArrayRef::AsFortran(std::ostream &o) const { std::ostream &ArrayRef::AsFortran(std::ostream &o) const {
EmitVar(o, base_); EmitVar(o, base_);
@ -532,12 +527,15 @@ std::ostream &CoarrayRef::AsFortran(std::ostream &o) const {
separator = ','; separator = ',';
} }
if (team_.has_value()) { if (team_.has_value()) {
EmitVar(o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM="); EmitVar(
o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM=");
} }
return o << ']'; return o << ']';
} }
std::ostream &DataRef::AsFortran(std::ostream &o) const { return EmitVar(o, u); } std::ostream &DataRef::AsFortran(std::ostream &o) const {
return EmitVar(o, u);
}
std::ostream &Substring::AsFortran(std::ostream &o) const { std::ostream &Substring::AsFortran(std::ostream &o) const {
EmitVar(o, parent_) << '('; EmitVar(o, parent_) << '(';

View File

@ -15,6 +15,15 @@
#ifndef FORTRAN_EVALUATE_FORMATTING_H_ #ifndef FORTRAN_EVALUATE_FORMATTING_H_
#define FORTRAN_EVALUATE_FORMATTING_H_ #define FORTRAN_EVALUATE_FORMATTING_H_
// It is inconvenient in C++ to have std::ostream::operator<<() as a direct
// friend function of a class template with many instantiations, so the
// various representational class templates in lib/evaluate format themselves
// via AsFortran(std::ostream &) member functions, which the operator<<()
// overload below will call.
//
// This header is meant to be included by the headers that define the several
// representational class templates that need it, not by external clients.
#include "../common/indirection.h" #include "../common/indirection.h"
#include <optional> #include <optional>
#include <ostream> #include <ostream>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. // Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. // Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1951,7 +1951,7 @@ void ExprChecker::Enter(const parser::Expr &expr) {
if (!expr.typedExpr) { if (!expr.typedExpr) {
if (MaybeExpr checked{AnalyzeExpr(context_, expr)}) { if (MaybeExpr checked{AnalyzeExpr(context_, expr)}) {
#if PMKDEBUG #if PMKDEBUG
// checked->AsFortran(std::cout << "checked expression: ") << '\n'; // std::cout << "checked expression: " << *checked << '\n';
#endif #endif
expr.typedExpr.reset( expr.typedExpr.reset(
new evaluate::GenericExprWrapper{std::move(*checked)}); new evaluate::GenericExprWrapper{std::move(*checked)});
@ -1967,7 +1967,7 @@ void ExprChecker::Enter(const parser::Expr &expr) {
void ExprChecker::Enter(const parser::Variable &var) { void ExprChecker::Enter(const parser::Variable &var) {
#if PMKDEBUG #if PMKDEBUG
if (MaybeExpr checked{AnalyzeExpr(context_, var)}) { if (MaybeExpr checked{AnalyzeExpr(context_, var)}) {
// checked->AsFortran(std::cout << "checked variable: ") << '\n'; // std::cout << "checked variable: " << *checked << '\n';
#else #else
if (AnalyzeExpr(context_, var)) { if (AnalyzeExpr(context_, var)) {
#endif #endif

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. // Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -37,7 +37,7 @@ int main() {
MATCH("-1_4", AsFortran(-DefaultIntegerExpr{1})); MATCH("-1_4", AsFortran(-DefaultIntegerExpr{1}));
auto ex1{ auto ex1{
DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}}; DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}};
MATCH("2_4+3_4*(-4_4))", AsFortran(ex1)); MATCH("2_4+3_4*(-4_4)", AsFortran(ex1));
Fortran::parser::CharBlock src; Fortran::parser::CharBlock src;
Fortran::parser::ContextualMessages messages{src, nullptr}; Fortran::parser::ContextualMessages messages{src, nullptr};
FoldingContext context{messages}; FoldingContext context{messages};

View File

@ -1,4 +1,4 @@
! Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. ! Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
! !
! Licensed under the Apache License, Version 2.0 (the "License"); ! Licensed under the Apache License, Version 2.0 (the "License");
! you may not use this file except in compliance with the License. ! you may not use this file except in compliance with the License.