[flang-commits] [flang] [flang] Fix LBOUND of associate name with pointer function selector (PR #224753)
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 18 14:52:58 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Linisha (linisha15)
<details>
<summary>Changes</summary>
Fixes #<!-- -->220736.
# Problem
When the selector of an ASSOCIATE construct is a reference to a function
that returns a pointer array, `lbound` of the associate name returned 1
instead of the lower bound of the pointer's target:
associate (fp => f_ptr()) ! f_ptr() returns a pointer to tgt(2:4)
print *, lbound(fp) ! printed 1, should be 2
fp(2) = -20. ! correctly modifies tgt(2)
end associate
A reference to a pointer-valued function is a variable, so the associate
name takes the target's bounds. Subscripting already did this; `LBOUND`
did not.
# Cause
`GetLowerBoundHelper` in `Evaluate/shape.cpp` returns a constant lower
bound of 1 for any expression that is not a whole symbol or a constant.
That treated a pointer-valued function reference like an ordinary
operation, so `LBOUND` was folded to 1 at compile time.
# Fix
Skip that default when the expression is a reference to a pointer-valued
function. The existing code for associate names then uses a descriptor
inquiry, so the bound is read at run time from the descriptor, as
lowering already does for subscripts. Array sections, components and
non-pointer function results still fold to 1.
# Test
Adds `Semantics/associate05.f90`: `lbound(fp, 1)` on such an associate
name must not be accepted as a constant expression. Without this change
no error is reported; with it, "Must be a constant value" is reported.
A non-pointer function result is not affected.
# How I checked it
- Ran flang's parser and semantic analysis on the issue's reproducer,
with and without the change. Only the pointer-function case differs.
- Compared diagnostics, symbol tables and folded expressions with and
without the change across the 2,980 `.f90`/`.F90` files under
`flang/test/{Semantics,Evaluate,Lower}`. The only difference is the new
test. (31 files could not be analyzed by my standalone runner because
the built-in module files were missing.)
- clang-format is clean on the changed lines.
### Not checked locally
My machine could not build the full compiler, so I have not run
`check-flang`/`lit`, the reproducer end to end, or any lowering tests.
>From reading the code, lowering already takes bounds from the descriptor,
so `lbound(fp)` should now print 2. I am relying on CI to confirm.
---
Full diff: https://github.com/llvm/llvm-project/pull/224753.diff
2 Files Affected:
- (modified) flang/lib/Evaluate/shape.cpp (+3-1)
- (added) flang/test/Semantics/associate05.f90 (+27)
``````````diff
diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp
index 27913c3559c71d..e2e85937c97d90 100644
--- a/flang/lib/Evaluate/shape.cpp
+++ b/flang/lib/Evaluate/shape.cpp
@@ -368,7 +368,9 @@ class GetLowerBoundHelper
if (dimension_ < GetRank(lb)) {
return Result{lb[dimension_]};
}
- } else { // operation
+ } else if (!(UnwrapProcedureRef(expr) && IsVariable(expr))) {
+ // operation (a reference to a POINTER-valued function is a variable
+ // whose lower bounds come from its result's descriptor)
return Result{1};
}
} else {
diff --git a/flang/test/Semantics/associate05.f90 b/flang/test/Semantics/associate05.f90
new file mode 100644
index 00000000000000..951d1fb3454461
--- /dev/null
+++ b/flang/test/Semantics/associate05.f90
@@ -0,0 +1,27 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! The lower bounds of an associate name whose selector is a reference to a
+! function with a POINTER result are those of the pointer's target, which are
+! not known at compile time. LBOUND() of such a name must therefore not be
+! folded to a constant. A non-pointer function result still has default
+! lower bounds.
+module m
+ real, target :: tgt(2:4)
+ contains
+ function f_ptr()
+ real, pointer :: f_ptr(:)
+ f_ptr => tgt
+ end function
+ function f_val()
+ real :: f_val(2:4)
+ f_val = 0.
+ end function
+ subroutine test
+ associate (fp => f_ptr(), fv => f_val())
+ block
+ !ERROR: Must be a constant value
+ integer, parameter :: k1 = lbound(fp, 1)
+ integer, parameter :: k2 = lbound(fv, 1)
+ end block
+ end associate
+ end subroutine
+end module
``````````
</details>
https://github.com/llvm/llvm-project/pull/224753
More information about the flang-commits
mailing list