[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