diff options
Diffstat (limited to 'flang/lib/Evaluate')
-rw-r--r-- | flang/lib/Evaluate/intrinsics.cpp | 44 | ||||
-rw-r--r-- | flang/lib/Evaluate/tools.cpp | 34 |
2 files changed, 73 insertions, 5 deletions
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 768e4ba..c37a7f90 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -3077,10 +3077,11 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer( ActualArguments &arguments, FoldingContext &context) const { characteristics::Procedure::Attrs attrs; attrs.set(characteristics::Procedure::Attr::Subroutine); - static const char *const keywords[]{"cptr", "fptr", "shape", nullptr}; + static const char *const keywords[]{ + "cptr", "fptr", "shape", "lower", nullptr}; characteristics::DummyArguments dummies; - if (CheckAndRearrangeArguments(arguments, context.messages(), keywords, 1)) { - CHECK(arguments.size() == 3); + if (CheckAndRearrangeArguments(arguments, context.messages(), keywords, 2)) { + CHECK(arguments.size() == 4); if (const auto *expr{arguments[0].value().UnwrapExpr()}) { // General semantic checks will catch an actual argument that's not // scalar. @@ -3173,11 +3174,30 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer( } } } + if (arguments[3] && fptrRank == 0) { + context.messages().Say(arguments[3]->sourceLocation(), + "LOWER= argument to C_F_POINTER() may not appear when FPTR= is scalar"_err_en_US); + } else if (arguments[3]) { + if (const auto *argExpr{arguments[3].value().UnwrapExpr()}) { + if (argExpr->Rank() > 1) { + context.messages().Say(arguments[3]->sourceLocation(), + "LOWER= argument to C_F_POINTER() must be a rank-one array."_err_en_US); + } else if (argExpr->Rank() == 1) { + if (auto constShape{GetConstantShape(context, *argExpr)}) { + if (constShape->At(ConstantSubscripts{1}).ToInt64() != fptrRank) { + context.messages().Say(arguments[3]->sourceLocation(), + "LOWER= argument to C_F_POINTER() must have size equal to the rank of FPTR="_err_en_US); + } + } + } + } + } } } if (dummies.size() == 2) { + // Handle SHAPE DynamicType shapeType{TypeCategory::Integer, defaults_.sizeIntegerKind()}; - if (arguments[2]) { + if (arguments.size() >= 3 && arguments[2]) { if (auto type{arguments[2]->GetType()}) { if (type->category() == TypeCategory::Integer) { shapeType = *type; @@ -3189,6 +3209,22 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer( shape.intent = common::Intent::In; shape.attrs.set(characteristics::DummyDataObject::Attr::Optional); dummies.emplace_back("shape"s, std::move(shape)); + + // Handle LOWER + DynamicType lowerType{TypeCategory::Integer, defaults_.sizeIntegerKind()}; + if (arguments.size() >= 4 && arguments[3]) { + if (auto type{arguments[3]->GetType()}) { + if (type->category() == TypeCategory::Integer) { + lowerType = *type; + } + } + } + characteristics::DummyDataObject lower{ + characteristics::TypeAndShape{lowerType, 1}}; + lower.intent = common::Intent::In; + lower.attrs.set(characteristics::DummyDataObject::Attr::Optional); + dummies.emplace_back("lower"s, std::move(lower)); + return SpecificCall{ SpecificIntrinsic{"__builtin_c_f_pointer"s, characteristics::Procedure{std::move(dummies), attrs}}, diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index 21e6b3c..171dd91 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1809,10 +1809,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 +1941,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 { |