Skip to content

Commit b2c363e

Browse files
authored
[flang] Fix generic resolution with actual/dummy procedure incompatib… (#120105)
…ility We generally allow any legal procedure pointer target as an actual argument for association with a dummy procedure, since many actual procedures are underspecified EXTERNALs. But for proper generic resolution, it is necessary to disallow incompatible functions with explicit result types. Fixes #119151.
1 parent 0e11e19 commit b2c363e

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

flang/lib/Semantics/expression.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,7 +2489,8 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
24892489

24902490
// Can actual be argument associated with dummy?
24912491
static bool CheckCompatibleArgument(bool isElemental,
2492-
const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
2492+
const ActualArgument &actual, const characteristics::DummyArgument &dummy,
2493+
FoldingContext &foldingContext) {
24932494
const auto *expr{actual.UnwrapExpr()};
24942495
return common::visit(
24952496
common::visitors{
@@ -2509,8 +2510,26 @@ static bool CheckCompatibleArgument(bool isElemental,
25092510
}
25102511
return false;
25112512
},
2512-
[&](const characteristics::DummyProcedure &) {
2513-
return expr && IsProcedurePointerTarget(*expr);
2513+
[&](const characteristics::DummyProcedure &dummy) {
2514+
if (!expr || !IsProcedurePointerTarget(*expr)) {
2515+
return false;
2516+
}
2517+
if (auto actualProc{characteristics::Procedure::Characterize(
2518+
*expr, foldingContext)}) {
2519+
const auto &dummyResult{dummy.procedure.value().functionResult};
2520+
const auto *dummyTypeAndShape{
2521+
dummyResult ? dummyResult->GetTypeAndShape() : nullptr};
2522+
const auto &actualResult{actualProc->functionResult};
2523+
const auto *actualTypeAndShape{
2524+
actualResult ? actualResult->GetTypeAndShape() : nullptr};
2525+
if (dummyTypeAndShape && actualTypeAndShape) {
2526+
// Return false when the function results' types are both
2527+
// known and not compatible.
2528+
return actualTypeAndShape->type().IsTkCompatibleWith(
2529+
dummyTypeAndShape->type());
2530+
}
2531+
}
2532+
return true;
25142533
},
25152534
[&](const characteristics::AlternateReturn &) {
25162535
return actual.isAlternateReturn();
@@ -2521,15 +2540,16 @@ static bool CheckCompatibleArgument(bool isElemental,
25212540

25222541
// Are the actual arguments compatible with the dummy arguments of procedure?
25232542
static bool CheckCompatibleArguments(
2524-
const characteristics::Procedure &procedure,
2525-
const ActualArguments &actuals) {
2543+
const characteristics::Procedure &procedure, const ActualArguments &actuals,
2544+
FoldingContext &foldingContext) {
25262545
bool isElemental{procedure.IsElemental()};
25272546
const auto &dummies{procedure.dummyArguments};
25282547
CHECK(dummies.size() == actuals.size());
25292548
for (std::size_t i{0}; i < dummies.size(); ++i) {
25302549
const characteristics::DummyArgument &dummy{dummies[i]};
25312550
const std::optional<ActualArgument> &actual{actuals[i]};
2532-
if (actual && !CheckCompatibleArgument(isElemental, *actual, dummy)) {
2551+
if (actual &&
2552+
!CheckCompatibleArgument(isElemental, *actual, dummy, foldingContext)) {
25332553
return false;
25342554
}
25352555
}
@@ -2726,7 +2746,8 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
27262746
}
27272747
if (semantics::CheckInterfaceForGeneric(*procedure, localActuals,
27282748
context_, false /* no integer conversions */) &&
2729-
CheckCompatibleArguments(*procedure, localActuals)) {
2749+
CheckCompatibleArguments(
2750+
*procedure, localActuals, foldingContext_)) {
27302751
if ((procedure->IsElemental() && elemental) ||
27312752
(!procedure->IsElemental() && nonElemental)) {
27322753
int d{ComputeCudaMatchingDistance(

flang/test/Semantics/generic11.f90

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
! Regression test for bug #119151
3+
interface sub
4+
subroutine sub1(ifun)
5+
interface
6+
integer function ifun()
7+
end
8+
end interface
9+
end
10+
subroutine sub2(rfun)
11+
real rfun
12+
external rfun
13+
end
14+
end interface
15+
integer ifun
16+
real rfun
17+
complex zfun
18+
external ifun, rfun, zfun, xfun
19+
call sub(ifun)
20+
call sub(rfun)
21+
!ERROR: No specific subroutine of generic 'sub' matches the actual arguments
22+
call sub(zfun)
23+
!ERROR: The actual arguments to the generic procedure 'sub' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface
24+
call sub(xfun)
25+
end

0 commit comments

Comments
 (0)