llvm / llvm/llvm-project

[flang] F2023 C1545 conditional-arg consistency (corank/ALLOCATABLE/POINTER) is enforced for specific procedure references, rejecting conforming code

Open
#209,840 3 comments 0 reactions 1 assignee Claimed by @vntkmr View on GitHub
flang:frontend
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

The Fortran 2023 conditional-argument semantics support added by #195345 enforces constraint C1545 for every procedure reference, but C1545 is scoped to generic references only. F2023 C1545 reads: "In a reference to a **generic** procedure, each *consequent-arg* in a *conditional-arg* shall have the same corank, and if any *consequent-arg* of a *conditional-arg* has the ALLOCATABLE or POINTER attribute, each *consequent-arg* shall have that attribute." For a reference to a *specific* procedure the standard imposes no such cross-consequent consistency requirement, so mixing, e.g., an allocatable variable and an ordinary variable as the two consequents is conforming when the dummy is an ordinary (non-allocatable, non-pointer) object. Current flang rejects it.

Reproducer:

```fortran
subroutine caller(flag)
logical :: flag
integer, allocatable :: a
integer :: b
interface
subroutine sub_plain(x)
integer, intent(in) :: x
end subroutine
end interface
allocate(a, source=1)
! Specific (non-generic) reference; dummy is a plain integer.
! C1545 does not apply, so this is standard-conforming.
call sub_plain((flag ? a : b))
end subroutine
```

Actual behavior:

```
error: If any consequent-arg in a conditional argument has the ALLOCATABLE attribute, each must have it
call sub_plain((flag ? a : b))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

Expected behavior: no error. The dummy is a plain INTEGER, so C1542 does not apply, and 15.5.2.3 permits an allocatable actual argument to be associated with a non-allocatable dummy. The same over-enforcement exists for the POINTER half of the constraint and for the same-corank requirement, since all three are checked by the same unconditional lambda.

Control observations (same build): the identical call with two plain-integer consequents is accepted, and a genuine generic reference with mixed allocatable/plain consequents is correctly rejected — so the defect is purely that the check also fires on specific references.

This is a known follow-up from the #195345 review: the check currently lives in the per-call argument checking in `flang/lib/Semantics/check-call.cpp` (the `checkConsistency` lambda in the conditional-argument checking added by that PR), with an in-code comment acknowledging "Strictly, this requirement applies only to references to generic procedures … For now it is enforced unconditionally here" and a TODO to move it into generic resolution (`ResolveGeneric`) so it is enforced precisely. See the review discussion: https://github.com/llvm/llvm-project/pull/195345#discussion_r3354828775 (constraint is generic-only) and https://github.com/llvm/llvm-project/pull/195345#discussion_r3475073560 (deferred to a follow-up PR).

Impact: over-restriction only (conforming programs are rejected); no wrong code is generated. A fix should also add a positive test for a specific-procedure reference with mixed allocatable/plain (and pointer/plain) consequents, since the existing C1545 tests exercise allocatable/pointer *dummies*, where the explicit-interface check fires independently and masks this case.

Reproduced with flang built from the #195345 changes at commit 566e9a9ab585cd803557350675c796ddf51a7f21 applied on top of main (5b3b76e77386), x86_64-linux, 2026-07-15; #195345 has since merged as 816a5eacc440.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.