forked from OSchip/llvm-project
[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:
parent
d6ea6af7c4
commit
f50047f45c
|
@ -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_
|
||||
|
|
|
@ -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)},
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue