Skip to content

Commit 11529d5

Browse files
authored
[flang] Fine-tune function result equivalence checking (#70260)
When a separate module function's definition has a redundant interface -- it's defined with MODULE FUNCTION, not MODULE PROCEDURE -- the check for result type equivalence needs to allow for character lengths that are the results of specification expressions. At present, identical-looking length specification expression don't compare equal, since they can refer to distinct dummy argument symbols. Ensure just that they are both constant or not, and if constant, that the lengths have the same value.
1 parent fa6b574 commit 11529d5

File tree

4 files changed

+50
-15
lines changed

4 files changed

+50
-15
lines changed

flang/lib/Evaluate/characteristics.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,13 +1069,32 @@ bool FunctionResult::IsCompatibleWith(
10691069
actual.IsAssumedLengthCharacter()) {
10701070
return true;
10711071
} else {
1072-
const auto *ifaceLenParam{
1073-
ifaceTypeShape->type().charLengthParamValue()};
1074-
const auto *actualLenParam{
1075-
actualTypeShape->type().charLengthParamValue()};
1076-
if (ifaceLenParam && actualLenParam &&
1077-
*ifaceLenParam == *actualLenParam) {
1078-
return true;
1072+
auto len{ToInt64(ifaceTypeShape->LEN())};
1073+
auto actualLen{ToInt64(actualTypeShape->LEN())};
1074+
if (len.has_value() != actualLen.has_value()) {
1075+
if (whyNot) {
1076+
*whyNot = "constant-length vs non-constant-length character "
1077+
"results";
1078+
}
1079+
} else if (len && *len != *actualLen) {
1080+
if (whyNot) {
1081+
*whyNot = "character results with distinct lengths";
1082+
}
1083+
} else {
1084+
const auto *ifaceLenParam{
1085+
ifaceTypeShape->type().charLengthParamValue()};
1086+
const auto *actualLenParam{
1087+
actualTypeShape->type().charLengthParamValue()};
1088+
if (ifaceLenParam && actualLenParam &&
1089+
ifaceLenParam->isExplicit() !=
1090+
actualLenParam->isExplicit()) {
1091+
if (whyNot) {
1092+
*whyNot =
1093+
"explicit-length vs deferred-length character results";
1094+
}
1095+
} else {
1096+
return true;
1097+
}
10791098
}
10801099
}
10811100
}

flang/lib/Semantics/check-declarations.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,11 +3289,14 @@ void SubprogramMatchHelper::Check(
32893289
Say(symbol1, symbol2,
32903290
"Module subprogram '%s' and its corresponding interface body are not both BIND(C)"_err_en_US);
32913291
}
3292-
if (proc1->functionResult && proc2->functionResult &&
3293-
*proc1->functionResult != *proc2->functionResult) {
3294-
Say(symbol1, symbol2,
3295-
"Return type of function '%s' does not match return type of"
3296-
" the corresponding interface body"_err_en_US);
3292+
if (proc1->functionResult && proc2->functionResult) {
3293+
std::string whyNot;
3294+
if (!proc1->functionResult->IsCompatibleWith(
3295+
*proc2->functionResult, &whyNot)) {
3296+
Say(symbol1, symbol2,
3297+
"Result of function '%s' is not compatible with the result of the corresponding interface body: %s"_err_en_US,
3298+
whyNot);
3299+
}
32973300
}
32983301
for (int i{0}; i < nargs1; ++i) {
32993302
const Symbol *arg1{args1[i]};

flang/test/Semantics/separate-mp02.f90

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,10 @@ module function f3()
272272
!OK
273273
real module function f1()
274274
end
275-
!ERROR: Return type of function 'f2' does not match return type of the corresponding interface body
275+
!ERROR: Result of function 'f2' is not compatible with the result of the corresponding interface body: function results have distinct types: INTEGER(4) vs REAL(4)
276276
integer module function f2()
277277
end
278-
!ERROR: Return type of function 'f3' does not match return type of the corresponding interface body
278+
!ERROR: Result of function 'f3' is not compatible with the result of the corresponding interface body: function results have incompatible attributes
279279
module function f3()
280280
real :: f3
281281
pointer :: f3
@@ -334,3 +334,16 @@ module subroutine sub2(s)
334334
character(len=1) s
335335
end subroutine
336336
end submodule
337+
338+
module m10
339+
interface
340+
module character(2) function f()
341+
end function
342+
end interface
343+
end module
344+
submodule(m10) sm10
345+
contains
346+
!ERROR: Result of function 'f' is not compatible with the result of the corresponding interface body: function results have distinct types: CHARACTER(KIND=1,LEN=3_8) vs CHARACTER(KIND=1,LEN=2_8)
347+
module character(3) function f()
348+
end function
349+
end submodule

flang/test/Semantics/separate-mp03.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ integer module function f1(x)
8181
!ERROR: 'notf2' was not declared a separate module procedure
8282
module procedure notf2
8383
end procedure
84-
!ERROR: Return type of function 'f3' does not match return type of the corresponding interface body
84+
!ERROR: Result of function 'f3' is not compatible with the result of the corresponding interface body: function results have distinct types: REAL(4) vs INTEGER(4)
8585
module function f3(x) result(res)
8686
real :: res
8787
real, intent(in) :: x

0 commit comments

Comments
 (0)