[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