[flang-commits] [flang] [flang][Semantics] Enforce F2023 C1545 only for generic references (PR #219581)

via flang-commits flang-commits at lists.llvm.org
Mon Aug 31 08:33:29 PDT 2026


================
@@ -1460,54 +1461,74 @@ static void CheckConditionalArg(
           "Each consequent-arg in conditional argument associated with a coarray %s must be a coarray"_err_en_US,
           dummyName);
     }
-    // C1544: the requirement that each consequent-arg match the dummy's
-    // ALLOCATABLE/POINTER attribute is enforced by the standard
-    // explicit-interface check (checkOneExpr) run on each non-.NIL.
-    // consequent below.
   }};
   condArg.ForEachConsequent(checkOneConsequent);
-  // C1545: in a reference to a generic procedure, each consequent-arg shall
-  // have the same corank, and if any has the ALLOCATABLE or POINTER attribute,
-  // each shall have it.  Strictly, this requirement applies only to references
-  // to generic procedures, where it avoids ambiguity when resolving the generic
-  // to a specific procedure; for a specific procedure reference these
-  // combinations are otherwise allowed.  For now it is enforced unconditionally
-  // here.
-  // TODO: move this check into generic resolution (ResolveGeneric) and enforce
-  // it precisely, i.e. only for references to generic procedures, where the
-  // ambiguity it guards against can actually arise.
-  std::optional<int> firstCorank;
-  std::optional<bool> firstIsAllocatable;
-  std::optional<bool> firstIsPointer;
-  auto checkConsistency{[&](const evaluate::ActualArgument::ConditionalArg::
-                                Consequent &cons) {
-    if (!cons) {
-      return;
+}
+
+// A pointer-valued function reference is an expression, not an entity with the
+// POINTER attribute, and may not be a POINTER actual argument;
+// IsObjectPointer() accepts it, IsAllocatableDesignator() does not.
+static bool HasPointerAttribute(
+    const evaluate::Expr<evaluate::SomeType> &expr) {
+  return evaluate::IsObjectPointer(expr) && !evaluate::UnwrapProcedureRef(expr);
+}
----------------
jeanPerier wrote:

Another way to look at it, in the following code, given both `gen(p)` and `gen(returns_pointer())` are accepted and resolve to the same specific, so should `gen((l ? p : returns_pointer()))`.

```
subroutine test(p, l)
  interface
    function returns_pointer() result(res)
      integer, pointer :: res
    end function
  end interface
  interface gen
    subroutine takes_pointer(x)
      integer, pointer :: x          ! not INTENT(IN)
    end subroutine
    subroutine takes_allocatable(x)
      integer, allocatable :: x
    end subroutine
  end interface
  integer, pointer :: p
  logical :: l
  call gen(p)
  call gen(returns_pointer())
  call gen((l ? p : returns_pointer())) 
end subroutine
```

https://github.com/llvm/llvm-project/pull/219581


More information about the flang-commits mailing list