summaryrefslogtreecommitdiff
path: root/flang/lib/Evaluate/tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Evaluate/tools.cpp')
-rw-r--r--flang/lib/Evaluate/tools.cpp81
1 files changed, 36 insertions, 45 deletions
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 3b2c4f9f5601..1f3cbbf6a0c3 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -495,7 +495,7 @@ Expr<SomeComplex> PromoteMixedComplexReal(
// N.B. When a "typeless" BOZ literal constant appears as one (not both!) of
// the operands to a dyadic operation where one is permitted, it assumes the
// type and kind of the other operand.
-template <template <typename> class OPR, bool CAN_BE_UNSIGNED>
+template <template <typename> class OPR>
std::optional<Expr<SomeType>> NumericOperation(
parser::ContextualMessages &messages, Expr<SomeType> &&x,
Expr<SomeType> &&y, int defaultRealKind) {
@@ -510,13 +510,8 @@ std::optional<Expr<SomeType>> NumericOperation(
std::move(rx), std::move(ry)));
},
[&](Expr<SomeUnsigned> &&ix, Expr<SomeUnsigned> &&iy) {
- if constexpr (CAN_BE_UNSIGNED) {
- return Package(PromoteAndCombine<OPR, TypeCategory::Unsigned>(
- std::move(ix), std::move(iy)));
- } else {
- messages.Say("Operands must not be UNSIGNED"_err_en_US);
- return NoExpr();
- }
+ return Package(PromoteAndCombine<OPR, TypeCategory::Unsigned>(
+ std::move(ix), std::move(iy)));
},
// Mixed REAL/INTEGER operations
[](Expr<SomeReal> &&rx, Expr<SomeInteger> &&iy) {
@@ -575,34 +570,31 @@ std::optional<Expr<SomeType>> NumericOperation(
},
// Operations with one typeless operand
[&](BOZLiteralConstant &&bx, Expr<SomeInteger> &&iy) {
- return NumericOperation<OPR, CAN_BE_UNSIGNED>(messages,
+ return NumericOperation<OPR>(messages,
AsGenericExpr(ConvertTo(iy, std::move(bx))), std::move(y),
defaultRealKind);
},
[&](BOZLiteralConstant &&bx, Expr<SomeUnsigned> &&iy) {
- return NumericOperation<OPR, CAN_BE_UNSIGNED>(messages,
+ return NumericOperation<OPR>(messages,
AsGenericExpr(ConvertTo(iy, std::move(bx))), std::move(y),
defaultRealKind);
},
[&](BOZLiteralConstant &&bx, Expr<SomeReal> &&ry) {
- return NumericOperation<OPR, CAN_BE_UNSIGNED>(messages,
+ return NumericOperation<OPR>(messages,
AsGenericExpr(ConvertTo(ry, std::move(bx))), std::move(y),
defaultRealKind);
},
[&](Expr<SomeInteger> &&ix, BOZLiteralConstant &&by) {
- return NumericOperation<OPR, CAN_BE_UNSIGNED>(messages,
- std::move(x), AsGenericExpr(ConvertTo(ix, std::move(by))),
- defaultRealKind);
+ return NumericOperation<OPR>(messages, std::move(x),
+ AsGenericExpr(ConvertTo(ix, std::move(by))), defaultRealKind);
},
[&](Expr<SomeUnsigned> &&ix, BOZLiteralConstant &&by) {
- return NumericOperation<OPR, CAN_BE_UNSIGNED>(messages,
- std::move(x), AsGenericExpr(ConvertTo(ix, std::move(by))),
- defaultRealKind);
+ return NumericOperation<OPR>(messages, std::move(x),
+ AsGenericExpr(ConvertTo(ix, std::move(by))), defaultRealKind);
},
[&](Expr<SomeReal> &&rx, BOZLiteralConstant &&by) {
- return NumericOperation<OPR, CAN_BE_UNSIGNED>(messages,
- std::move(x), AsGenericExpr(ConvertTo(rx, std::move(by))),
- defaultRealKind);
+ return NumericOperation<OPR>(messages, std::move(x),
+ AsGenericExpr(ConvertTo(rx, std::move(by))), defaultRealKind);
},
// Error cases
[&](Expr<SomeUnsigned> &&, auto &&) {
@@ -621,7 +613,7 @@ std::optional<Expr<SomeType>> NumericOperation(
std::move(x.u), std::move(y.u));
}
-template std::optional<Expr<SomeType>> NumericOperation<Power, false>(
+template std::optional<Expr<SomeType>> NumericOperation<Power>(
parser::ContextualMessages &, Expr<SomeType> &&, Expr<SomeType> &&,
int defaultRealKind);
template std::optional<Expr<SomeType>> NumericOperation<Multiply>(
@@ -890,29 +882,6 @@ std::optional<Expr<SomeType>> ConvertToType(
}
}
-bool IsAssumedRank(const Symbol &original) {
- if (const auto *assoc{original.detailsIf<semantics::AssocEntityDetails>()}) {
- if (assoc->rank()) {
- return false; // in RANK(n) or RANK(*)
- } else if (assoc->IsAssumedRank()) {
- return true; // RANK DEFAULT
- }
- }
- const Symbol &symbol{semantics::ResolveAssociations(original)};
- const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()};
- return object && object->IsAssumedRank();
-}
-
-bool IsAssumedRank(const ActualArgument &arg) {
- if (const auto *expr{arg.UnwrapExpr()}) {
- return IsAssumedRank(*expr);
- } else {
- const Symbol *assumedTypeDummy{arg.GetAssumedTypeDummy()};
- CHECK(assumedTypeDummy);
- return IsAssumedRank(*assumedTypeDummy);
- }
-}
-
int GetCorank(const ActualArgument &arg) {
const auto *expr{arg.UnwrapExpr()};
return GetCorank(*expr);
@@ -1203,6 +1172,15 @@ bool HasVectorSubscript(const Expr<SomeType> &expr) {
return HasVectorSubscriptHelper{}(expr);
}
+bool HasVectorSubscript(const ActualArgument &actual) {
+ auto expr{actual.UnwrapExpr()};
+ return expr && HasVectorSubscript(*expr);
+}
+
+bool IsArraySection(const Expr<SomeType> &expr) {
+ return expr.Rank() > 0 && IsVariable(expr) && !UnwrapWholeSymbolDataRef(expr);
+}
+
// HasConstant()
struct HasConstantHelper : public AnyTraverse<HasConstantHelper, bool,
/*TraverseAssocEntityDetails=*/false> {
@@ -2312,9 +2290,22 @@ bool IsDummy(const Symbol &symbol) {
ResolveAssociations(symbol).details());
}
+bool IsAssumedRank(const Symbol &original) {
+ if (const auto *assoc{original.detailsIf<semantics::AssocEntityDetails>()}) {
+ if (assoc->rank()) {
+ return false; // in RANK(n) or RANK(*)
+ } else if (assoc->IsAssumedRank()) {
+ return true; // RANK DEFAULT
+ }
+ }
+ const Symbol &symbol{semantics::ResolveAssociations(original)};
+ const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()};
+ return object && object->IsAssumedRank();
+}
+
bool IsAssumedShape(const Symbol &symbol) {
const Symbol &ultimate{ResolveAssociations(symbol)};
- const auto *object{ultimate.detailsIf<ObjectEntityDetails>()};
+ const auto *object{ultimate.detailsIf<semantics::ObjectEntityDetails>()};
return object && object->IsAssumedShape() &&
!semantics::IsAllocatableOrObjectPointer(&ultimate);
}