aboutsummaryrefslogtreecommitdiff
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.cpp44
1 files changed, 40 insertions, 4 deletions
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 21e6b3c..9c059b0 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1693,17 +1693,17 @@ struct ArgumentExtractor
// to int(kind=4) for example.
return (*this)(x.template operand<0>());
} else {
- return std::make_pair(operation::OperationCode(x),
+ return std::make_pair(operation::OperationCode(x.derived()),
OperationArgs(x, std::index_sequence_for<Os...>{}));
}
}
template <typename T> Result operator()(const Designator<T> &x) const {
- return {operation::Operator::Identity, {AsSomeExpr(x)}};
+ return {operation::OperationCode(x), {AsSomeExpr(x)}};
}
template <typename T> Result operator()(const Constant<T> &x) const {
- return {operation::Operator::Identity, {AsSomeExpr(x)}};
+ return {operation::OperationCode(x), {AsSomeExpr(x)}};
}
template <typename... Rs>
@@ -1793,6 +1793,10 @@ std::string operation::ToString(operation::Operator op) {
llvm_unreachable("Unhandler operator");
}
+operation::Operator operation::OperationCode(const Relational<SomeType> &op) {
+ return common::visit([](auto &&s) { return OperationCode(s); }, op.u);
+}
+
operation::Operator operation::OperationCode(const ProcedureDesignator &proc) {
Operator code{llvm::StringSwitch<Operator>(proc.GetName())
.Case("associated", Operator::Associated)
@@ -1809,10 +1813,15 @@ operation::Operator operation::OperationCode(const ProcedureDesignator &proc) {
}
std::pair<operation::Operator, std::vector<Expr<SomeType>>>
-GetTopLevelOperation(const Expr<SomeType> &expr) {
+GetTopLevelOperationIgnoreResizing(const Expr<SomeType> &expr) {
return operation::ArgumentExtractor<true>{}(expr);
}
+std::pair<operation::Operator, std::vector<Expr<SomeType>>>
+GetTopLevelOperation(const Expr<SomeType> &expr) {
+ return operation::ArgumentExtractor<false>{}(expr);
+}
+
namespace operation {
struct ConvertCollector
: public Traverse<ConvertCollector,
@@ -1936,6 +1945,33 @@ bool IsSameOrConvertOf(const Expr<SomeType> &expr, const Expr<SomeType> &x) {
return false;
}
}
+
+struct VariableFinder : public evaluate::AnyTraverse<VariableFinder> {
+ using Base = evaluate::AnyTraverse<VariableFinder>;
+ using SomeExpr = Expr<SomeType>;
+ VariableFinder(const SomeExpr &v) : Base(*this), var(v) {}
+
+ using Base::operator();
+
+ template <typename T>
+ bool operator()(const evaluate::Designator<T> &x) const {
+ return evaluate::AsGenericExpr(common::Clone(x)) == var;
+ }
+
+ template <typename T>
+ bool operator()(const evaluate::FunctionRef<T> &x) const {
+ return evaluate::AsGenericExpr(common::Clone(x)) == var;
+ }
+
+private:
+ const SomeExpr &var;
+};
+
+bool IsVarSubexpressionOf(
+ const Expr<SomeType> &sub, const Expr<SomeType> &super) {
+ return VariableFinder{sub}(super);
+}
+
} // namespace Fortran::evaluate
namespace Fortran::semantics {