@@ -76,6 +76,7 @@ class PointerAssignmentChecker {
7676 const Procedure * = nullptr ,
7777 const evaluate::SpecificIntrinsic *specific = nullptr );
7878 bool LhsOkForUnlimitedPoly () const ;
79+ std::optional<MessageFormattedText> CheckRanks (const TypeAndShape &rhs) const ;
7980 template <typename ... A> parser::Message *Say (A &&...);
8081 template <typename FeatureOrUsageWarning, typename ... A>
8182 parser::Message *Warn (FeatureOrUsageWarning, A &&...);
@@ -278,10 +279,19 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) {
278279 } else if (lhsType_) {
279280 const auto *frTypeAndShape{funcResult->GetTypeAndShape ()};
280281 CHECK (frTypeAndShape);
281- if (!lhsType_->IsCompatibleWith (foldingContext_.messages (), *frTypeAndShape,
282- " pointer" , " function result" ,
283- /* omitShapeConformanceCheck=*/ isBoundsRemapping_ || isAssumedRank_,
284- evaluate::CheckConformanceFlags::BothDeferredShape)) {
282+ if (frTypeAndShape->type ().IsUnlimitedPolymorphic () &&
283+ LhsOkForUnlimitedPoly ()) {
284+ // Special case exception to type checking (F'2023 C1017);
285+ // still check rank compatibility.
286+ if (auto msg{CheckRanks (*frTypeAndShape)}) {
287+ Say (*msg);
288+ return false ;
289+ }
290+ } else if (!lhsType_->IsCompatibleWith (foldingContext_.messages (),
291+ *frTypeAndShape, " pointer" , " function result" ,
292+ /* omitShapeConformanceCheck=*/ isBoundsRemapping_ ||
293+ isAssumedRank_,
294+ evaluate::CheckConformanceFlags::BothDeferredShape)) {
285295 return false ; // IsCompatibleWith() emitted message
286296 }
287297 }
@@ -324,27 +334,17 @@ bool PointerAssignmentChecker::Check(const evaluate::Designator<T> &d) {
324334 msg = " Pointer must be VOLATILE when target is a"
325335 " VOLATILE coarray" _err_en_US;
326336 }
337+ } else if (auto m{CheckRanks (*rhsType)}) {
338+ msg = std::move (*m);
327339 } else if (rhsType->type ().IsUnlimitedPolymorphic ()) {
328340 if (!LhsOkForUnlimitedPoly ()) {
329341 msg = " Pointer type must be unlimited polymorphic or non-extensible"
330342 " derived type when target is unlimited polymorphic" _err_en_US;
331343 }
332- } else {
333- if (!lhsType_->type ().IsTkLenCompatibleWith (rhsType->type ())) {
334- msg = MessageFormattedText{
335- " Target type %s is not compatible with pointer type %s" _err_en_US,
336- rhsType->type ().AsFortran (), lhsType_->type ().AsFortran ()};
337-
338- } else if (!isBoundsRemapping_ &&
339- !lhsType_->attrs ().test (TypeAndShape::Attr::AssumedRank)) {
340- int lhsRank{lhsType_->Rank ()};
341- int rhsRank{rhsType->Rank ()};
342- if (lhsRank != rhsRank) {
343- msg = MessageFormattedText{
344- " Pointer has rank %d but target has rank %d" _err_en_US, lhsRank,
345- rhsRank};
346- }
347- }
344+ } else if (!lhsType_->type ().IsTkLenCompatibleWith (rhsType->type ())) {
345+ msg = MessageFormattedText{
346+ " Target type %s is not compatible with pointer type %s" _err_en_US,
347+ rhsType->type ().AsFortran (), lhsType_->type ().AsFortran ()};
348348 }
349349 }
350350 if (msg) {
@@ -434,6 +434,21 @@ bool PointerAssignmentChecker::LhsOkForUnlimitedPoly() const {
434434 }
435435}
436436
437+ std::optional<MessageFormattedText> PointerAssignmentChecker::CheckRanks (
438+ const TypeAndShape &rhs) const {
439+ if (!isBoundsRemapping_ &&
440+ !lhsType_->attrs ().test (TypeAndShape::Attr::AssumedRank)) {
441+ int lhsRank{lhsType_->Rank ()};
442+ int rhsRank{rhs.Rank ()};
443+ if (lhsRank != rhsRank) {
444+ return MessageFormattedText{
445+ " Pointer has rank %d but target has rank %d" _err_en_US, lhsRank,
446+ rhsRank};
447+ }
448+ }
449+ return std::nullopt ;
450+ }
451+
437452template <typename ... A>
438453parser::Message *PointerAssignmentChecker::Say (A &&...x) {
439454 auto *msg{foldingContext_.messages ().Say (std::forward<A>(x)...)};
0 commit comments