[flang] merge with master

Original-commit: flang-compiler/f18@53f15da06a
Reviewed-on: https://github.com/flang-compiler/f18/pull/219
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-10-23 17:05:24 -07:00
parent d6ea6af7c4
commit f50047f45c
3 changed files with 119 additions and 88 deletions

View File

@ -43,81 +43,98 @@ template<typename A> Expr<ResultType<A>> Fold(FoldingContext &, A &&x) {
template<typename A> Expr<A> Fold(FoldingContext &context, Expr<A> &&expr) {
static_assert(A::isSpecificIntrinsicType);
return std::visit([&](auto &&x) -> Expr<A> { return Fold(context, std::move(x)); }, std::move(expr.u));
return std::visit(
[&](auto &&x) -> Expr<A> { return Fold(context, std::move(x)); },
std::move(expr.u));
}
template<TypeCategory CAT>
Expr<SomeKind<CAT>>
Fold(FoldingContext &context, Expr<SomeKind<CAT>> &&expr) {
return std::visit([&](auto &&x) -> Expr<SomeKind<CAT>> {
if constexpr (CAT == TypeCategory::Derived) {
return Fold(context, std::move(x));
} else {
return Expr<SomeKind<CAT>>{Fold(context, std::move(x))};
}
}, std::move(expr.u));
Expr<SomeKind<CAT>> Fold(FoldingContext &context, Expr<SomeKind<CAT>> &&expr) {
return std::visit(
[&](auto &&x) -> Expr<SomeKind<CAT>> {
if constexpr (CAT == TypeCategory::Derived) {
return Fold(context, std::move(x));
} else {
return Expr<SomeKind<CAT>>{Fold(context, std::move(x))};
}
},
std::move(expr.u));
}
template<> inline Expr<SomeType> Fold(FoldingContext &context, Expr<SomeType> &&expr) {
return std::visit([&](auto &&x) -> Expr<SomeType> {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, BOZLiteralConstant>) {
return std::move(expr);
} else {
return Expr<SomeType>{Fold(context, std::move(x))};
}
}, std::move(expr.u));
template<>
inline Expr<SomeType> Fold(FoldingContext &context, Expr<SomeType> &&expr) {
return std::visit(
[&](auto &&x) -> Expr<SomeType> {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>,
BOZLiteralConstant>) {
return std::move(expr);
} else {
return Expr<SomeType>{Fold(context, std::move(x))};
}
},
std::move(expr.u));
}
// Unary operations
template<typename TO, TypeCategory FROMCAT> Expr<TO> Fold(FoldingContext &context, Convert<TO, FROMCAT> &&convert) {
return std::visit([&](auto &kindExpr) -> Expr<TO> {
kindExpr = Fold(context, std::move(kindExpr));
using Operand = ResultType<decltype(kindExpr)>;
if (const auto *c{std::get_if<Constant<Operand>>(&kindExpr.u)}) {
if constexpr (TO::category == TypeCategory::Integer) {
if constexpr (Operand::category == TypeCategory::Integer) {
auto converted{Scalar<TO>::ConvertSigned(c->value)};
if (converted.overflow) {
context.messages.Say("INTEGER(%d) to INTEGER(%d) conversion overflowed"_en_US, Operand::kind, TO::kind);
template<typename TO, TypeCategory FROMCAT>
Expr<TO> Fold(FoldingContext &context, Convert<TO, FROMCAT> &&convert) {
return std::visit(
[&](auto &kindExpr) -> Expr<TO> {
kindExpr = Fold(context, std::move(kindExpr));
using Operand = ResultType<decltype(kindExpr)>;
if (const auto *c{std::get_if<Constant<Operand>>(&kindExpr.u)}) {
if constexpr (TO::category == TypeCategory::Integer) {
if constexpr (Operand::category == TypeCategory::Integer) {
auto converted{Scalar<TO>::ConvertSigned(c->value)};
if (converted.overflow) {
context.messages.Say(
"INTEGER(%d) to INTEGER(%d) conversion overflowed"_en_US,
Operand::kind, TO::kind);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
} else if constexpr (Operand::category == TypeCategory::Real) {
auto converted{c->value.template ToInteger<Scalar<TO>>()};
if (converted.flags.test(RealFlag::InvalidArgument)) {
context.messages.Say(
"REAL(%d) to INTEGER(%d) conversion: invalid argument"_en_US,
Operand::kind, TO::kind);
} else if (converted.flags.test(RealFlag::Overflow)) {
context.messages.Say(
"REAL(%d) to INTEGER(%d) conversion overflowed"_en_US,
Operand::kind, TO::kind);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
}
} else if constexpr (TO::category == TypeCategory::Real) {
if constexpr (Operand::category == TypeCategory::Integer) {
auto converted{Scalar<TO>::FromInteger(c->value)};
if (!converted.flags.empty()) {
char buffer[64];
std::snprintf(buffer, sizeof buffer,
"INTEGER(%d) to REAL(%d) conversion", Operand::kind,
TO::kind);
RealFlagWarnings(context, converted.flags, buffer);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
} else if constexpr (Operand::category == TypeCategory::Real) {
auto converted{Scalar<TO>::Convert(c->value)};
if (!converted.flags.empty()) {
char buffer[64];
std::snprintf(buffer, sizeof buffer,
"REAL(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
RealFlagWarnings(context, converted.flags, buffer);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
}
} else if constexpr (TO::category == TypeCategory::Logical &&
Operand::category == TypeCategory::Logical) {
return Expr<TO>{Constant<TO>{c->value.IsTrue()}};
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
} else if constexpr (Operand::category == TypeCategory::Real) {
auto converted{c->value.template ToInteger<Scalar<TO>>()};
if (converted.flags.test(RealFlag::InvalidArgument)) {
context.messages.Say(
"REAL(%d) to INTEGER(%d) conversion: invalid argument"_en_US, Operand::kind, TO::kind);
} else if (converted.flags.test(RealFlag::Overflow)) {
context.messages.Say(
"REAL(%d) to INTEGER(%d) conversion overflowed"_en_US, Operand::kind, TO::kind);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
}
} else if constexpr (TO::category == TypeCategory::Real) {
if constexpr (Operand::category == TypeCategory::Integer) {
auto converted{Scalar<TO>::FromInteger(c->value)};
if (!converted.flags.empty()) {
char buffer[64];
std::snprintf(buffer, sizeof buffer, "INTEGER(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
RealFlagWarnings(context, converted.flags, buffer);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
} else if constexpr (Operand::category == TypeCategory::Real) {
auto converted{Scalar<TO>::Convert(c->value)};
if (!converted.flags.empty()) {
char buffer[64];
std::snprintf(buffer, sizeof buffer, "REAL(%d) to REAL(%d) conversion", Operand::kind, TO::kind);
RealFlagWarnings(context, converted.flags, buffer);
}
return Expr<TO>{Constant<TO>{std::move(converted.value)}};
}
} else if constexpr (TO::category == TypeCategory::Logical &&
Operand::category == TypeCategory::Logical) {
return Expr<TO>{Constant<TO>{c->value.IsTrue()}};
}
}
return Expr<TO>{std::move(convert)};
}, convert.left().u);
return Expr<TO>{std::move(convert)};
},
convert.left().u);
}
template<typename T> Expr<T> Fold(FoldingContext &context, Negate<T> &&x) {
@ -131,13 +148,17 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Negate<T> &&x) {
}
return Expr<T>{Constant<T>{std::move(negated.value)}};
} else {
return Expr<T>{Constant<T>{c->value.Negate()}}; // REAL & COMPLEX negation: no exceptions possible
return Expr<T>{Constant<T>{
c->value
.Negate()}}; // REAL & COMPLEX negation: no exceptions possible
}
}
return Expr<T>{std::move(x)};
}
template<int KIND> Expr<Type<TypeCategory::Real, KIND>> Fold(FoldingContext &context, ComplexComponent<KIND> &&x) {
template<int KIND>
Expr<Type<TypeCategory::Real, KIND>> Fold(
FoldingContext &context, ComplexComponent<KIND> &&x) {
using Operand = Type<TypeCategory::Complex, KIND>;
using Part = Type<TypeCategory::Real, KIND>;
auto &operand{x.left()};
@ -152,7 +173,9 @@ template<int KIND> Expr<Type<TypeCategory::Real, KIND>> Fold(FoldingContext &con
return Expr<Part>{std::move(x)};
}
template<int KIND> Expr<Type<TypeCategory::Logical, KIND>> Fold(FoldingContext &context, Not<KIND> &&x) {
template<int KIND>
Expr<Type<TypeCategory::Logical, KIND>> Fold(
FoldingContext &context, Not<KIND> &&x) {
using Ty = Type<TypeCategory::Logical, KIND>;
auto &operand{x.left()};
operand = Fold(context, std::move(operand));
@ -164,8 +187,9 @@ template<int KIND> Expr<Type<TypeCategory::Logical, KIND>> Fold(FoldingContext &
// Binary (dyadic) operations
template<typename T1, typename T2> std::optional<std::pair<Scalar<T1>, Scalar<T2>>>
FoldOperands(FoldingContext &context, Expr<T1> &x, Expr<T2> &y) {
template<typename T1, typename T2>
std::optional<std::pair<Scalar<T1>, Scalar<T2>>> FoldOperands(
FoldingContext &context, Expr<T1> &x, Expr<T2> &y) {
x = Fold(context, std::move(x));
y = Fold(context, std::move(y));
if (const auto *xc{std::get_if<Constant<T1>>(&x.u)}) {
@ -198,7 +222,8 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Subtract<T> &&x) {
if constexpr (T::category == TypeCategory::Integer) {
auto difference{folded->first.SubtractSigned(folded->second)};
if (difference.overflow) {
context.messages.Say("INTEGER(%d) subtraction overflowed"_en_US, T::kind);
context.messages.Say(
"INTEGER(%d) subtraction overflowed"_en_US, T::kind);
}
return Expr<T>{Constant<T>{difference.value}};
} else {
@ -215,7 +240,8 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Multiply<T> &&x) {
if constexpr (T::category == TypeCategory::Integer) {
auto product{folded->first.MultiplySigned(folded->second)};
if (product.SignedMultiplicationOverflowed()) {
context.messages.Say("INTEGER(%d) multiplication overflowed"_en_US, T::kind);
context.messages.Say(
"INTEGER(%d) multiplication overflowed"_en_US, T::kind);
}
return Expr<T>{Constant<T>{product.lower}};
} else {
@ -252,7 +278,8 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Power<T> &&x) {
if constexpr (T::category == TypeCategory::Integer) {
auto power{folded->first.Power(folded->second)};
if (power.divisionByZero) {
context.messages.Say("INTEGER(%d) zero to negative power"_en_US, T::kind);
context.messages.Say(
"INTEGER(%d) zero to negative power"_en_US, T::kind);
} else if (power.overflow) {
context.messages.Say("INTEGER(%d) power overflowed"_en_US, T::kind);
} else if (power.zeroToZero) {
@ -266,16 +293,19 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Power<T> &&x) {
return Expr<T>{std::move(x)};
}
template<typename T> Expr<T> Fold(FoldingContext &context, RealToIntPower<T> &&x) {
return std::visit([&](auto &y) -> Expr<T> {
if (auto folded{FoldOperands(context, x.left(), y)}) {
auto power{evaluate::IntPower(folded->first, folded->second)};
RealFlagWarnings(context, power.flags, "power with INTEGER exponent");
return Expr<T>{Constant<T>{power.value}};
} else {
return Expr<T>{std::move(x)};
}
}, x.right().u);
template<typename T>
Expr<T> Fold(FoldingContext &context, RealToIntPower<T> &&x) {
return std::visit(
[&](auto &y) -> Expr<T> {
if (auto folded{FoldOperands(context, x.left(), y)}) {
auto power{evaluate::IntPower(folded->first, folded->second)};
RealFlagWarnings(context, power.flags, "power with INTEGER exponent");
return Expr<T>{Constant<T>{power.value}};
} else {
return Expr<T>{std::move(x)};
}
},
x.right().u);
}
template<typename T> Expr<T> Fold(FoldingContext &context, Extremum<T> &&x) {
@ -285,7 +315,9 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Extremum<T> &&x) {
return Expr<T>{Constant<T>{folded->first}};
}
} else if constexpr (T::category == TypeCategory::Real) {
if (folded->first.IsNotANumber() || (folded->first.Compare(folded->second) == Relation::Less) == (x.ordering == Ordering::Less)) {
if (folded->first.IsNotANumber() ||
(folded->first.Compare(folded->second) == Relation::Less) ==
(x.ordering == Ordering::Less)) {
return Expr<T>{Constant<T>{folded->first}};
}
} else {
@ -298,5 +330,5 @@ template<typename T> Expr<T> Fold(FoldingContext &context, Extremum<T> &&x) {
return Expr<T>{std::move(x)};
}
}
} // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_FOLD_H_

View File

@ -111,7 +111,7 @@ struct CallAndArguments {
// member function that converts parse trees into (usually) generic
// expressions.
struct ExprAnalyzer {
ExprAnalyzer(semantics::SemanticsContext &context) : context{context} {}
explicit ExprAnalyzer(semantics::SemanticsContext &ctx) : context{ctx} {}
MaybeExpr Analyze(const parser::Expr &);
MaybeExpr Analyze(const parser::CharLiteralConstantSubstring &);
@ -832,8 +832,8 @@ std::optional<CallAndArguments> ExprAnalyzer::Procedure(
} else {
CallCharacteristics cc{n.source};
if (std::optional<SpecificCall> specificCall{
intrinsics.Probe(
cc, arguments, &context.messages)}) {
context.intrinsics().Probe(cc, arguments,
&context.foldingContext().messages)}) {
return {CallAndArguments{
ProcedureDesignator{
std::move(specificCall->specificIntrinsic)},

View File

@ -492,7 +492,6 @@ int main(int argc, char *const argv[]) {
driver.pgf90Args.push_back("-Mbackslash");
}
Fortran::semantics::SemanticsContext semanticsContext{defaultKinds};
semanticsContext.set_moduleDirectory(driver.moduleDirectory)
.set_searchDirectories(driver.searchDirectories)