Skip to content

[flang] Fix generic resolution with actual/dummy procedure incompatib… #120105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 17, 2024

Conversation

klausler
Copy link
Contributor

…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.

…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 llvm#119151.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Dec 16, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 16, 2024

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

…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.


Full diff: https://github.com/llvm/llvm-project/pull/120105.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/expression.cpp (+28-7)
  • (added) flang/test/Semantics/generic11.f90 (+25)
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index b9be586f4d7721..0dbd6eaff40e3f 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2489,7 +2489,8 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
 
 // Can actual be argument associated with dummy?
 static bool CheckCompatibleArgument(bool isElemental,
-    const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
+    const ActualArgument &actual, const characteristics::DummyArgument &dummy,
+    FoldingContext &foldingContext) {
   const auto *expr{actual.UnwrapExpr()};
   return common::visit(
       common::visitors{
@@ -2509,8 +2510,26 @@ static bool CheckCompatibleArgument(bool isElemental,
             }
             return false;
           },
-          [&](const characteristics::DummyProcedure &) {
-            return expr && IsProcedurePointerTarget(*expr);
+          [&](const characteristics::DummyProcedure &dummy) {
+            if (!expr || !IsProcedurePointerTarget(*expr)) {
+              return false;
+            }
+            if (auto actualProc{characteristics::Procedure::Characterize(
+                    *expr, foldingContext)}) {
+              const auto &dummyResult{dummy.procedure.value().functionResult};
+              const auto *dummyTypeAndShape{
+                  dummyResult ? dummyResult->GetTypeAndShape() : nullptr};
+              const auto &actualResult{actualProc->functionResult};
+              const auto *actualTypeAndShape{
+                  actualResult ? actualResult->GetTypeAndShape() : nullptr};
+              if (dummyTypeAndShape && actualTypeAndShape) {
+                // Return false when the function results' types are both
+                // known and not compatible.
+                return actualTypeAndShape->type().IsTkCompatibleWith(
+                    dummyTypeAndShape->type());
+              }
+            }
+            return true;
           },
           [&](const characteristics::AlternateReturn &) {
             return actual.isAlternateReturn();
@@ -2521,15 +2540,16 @@ static bool CheckCompatibleArgument(bool isElemental,
 
 // Are the actual arguments compatible with the dummy arguments of procedure?
 static bool CheckCompatibleArguments(
-    const characteristics::Procedure &procedure,
-    const ActualArguments &actuals) {
+    const characteristics::Procedure &procedure, const ActualArguments &actuals,
+    FoldingContext &foldingContext) {
   bool isElemental{procedure.IsElemental()};
   const auto &dummies{procedure.dummyArguments};
   CHECK(dummies.size() == actuals.size());
   for (std::size_t i{0}; i < dummies.size(); ++i) {
     const characteristics::DummyArgument &dummy{dummies[i]};
     const std::optional<ActualArgument> &actual{actuals[i]};
-    if (actual && !CheckCompatibleArgument(isElemental, *actual, dummy)) {
+    if (actual &&
+        !CheckCompatibleArgument(isElemental, *actual, dummy, foldingContext)) {
       return false;
     }
   }
@@ -2726,7 +2746,8 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
         }
         if (semantics::CheckInterfaceForGeneric(*procedure, localActuals,
                 context_, false /* no integer conversions */) &&
-            CheckCompatibleArguments(*procedure, localActuals)) {
+            CheckCompatibleArguments(
+                *procedure, localActuals, foldingContext_)) {
           if ((procedure->IsElemental() && elemental) ||
               (!procedure->IsElemental() && nonElemental)) {
             int d{ComputeCudaMatchingDistance(
diff --git a/flang/test/Semantics/generic11.f90 b/flang/test/Semantics/generic11.f90
new file mode 100644
index 00000000000000..14383ab150fe41
--- /dev/null
+++ b/flang/test/Semantics/generic11.f90
@@ -0,0 +1,25 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Regression test for bug #119151
+interface sub
+  subroutine sub1(ifun)
+    interface
+      integer function ifun()
+      end
+     end interface
+   end
+   subroutine sub2(rfun)
+     real rfun
+     external rfun
+   end
+end interface
+integer ifun
+real rfun
+complex zfun
+external ifun, rfun, zfun, xfun
+call sub(ifun)
+call sub(rfun)
+!ERROR: No specific subroutine of generic 'sub' matches the actual arguments
+call sub(zfun)
+!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
+call sub(xfun)
+end

@klausler klausler merged commit b2c363e into llvm:main Dec 17, 2024
11 checks passed
@klausler klausler deleted the bug119151 branch December 17, 2024 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Flang] Compilation error when a subroutine described in generic procedure interface is referred to by generic name
3 participants