diff options
Diffstat (limited to 'flang/lib/Semantics/pointer-assignment.cpp')
-rw-r--r-- | flang/lib/Semantics/pointer-assignment.cpp | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 2450ce3..7f4548c 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -76,6 +76,7 @@ private: const Procedure * = nullptr, const evaluate::SpecificIntrinsic *specific = nullptr); bool LhsOkForUnlimitedPoly() const; + std::optional<MessageFormattedText> CheckRanks(const TypeAndShape &rhs) const; template <typename... A> parser::Message *Say(A &&...); template <typename FeatureOrUsageWarning, typename... A> parser::Message *Warn(FeatureOrUsageWarning, A &&...); @@ -278,10 +279,19 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) { } else if (lhsType_) { const auto *frTypeAndShape{funcResult->GetTypeAndShape()}; CHECK(frTypeAndShape); - if (!lhsType_->IsCompatibleWith(foldingContext_.messages(), *frTypeAndShape, - "pointer", "function result", - /*omitShapeConformanceCheck=*/isBoundsRemapping_ || isAssumedRank_, - evaluate::CheckConformanceFlags::BothDeferredShape)) { + if (frTypeAndShape->type().IsUnlimitedPolymorphic() && + LhsOkForUnlimitedPoly()) { + // Special case exception to type checking (F'2023 C1017); + // still check rank compatibility. + if (auto msg{CheckRanks(*frTypeAndShape)}) { + Say(*msg); + return false; + } + } else if (!lhsType_->IsCompatibleWith(foldingContext_.messages(), + *frTypeAndShape, "pointer", "function result", + /*omitShapeConformanceCheck=*/isBoundsRemapping_ || + isAssumedRank_, + evaluate::CheckConformanceFlags::BothDeferredShape)) { return false; // IsCompatibleWith() emitted message } } @@ -324,27 +334,17 @@ bool PointerAssignmentChecker::Check(const evaluate::Designator<T> &d) { msg = "Pointer must be VOLATILE when target is a" " VOLATILE coarray"_err_en_US; } + } else if (auto m{CheckRanks(*rhsType)}) { + msg = std::move(*m); } else if (rhsType->type().IsUnlimitedPolymorphic()) { if (!LhsOkForUnlimitedPoly()) { msg = "Pointer type must be unlimited polymorphic or non-extensible" " derived type when target is unlimited polymorphic"_err_en_US; } - } else { - if (!lhsType_->type().IsTkLenCompatibleWith(rhsType->type())) { - msg = MessageFormattedText{ - "Target type %s is not compatible with pointer type %s"_err_en_US, - rhsType->type().AsFortran(), lhsType_->type().AsFortran()}; - - } else if (!isBoundsRemapping_ && - !lhsType_->attrs().test(TypeAndShape::Attr::AssumedRank)) { - int lhsRank{lhsType_->Rank()}; - int rhsRank{rhsType->Rank()}; - if (lhsRank != rhsRank) { - msg = MessageFormattedText{ - "Pointer has rank %d but target has rank %d"_err_en_US, lhsRank, - rhsRank}; - } - } + } else if (!lhsType_->type().IsTkLenCompatibleWith(rhsType->type())) { + msg = MessageFormattedText{ + "Target type %s is not compatible with pointer type %s"_err_en_US, + rhsType->type().AsFortran(), lhsType_->type().AsFortran()}; } } if (msg) { @@ -434,6 +434,21 @@ bool PointerAssignmentChecker::LhsOkForUnlimitedPoly() const { } } +std::optional<MessageFormattedText> PointerAssignmentChecker::CheckRanks( + const TypeAndShape &rhs) const { + if (!isBoundsRemapping_ && + !lhsType_->attrs().test(TypeAndShape::Attr::AssumedRank)) { + int lhsRank{lhsType_->Rank()}; + int rhsRank{rhs.Rank()}; + if (lhsRank != rhsRank) { + return MessageFormattedText{ + "Pointer has rank %d but target has rank %d"_err_en_US, lhsRank, + rhsRank}; + } + } + return std::nullopt; +} + template <typename... A> parser::Message *PointerAssignmentChecker::Say(A &&...x) { auto *msg{foldingContext_.messages().Say(std::forward<A>(x)...)}; |