[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:28 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:

The situation around what a procedure reference returning a POINTER is not the most straightforward in the standard.

While the standard explicitly prevents their usage on the left hand side of a pointer assignment via the grammar (they are not variable names), it does not say the result does not have the POINTER attribute, and all of gfortran/ifx/nvfortran do consider they have the POINTER attribute when passing them since they all allow the following without any complaints:

```
recursive subroutine test(i)
 interface
   function returns_pointer()
     integer, pointer :: returns_pointer
   end function
 end interface
  interface
   subroutine takes_pointer(p)
     integer, pointer :: p
   end subroutine
 end interface
 integer, target :: i
 call takes_pointer(returns_pointer())
end subroutine
```

If such dummy pointer explicitly has the `INTENT(OUT)`, flang will reject pointer function reference as actual arguments. This shows flang do consider them as POINTER where the pointer cannot be defined (but the data target can).

Flang was explicitly aligned to follow this precedents in 

- https://github.com/llvm/llvm-project/commit/f025e41174
- https://github.com/llvm/llvm-project/commit/8b7a90b84b
- https://github.com/llvm/llvm-project/commit/f82ee15554
- https://github.com/llvm/llvm-project/commit/30d932305567e7f3d9018db3fd25060ae5c16cd5


In any case, the logic here should follow what is done in generic resolution, and currently generic resolution will consider that a function reference to a function returning an object pointer has the POINTER attribute as far as generic resolution is concerned (it is using `IsObjectPointer`), so the check that are meant to secure the potential ambiguity with conditional arguments in generic resolution should follow the same logic for consistency.

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


More information about the flang-commits mailing list