forked from OSchip/llvm-project
[flang] Add analyzed assignment to parse tree
Add `typedAssignment` to the `AssignmentStmt` node, analagous to `typedExpr` in `Expr`. This represents the analyzed form of an assignment. It may be a subroutine call in the case of a user-defined assignment. Add `GetAssignment` function to get it from the parse tree node if present. Original-commit: flang-compiler/f18@675b0b9bb7 Reviewed-on: https://github.com/flang-compiler/f18/pull/841 Tree-same-pre-rewrite: false
This commit is contained in:
parent
e67f6a775e
commit
ddb4f259f6
|
@ -175,6 +175,8 @@ bool GenericExprWrapper::operator==(const GenericExprWrapper &that) const {
|
|||
return v == that.v;
|
||||
}
|
||||
|
||||
GenericAssignmentWrapper::~GenericAssignmentWrapper() = default;
|
||||
|
||||
template<TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
|
||||
return std::visit(
|
||||
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
|
||||
|
@ -194,3 +196,4 @@ std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
|
|||
INSTANTIATE_EXPRESSION_TEMPLATES
|
||||
}
|
||||
DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
|
||||
DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
|
||||
|
|
|
@ -854,6 +854,21 @@ public:
|
|||
common::CombineVariants<TypelessExpression, CategoryExpression> u;
|
||||
};
|
||||
|
||||
// An assignment is either intrinsic (with lhs and rhs) or user-defined,
|
||||
// represented as a ProcedureRef.
|
||||
class Assignment {
|
||||
public:
|
||||
explicit Assignment(ProcedureRef &&x) : u{std::move(x)} {}
|
||||
Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs)
|
||||
: u{IntrinsicAssignment{std::move(lhs), std::move(rhs)}} {}
|
||||
struct IntrinsicAssignment {
|
||||
Expr<SomeType> lhs;
|
||||
Expr<SomeType> rhs;
|
||||
};
|
||||
|
||||
std::variant<IntrinsicAssignment, ProcedureRef> u;
|
||||
};
|
||||
|
||||
// This wrapper class is used, by means of a forward reference with
|
||||
// an owning pointer, to cache analyzed expressions in parse tree nodes.
|
||||
// v is nullopt if an error occurred during expression analysis.
|
||||
|
@ -864,6 +879,13 @@ struct GenericExprWrapper {
|
|||
std::optional<Expr<SomeType>> v;
|
||||
};
|
||||
|
||||
// Like GenericExprWrapper but for analyzed assignments
|
||||
struct GenericAssignmentWrapper {
|
||||
GenericAssignmentWrapper(std::optional<Assignment> &&x) : v{std::move(x)} {}
|
||||
~GenericAssignmentWrapper();
|
||||
std::optional<Assignment> v;
|
||||
};
|
||||
|
||||
FOR_EACH_CATEGORY_TYPE(extern template class Expr, )
|
||||
FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, )
|
||||
FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructorValues, )
|
||||
|
|
|
@ -23,6 +23,9 @@ namespace Fortran::evaluate {
|
|||
struct GenericExprWrapper {
|
||||
~GenericExprWrapper();
|
||||
};
|
||||
struct GenericAssignmentWrapper {
|
||||
~GenericAssignmentWrapper();
|
||||
};
|
||||
}
|
||||
|
||||
namespace Fortran::parser {
|
||||
|
@ -248,3 +251,4 @@ std::ostream &operator<<(std::ostream &os, const Name &x) {
|
|||
}
|
||||
|
||||
template class std::unique_ptr<Fortran::evaluate::GenericExprWrapper>;
|
||||
template class std::unique_ptr<Fortran::evaluate::GenericAssignmentWrapper>;
|
||||
|
|
|
@ -70,6 +70,7 @@ class DerivedTypeSpec;
|
|||
// type-checked generic expression representations by semantic analysis.
|
||||
namespace Fortran::evaluate {
|
||||
struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
|
||||
struct GenericAssignmentWrapper; // forward definition, represent assignment
|
||||
}
|
||||
|
||||
// Most non-template classes in this file use these default definitions
|
||||
|
@ -1918,6 +1919,9 @@ struct DeallocateStmt {
|
|||
// R1032 assignment-stmt -> variable = expr
|
||||
struct AssignmentStmt {
|
||||
TUPLE_CLASS_BOILERPLATE(AssignmentStmt);
|
||||
using TypedAssignment = std::unique_ptr<evaluate::GenericAssignmentWrapper,
|
||||
common::Deleter<evaluate::GenericAssignmentWrapper>>;
|
||||
mutable TypedAssignment typedAssignment;
|
||||
std::tuple<Variable, Expr> t;
|
||||
};
|
||||
|
||||
|
|
|
@ -315,6 +315,11 @@ bool ExprTypeKindIsDefault(
|
|||
dynamicType->kind() == context.GetDefaultKind(dynamicType->category());
|
||||
}
|
||||
|
||||
const evaluate::Assignment *GetAssignment(const parser::AssignmentStmt &x) {
|
||||
const auto &typed{x.typedAssignment};
|
||||
return typed && typed->v ? &*typed->v : nullptr;
|
||||
}
|
||||
|
||||
const Symbol *FindInterface(const Symbol &symbol) {
|
||||
return std::visit(
|
||||
common::visitors{
|
||||
|
|
|
@ -241,6 +241,8 @@ template<typename T> const SomeExpr *GetExpr(const T &x) {
|
|||
return GetExprHelper{}.Get(x);
|
||||
}
|
||||
|
||||
const evaluate::Assignment *GetAssignment(const parser::AssignmentStmt &);
|
||||
|
||||
template<typename T> std::optional<std::int64_t> GetIntValue(const T &x) {
|
||||
if (const auto *expr{GetExpr(x)}) {
|
||||
return evaluate::ToInt64(*expr);
|
||||
|
|
|
@ -24,6 +24,11 @@ struct GenericExprWrapper {
|
|||
~GenericExprWrapper();
|
||||
};
|
||||
GenericExprWrapper::~GenericExprWrapper() = default;
|
||||
struct GenericAssignmentWrapper {
|
||||
~GenericAssignmentWrapper();
|
||||
};
|
||||
GenericAssignmentWrapper::~GenericAssignmentWrapper() = default;
|
||||
}
|
||||
|
||||
DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
|
||||
DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
|
||||
|
|
Loading…
Reference in New Issue