@@ -76,6 +76,7 @@ class PointerAssignmentChecker {
76
76
const Procedure * = nullptr ,
77
77
const evaluate::SpecificIntrinsic *specific = nullptr );
78
78
bool LhsOkForUnlimitedPoly () const ;
79
+ std::optional<MessageFormattedText> CheckRanks (const TypeAndShape &rhs) const ;
79
80
template <typename ... A> parser::Message *Say (A &&...);
80
81
template <typename FeatureOrUsageWarning, typename ... A>
81
82
parser::Message *Warn (FeatureOrUsageWarning, A &&...);
@@ -278,10 +279,19 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) {
278
279
} else if (lhsType_) {
279
280
const auto *frTypeAndShape{funcResult->GetTypeAndShape ()};
280
281
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)) {
285
295
return false ; // IsCompatibleWith() emitted message
286
296
}
287
297
}
@@ -324,27 +334,17 @@ bool PointerAssignmentChecker::Check(const evaluate::Designator<T> &d) {
324
334
msg = " Pointer must be VOLATILE when target is a"
325
335
" VOLATILE coarray" _err_en_US;
326
336
}
337
+ } else if (auto m{CheckRanks (*rhsType)}) {
338
+ msg = std::move (*m);
327
339
} else if (rhsType->type ().IsUnlimitedPolymorphic ()) {
328
340
if (!LhsOkForUnlimitedPoly ()) {
329
341
msg = " Pointer type must be unlimited polymorphic or non-extensible"
330
342
" derived type when target is unlimited polymorphic" _err_en_US;
331
343
}
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 ()};
348
348
}
349
349
}
350
350
if (msg) {
@@ -434,6 +434,21 @@ bool PointerAssignmentChecker::LhsOkForUnlimitedPoly() const {
434
434
}
435
435
}
436
436
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
+
437
452
template <typename ... A>
438
453
parser::Message *PointerAssignmentChecker::Say (A &&...x) {
439
454
auto *msg{foldingContext_.messages ().Say (std::forward<A>(x)...)};
0 commit comments