Skip to content

Commit b59dd1c

Browse files
committed
[flang] Fine-tune function result equivalence checking
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 7c2ef38 commit b59dd1c

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
@@ -1060,13 +1060,32 @@ bool FunctionResult::IsCompatibleWith(
10601060
actual.IsAssumedLengthCharacter()) {
10611061
return true;
10621062
} else {
1063-
const auto *ifaceLenParam{
1064-
ifaceTypeShape->type().charLengthParamValue()};
1065-
const auto *actualLenParam{
1066-
actualTypeShape->type().charLengthParamValue()};
1067-
if (ifaceLenParam && actualLenParam &&
1068-
*ifaceLenParam == *actualLenParam) {
1069-
return true;
1063+
auto len{ToInt64(ifaceTypeShape->LEN())};
1064+
auto actualLen{ToInt64(actualTypeShape->LEN())};
1065+
if (len.has_value() != actualLen.has_value()) {
1066+
if (whyNot) {
1067+
*whyNot = "constant-length vs non-constant-length character "
1068+
"results";
1069+
}
1070+
} else if (len && *len != *actualLen) {
1071+
if (whyNot) {
1072+
*whyNot = "character results with distinct lengths";
1073+
}
1074+
} else {
1075+
const auto *ifaceLenParam{
1076+
ifaceTypeShape->type().charLengthParamValue()};
1077+
const auto *actualLenParam{
1078+
actualTypeShape->type().charLengthParamValue()};
1079+
if (ifaceLenParam && actualLenParam &&
1080+
ifaceLenParam->isExplicit() !=
1081+
actualLenParam->isExplicit()) {
1082+
if (whyNot) {
1083+
*whyNot =
1084+
"explicit-length vs deferred-length character results";
1085+
}
1086+
} else {
1087+
return true;
1088+
}
10701089
}
10711090
}
10721091
}

flang/lib/Semantics/check-declarations.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,11 +3285,14 @@ void SubprogramMatchHelper::Check(
32853285
Say(symbol1, symbol2,
32863286
"Module subprogram '%s' and its corresponding interface body are not both BIND(C)"_err_en_US);
32873287
}
3288-
if (proc1->functionResult && proc2->functionResult &&
3289-
*proc1->functionResult != *proc2->functionResult) {
3290-
Say(symbol1, symbol2,
3291-
"Return type of function '%s' does not match return type of"
3292-
" the corresponding interface body"_err_en_US);
3288+
if (proc1->functionResult && proc2->functionResult) {
3289+
std::string whyNot;
3290+
if (!proc1->functionResult->IsCompatibleWith(
3291+
*proc2->functionResult, &whyNot)) {
3292+
Say(symbol1, symbol2,
3293+
"Result of function '%s' is not compatible with the result of the corresponding interface body: %s"_err_en_US,
3294+
whyNot);
3295+
}
32933296
}
32943297
for (int i{0}; i < nargs1; ++i) {
32953298
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)