[flang-commits] [flang] [flang][debug] Track dummy argument positions explicitly. (PR #167489)

via flang-commits flang-commits at lists.llvm.org
Tue Nov 11 03:09:41 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Abid Qadeer (abidh)

<details>
<summary>Changes</summary>

CHARACTER dummy arguments were treated as local variables in debug info. This happened because our method to get the argument number was not robust. It relied on `DeclareOp` having a direct reference to arguments which was not the case for character arguments. This is fixed by storing source-level argument positions in `DeclareOp`.

Fixes #<!-- -->112886

---

Patch is 920.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/167489.diff


192 Files Affected:

- (modified) flang/include/flang/Lower/AbstractConverter.h (+6) 
- (modified) flang/include/flang/Optimizer/Builder/HLFIRTools.h (+1-1) 
- (modified) flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td (+3-2) 
- (modified) flang/include/flang/Optimizer/Dialect/FIROps.td (+3-2) 
- (modified) flang/include/flang/Optimizer/HLFIR/HLFIROps.td (+4-3) 
- (modified) flang/lib/Lower/Bridge.cpp (+39-6) 
- (modified) flang/lib/Lower/ConvertVariable.cpp (+8-3) 
- (modified) flang/lib/Optimizer/Builder/FIRBuilder.cpp (+2-1) 
- (modified) flang/lib/Optimizer/Builder/HLFIRTools.cpp (+2-2) 
- (modified) flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp (+5-1) 
- (modified) flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp (+10-9) 
- (modified) flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp (+2-1) 
- (modified) flang/lib/Optimizer/Transforms/AddDebugInfo.cpp (+3-16) 
- (modified) flang/test/Fir/dispatch.f90 (+1-1) 
- (modified) flang/test/HLFIR/assumed-type-actual-args.f90 (+10-10) 
- (modified) flang/test/HLFIR/assumed_shape_with_value_keyword.f90 (+9-9) 
- (modified) flang/test/HLFIR/boxchar_emboxing.f90 (+2-2) 
- (modified) flang/test/HLFIR/c_ptr_byvalue.f90 (+1-1) 
- (modified) flang/test/HLFIR/call_with_poly_dummy.f90 (+1-1) 
- (modified) flang/test/HLFIR/optional_dummy.f90 (+1-1) 
- (added) flang/test/Integration/debug-char-arg-issue-112886.f90 (+46) 
- (modified) flang/test/Lower/CUDA/cuda-data-attribute.cuf (+4-4) 
- (modified) flang/test/Lower/CUDA/cuda-data-transfer.cuf (+8-8) 
- (modified) flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 (+11-11) 
- (modified) flang/test/Lower/HLFIR/allocatable-and-pointer-status-change.f90 (+6-6) 
- (modified) flang/test/Lower/HLFIR/allocatables-and-pointers.f90 (+9-9) 
- (modified) flang/test/Lower/HLFIR/array-ctor-as-elemental-nested.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/array-ctor-as-elemental.f90 (+5-5) 
- (modified) flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 (+6-6) 
- (modified) flang/test/Lower/HLFIR/array-ctor-index.f90 (+4-4) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-calls.f90 (+6-6) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-entry.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-iface-alloc-ptr.f90 (+5-5) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-iface.f90 (+9-9) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-inquiries-2.f90 (+5-5) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-inquiries.f90 (+24-24) 
- (modified) flang/test/Lower/HLFIR/assumed-rank-internal-proc.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/binary-ops.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/bindc-value-derived.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 (+8-8) 
- (modified) flang/test/Lower/HLFIR/calls-array-results.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/calls-assumed-shape.f90 (+7-7) 
- (modified) flang/test/Lower/HLFIR/calls-constant-expr-arg.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/calls-f77.f90 (+7-7) 
- (modified) flang/test/Lower/HLFIR/calls-optional.f90 (+7-7) 
- (modified) flang/test/Lower/HLFIR/calls-percent-val-ref.f90 (+6-6) 
- (modified) flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/charconvert.f90 (+4-4) 
- (modified) flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/complex-div-to-hlfir.f90 (+12-12) 
- (modified) flang/test/Lower/HLFIR/convert-mbox-to-value.f90 (+8-8) 
- (modified) flang/test/Lower/HLFIR/convert-variable-assumed-rank.f90 (+9-9) 
- (modified) flang/test/Lower/HLFIR/convert-variable-block.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/convert-variable.f90 (+11-11) 
- (modified) flang/test/Lower/HLFIR/cray-pointers.f90 (+5-5) 
- (modified) flang/test/Lower/HLFIR/cshift.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/custom-intrinsic.f90 (+50-50) 
- (modified) flang/test/Lower/HLFIR/designators-component-ref.f90 (+4-4) 
- (modified) flang/test/Lower/HLFIR/designators.f90 (+20-20) 
- (modified) flang/test/Lower/HLFIR/dot_product.f90 (+2-2) 
- (added) flang/test/Lower/HLFIR/dummy-arg-number.f90 (+53) 
- (modified) flang/test/Lower/HLFIR/dummy-scope.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/elemental-array-ops.f90 (+6-6) 
- (modified) flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 (+4-4) 
- (modified) flang/test/Lower/HLFIR/elemental-result-length.f90 (+6-6) 
- (modified) flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/eoshift.f90 (+11-11) 
- (modified) flang/test/Lower/HLFIR/expr-addr.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/expr-box.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/expr-value.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 (+5-5) 
- (modified) flang/test/Lower/HLFIR/implicit-type-conversion.f90 (+14-14) 
- (modified) flang/test/Lower/HLFIR/index.f90 (+12-12) 
- (modified) flang/test/Lower/HLFIR/intentout-allocatable-components.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/internal-procedures.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/intrinsic-dynamically-optional.f90 (+2-2) 
- (modified) flang/test/Lower/HLFIR/procedure-pointer.f90 (+3-3) 
- (modified) flang/test/Lower/HLFIR/select-rank.f90 (+18-18) 
- (modified) flang/test/Lower/HLFIR/statement-functions.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/structure-constructor.f90 (+8-8) 
- (modified) flang/test/Lower/HLFIR/transformational.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/transpose.f90 (+5-5) 
- (modified) flang/test/Lower/HLFIR/trim.f90 (+1-1) 
- (modified) flang/test/Lower/HLFIR/user-defined-assignment.f90 (+19-19) 
- (modified) flang/test/Lower/HLFIR/vector-subscript-as-value.f90 (+3-3) 
- (modified) flang/test/Lower/Intrinsics/associated-proc-pointers.f90 (+6-6) 
- (modified) flang/test/Lower/Intrinsics/c_f_procpointer.f90 (+4-4) 
- (modified) flang/test/Lower/Intrinsics/c_funloc-proc-pointers.f90 (+2-2) 
- (modified) flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 (+4-4) 
- (modified) flang/test/Lower/Intrinsics/etime-function.f90 (+2-2) 
- (modified) flang/test/Lower/Intrinsics/etime.f90 (+2-2) 
- (modified) flang/test/Lower/Intrinsics/execute_command_line-optional.f90 (+5-5) 
- (modified) flang/test/Lower/Intrinsics/execute_command_line.f90 (+6-6) 
- (modified) flang/test/Lower/Intrinsics/getcwd-function.f90 (+1-1) 
- (modified) flang/test/Lower/Intrinsics/getcwd-optional.f90 (+2-2) 
- (modified) flang/test/Lower/Intrinsics/getcwd.f90 (+3-3) 
- (modified) flang/test/Lower/Intrinsics/ieee_logb.f90 (+1-1) 
- (modified) flang/test/Lower/Intrinsics/nearest.f90 (+14-14) 
- (modified) flang/test/Lower/Intrinsics/perror.f90 (+1-1) 
- (modified) flang/test/Lower/Intrinsics/putenv-sub.f90 (+3-3) 
- (modified) flang/test/Lower/Intrinsics/rename.f90 (+4-4) 
- (modified) flang/test/Lower/Intrinsics/second.f90 (+4-4) 
- (modified) flang/test/Lower/Intrinsics/selected_char_kind.f90 (+1-1) 
- (modified) flang/test/Lower/Intrinsics/selected_logical_kind.f90 (+5-5) 
- (modified) flang/test/Lower/Intrinsics/signal.f90 (+1-1) 
- (modified) flang/test/Lower/Intrinsics/sizeof.f90 (+2-2) 
- (modified) flang/test/Lower/Intrinsics/system-optional.f90 (+2-2) 
- (modified) flang/test/Lower/Intrinsics/system.f90 (+4-4) 
- (modified) flang/test/Lower/Intrinsics/unlink-sub.f90 (+3-3) 
- (modified) flang/test/Lower/OpenACC/acc-atomic-update-array.f90 (+9-9) 
- (modified) flang/test/Lower/OpenACC/acc-bounds.f90 (+5-5) 
- (modified) flang/test/Lower/OpenACC/acc-data-operands-remapping.f90 (+46-46) 
- (modified) flang/test/Lower/OpenACC/acc-declare.f90 (+7-7) 
- (modified) flang/test/Lower/OpenACC/acc-enter-data.f90 (+1-1) 
- (modified) flang/test/Lower/OpenACC/acc-firstprivate-derived-pointer-component.f90 (+2-2) 
- (modified) flang/test/Lower/OpenACC/acc-loop-exit.f90 (+1-1) 
- (modified) flang/test/Lower/OpenACC/acc-private.f90 (+6-6) 
- (modified) flang/test/Lower/OpenACC/acc-reduction.f90 (+4-4) 
- (modified) flang/test/Lower/OpenACC/acc-use-device.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/allocatable-array-bounds.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/array-bounds.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/cancel.f90 (+4-4) 
- (modified) flang/test/Lower/OpenMP/depend-complex.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/depend-substring.f90 (+4-4) 
- (modified) flang/test/Lower/OpenMP/flush.f90 (+6-6) 
- (modified) flang/test/Lower/OpenMP/optional-argument-map-2.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/parallel-firstprivate-clause-scalar.f90 (+21-21) 
- (modified) flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 (+9-9) 
- (modified) flang/test/Lower/OpenMP/parallel-private-clause-fixes.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/parallel-private-clause-str.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/parallel-reduction3.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/parallel-wsloop-firstpriv.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/parallel-wsloop-lastpriv.f90 (+5-5) 
- (modified) flang/test/Lower/OpenMP/parallel-wsloop.f90 (+11-11) 
- (modified) flang/test/Lower/OpenMP/reduction-array-intrinsic.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/sections-array-reduction.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/sections-reduction.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/sections.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/simd.f90 (+7-7) 
- (modified) flang/test/Lower/OpenMP/single.f90 (+6-6) 
- (modified) flang/test/Lower/OpenMP/target.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/task-depend-array-section.f90 (+4-4) 
- (modified) flang/test/Lower/OpenMP/tile01.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/tile02.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/unroll-heuristic01.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/unroll-heuristic02.f90 (+6-6) 
- (modified) flang/test/Lower/OpenMP/unroll-heuristic03.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-max.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 (+2-2) 
- (modified) flang/test/Lower/OpenMP/wsloop-reduction-min.f90 (+2-2) 
- (modified) flang/test/Lower/allocatable-assignment.f90 (+30-30) 
- (modified) flang/test/Lower/allocatable-polymorphic.f90 (+3-3) 
- (modified) flang/test/Lower/array-character.f90 (+2-2) 
- (modified) flang/test/Lower/array-elemental-calls-char-byval.f90 (+12-12) 
- (modified) flang/test/Lower/array-elemental-calls-char-dynamic.f90 (+11-11) 
- (modified) flang/test/Lower/array-elemental-calls-char.f90 (+15-15) 
- (modified) flang/test/Lower/box-address.f90 (+1-1) 
- (modified) flang/test/Lower/call-by-value-attr.f90 (+1-1) 
- (modified) flang/test/Lower/call-character-array-to-polymorphic-pointer.f90 (+1-1) 
- (modified) flang/test/Lower/character-substrings.f90 (+9-9) 
- (modified) flang/test/Lower/charconvert.f90 (+4-4) 
- (modified) flang/test/Lower/components.f90 (+7-7) 
- (modified) flang/test/Lower/derived-assignments.f90 (+12-12) 
- (modified) flang/test/Lower/dispatch.f90 (+15-15) 
- (modified) flang/test/Lower/entry-statement.f90 (+6-6) 
- (modified) flang/test/Lower/forall-pointer-assignment.f90 (+1-1) 
- (modified) flang/test/Lower/forall/scalar-substring.f90 (+1-1) 
- (modified) flang/test/Lower/structure-constructors-alloc-comp.f90 (+3-3) 
- (modified) flang/test/Lower/unsigned-ops.f90 (+4-4) 
- (modified) flang/test/Lower/volatile-derived-type.f90 (+1-1) 
- (modified) flang/test/Lower/volatile-string.f90 (+2-2) 
- (modified) flang/test/Lower/volatile3.f90 (+6-6) 
- (modified) flang/test/Transforms/debug-dummy-argument.fir (+1-1) 
- (modified) flang/test/Transforms/debug-local-var.fir (+6-6) 
- (modified) flang/unittests/Optimizer/FortranVariableTest.cpp (+8-4) 


``````````diff
diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h
index f8322a50effc4..2031f3845509c 100644
--- a/flang/include/flang/Lower/AbstractConverter.h
+++ b/flang/include/flang/Lower/AbstractConverter.h
@@ -271,6 +271,12 @@ class AbstractConverter {
   virtual bool
   isRegisteredDummySymbol(Fortran::semantics::SymbolRef symRef) const = 0;
 
+  /// Get the source-level argument position (1-based) for a dummy symbol.
+  /// Returns 0 if the symbol is not a registered dummy or position is unknown.
+  /// Can only be used reliably during the instantiation of variables.
+  virtual unsigned
+  getDummyArgPosition(const Fortran::semantics::Symbol &sym) const = 0;
+
   /// Returns the FunctionLikeUnit being lowered, if any.
   virtual const Fortran::lower::pft::FunctionLikeUnit *
   getCurrentFunctionUnit() const = 0;
diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index 891373e8dbb0a..9933e3ed6c308 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -233,7 +233,7 @@ genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
            fir::FortranVariableFlagsAttr flags,
            mlir::Value dummyScope = nullptr, mlir::Value storage = nullptr,
            std::uint64_t storageOffset = 0,
-           cuf::DataAttributeAttr dataAttr = {});
+           cuf::DataAttributeAttr dataAttr = {}, unsigned dummyArgNo = 0);
 
 /// Generate an hlfir.associate to build a variable from an expression value.
 /// The type of the variable must be provided so that scalar logicals are
diff --git a/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td b/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td
index 04f839386498c..b29228eed1591 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRCG/CGOps.td
@@ -229,12 +229,13 @@ def fircg_XDeclareOp : fircg_Op<"ext_declare", [AttrSizedOperandSegments]> {
 
   let arguments = (ins AnyRefOrBox:$memref, Variadic<AnyIntegerType>:$shape,
       Variadic<AnyIntegerType>:$shift, Variadic<AnyIntegerType>:$typeparams,
-      Optional<fir_DummyScopeType>:$dummy_scope, Builtin_StringAttr:$uniq_name);
+      Optional<fir_DummyScopeType>:$dummy_scope, Builtin_StringAttr:$uniq_name,
+      OptionalAttr<UI32Attr>:$dummy_arg_no);
   let results = (outs AnyRefOrBox);
 
   let assemblyFormat = [{
     $memref (`(` $shape^ `)`)? (`origin` $shift^)? (`typeparams` $typeparams^)?
-    (`dummy_scope` $dummy_scope^)?
+    (`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
     attr-dict `:` functional-type(operands, results)
   }];
 
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index bae52d63fda45..da5f7da2f4229 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -3274,13 +3274,14 @@ def fir_DeclareOp
       DefaultValuedAttr<UI64Attr, "0">:$storage_offset,
       Builtin_StringAttr:$uniq_name,
       OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs,
-      OptionalAttr<cuf_DataAttributeAttr>:$data_attr);
+      OptionalAttr<cuf_DataAttributeAttr>:$data_attr,
+      OptionalAttr<UI32Attr>:$dummy_arg_no);
 
   let results = (outs AnyRefOrBox);
 
   let assemblyFormat = [{
     $memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)?
-    (`dummy_scope` $dummy_scope^)?
+    (`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
     (`storage` `(` $storage^ `[` $storage_offset `]` `)`)?
     attr-dict `:` functional-type(operands, results)
   }];
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index b7563a2f752f0..73f6be604a55c 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -103,13 +103,13 @@ def hlfir_DeclareOp
       Builtin_StringAttr:$uniq_name,
       OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs,
       OptionalAttr<cuf_DataAttributeAttr>:$data_attr,
-      OptionalAttr<UnitAttr>:$skip_rebox);
+      OptionalAttr<UnitAttr>:$skip_rebox, OptionalAttr<UI32Attr>:$dummy_arg_no);
 
   let results = (outs AnyFortranVariable, AnyRefOrBoxLike);
 
   let assemblyFormat = [{
     $memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)?
-    (`dummy_scope` $dummy_scope^)?
+    (`dummy_scope` $dummy_scope^ (`arg` $dummy_arg_no^)?)?
     (`storage` `(` $storage^ `[` $storage_offset `]` `)`)?
     (`skip_rebox` $skip_rebox^)?
     attr-dict `:` functional-type(operands, results)
@@ -122,7 +122,8 @@ def hlfir_DeclareOp
       CArg<"mlir::Value", "{}">:$storage,
       CArg<"std::uint64_t", "0">:$storage_offset,
       CArg<"fir::FortranVariableFlagsAttr", "{}">:$fortran_attrs,
-      CArg<"cuf::DataAttributeAttr", "{}">:$data_attr)>];
+      CArg<"cuf::DataAttributeAttr", "{}">:$data_attr,
+      CArg<"unsigned", "0">:$dummy_arg_no)>];
 
   let extraClassDeclaration = [{
     /// Get the variable original base (same as input). It lacks
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5779bcd5d293c..364471eaf9df5 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -1129,6 +1129,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     return registeredDummySymbols.contains(sym);
   }
 
+  unsigned getDummyArgPosition(
+      const Fortran::semantics::Symbol &sym) const override final {
+    auto it = dummyArgPositions.find(&sym);
+    return (it != dummyArgPositions.end()) ? it->second : 0;
+  }
+
   const Fortran::lower::pft::FunctionLikeUnit *
   getCurrentFunctionUnit() const override final {
     return currentFunctionUnit;
@@ -1413,11 +1419,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   /// definitive mapping. The specification expression have not been lowered
   /// yet. The final mapping will be done using this pre-mapping in
   /// Fortran::lower::mapSymbolAttributes.
+  /// \param argNo The 1-based source position of this argument (0 if
+  /// unknown/result)
   bool mapBlockArgToDummyOrResult(const Fortran::semantics::SymbolRef sym,
-                                  mlir::Value val, bool isResult) {
+                                  mlir::Value val, bool isResult,
+                                  unsigned argNo = 0) {
     localSymbols.addSymbol(sym, val);
     if (!isResult)
-      registerDummySymbol(sym);
+      registerDummySymbol(sym, argNo);
 
     return true;
   }
@@ -5962,7 +5971,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
                             const Fortran::lower::CalleeInterface &callee) {
     assert(builder && "require a builder object at this point");
     using PassBy = Fortran::lower::CalleeInterface::PassEntityBy;
+
+    // Track the source-level argument position (1-based)
+    unsigned argPosition = 0;
+
     auto mapPassedEntity = [&](const auto arg, bool isResult = false) {
+      // Count only actual source-level dummy arguments (not results or
+      // host assoc tuples)
+      if (!isResult && arg.entity.has_value())
+        argPosition++;
+
       if (arg.passBy == PassBy::AddressAndLength) {
         if (callee.characterize().IsBindC())
           return;
@@ -5973,11 +5991,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         mlir::Value casted =
             builder->createVolatileCast(loc, false, arg.firArgument);
         mlir::Value box = charHelp.createEmboxChar(casted, arg.firLength);
-        mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult);
+        mapBlockArgToDummyOrResult(arg.entity->get(), box, isResult,
+                                   isResult ? 0 : argPosition);
       } else {
         if (arg.entity.has_value()) {
           mapBlockArgToDummyOrResult(arg.entity->get(), arg.firArgument,
-                                     isResult);
+                                     isResult, isResult ? 0 : argPosition);
         } else {
           assert(funit.parentHasTupleHostAssoc() && "expect tuple argument");
         }
@@ -6835,13 +6854,22 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   }
 
   /// Record the given symbol as a dummy argument of this function.
-  void registerDummySymbol(Fortran::semantics::SymbolRef symRef) {
+  /// \param symRef The symbol representing the dummy argument
+  /// \param argNo The 1-based position of this argument in the source (0 =
+  /// unknown)
+  void registerDummySymbol(Fortran::semantics::SymbolRef symRef,
+                           unsigned argNo = 0) {
     auto *sym = &*symRef;
     registeredDummySymbols.insert(sym);
+    if (argNo > 0)
+      dummyArgPositions[sym] = argNo;
   }
 
   /// Reset all registered dummy symbols.
-  void resetRegisteredDummySymbols() { registeredDummySymbols.clear(); }
+  void resetRegisteredDummySymbols() {
+    registeredDummySymbols.clear();
+    dummyArgPositions.clear();
+  }
 
   void setCurrentFunctionUnit(Fortran::lower::pft::FunctionLikeUnit *unit) {
     currentFunctionUnit = unit;
@@ -6883,6 +6911,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
   llvm::SmallPtrSet<const Fortran::semantics::Symbol *, 16>
       registeredDummySymbols;
 
+  /// Map from dummy symbols to their 1-based argument positions.
+  /// Used to generate debug info with correct argument numbers.
+  llvm::DenseMap<const Fortran::semantics::Symbol *, unsigned>
+      dummyArgPositions;
+
   /// A map of unique names for constant expressions.
   /// The names are used for representing the constant expressions
   /// with global constant initialized objects.
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 2517ab35d4ff0..53d4d7566acfa 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1946,12 +1946,15 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
       return;
     }
     mlir::Value dummyScope;
-    if (converter.isRegisteredDummySymbol(sym))
+    unsigned argNo = 0;
+    if (converter.isRegisteredDummySymbol(sym)) {
       dummyScope = converter.dummyArgsScopeValue();
+      argNo = converter.getDummyArgPosition(sym);
+    }
     auto [storage, storageOffset] = converter.getSymbolStorage(sym);
     auto newBase = hlfir::DeclareOp::create(
         builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage,
-        storageOffset, attributes, dataAttr);
+        storageOffset, attributes, dataAttr, argNo);
     symMap.addVariableDefinition(sym, newBase, force);
     return;
   }
@@ -2004,15 +2007,17 @@ void Fortran::lower::genDeclareSymbol(
                                                         sym.GetUltimate());
     auto name = converter.mangleName(sym);
     mlir::Value dummyScope;
+    unsigned argNo = 0;
     fir::ExtendedValue base = exv;
     if (converter.isRegisteredDummySymbol(sym)) {
       base = genPackArray(converter, sym, exv);
       dummyScope = converter.dummyArgsScopeValue();
+      argNo = converter.getDummyArgPosition(sym);
     }
     auto [storage, storageOffset] = converter.getSymbolStorage(sym);
     hlfir::EntityWithAttributes declare =
         hlfir::genDeclare(loc, builder, base, name, attributes, dummyScope,
-                          storage, storageOffset, dataAttr);
+                          storage, storageOffset, dataAttr, argNo);
     symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force);
     return;
   }
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 5da27d1713825..6ef6074cf73ad 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -427,7 +427,8 @@ mlir::Value fir::FirOpBuilder::genTempDeclareOp(
       builder, loc, memref.getType(), memref, shape, typeParams,
       /*dummy_scope=*/nullptr,
       /*storage=*/nullptr,
-      /*storage_offset=*/0, nameAttr, fortranAttrs, cuf::DataAttributeAttr{});
+      /*storage_offset=*/0, nameAttr, fortranAttrs, cuf::DataAttributeAttr{},
+      /*dummy_arg_no=*/mlir::IntegerAttr{});
 }
 
 mlir::Value fir::FirOpBuilder::genStackSave(mlir::Location loc) {
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 793be32400db6..b435ae15cff58 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -250,7 +250,7 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
                   const fir::ExtendedValue &exv, llvm::StringRef name,
                   fir::FortranVariableFlagsAttr flags, mlir::Value dummyScope,
                   mlir::Value storage, std::uint64_t storageOffset,
-                  cuf::DataAttributeAttr dataAttr) {
+                  cuf::DataAttributeAttr dataAttr, unsigned dummyArgNo) {
 
   mlir::Value base = fir::getBase(exv);
   assert(fir::conformsWithPassByRef(base.getType()) &&
@@ -281,7 +281,7 @@ hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
       [](const auto &) {});
   auto declareOp = hlfir::DeclareOp::create(
       builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage,
-      storageOffset, flags, dataAttr);
+      storageOffset, flags, dataAttr, dummyArgNo);
   return mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation());
 }
 
diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp
index 1b1d43c11c707..bafeb32660e6c 100644
--- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp
+++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp
@@ -302,11 +302,15 @@ class DeclareOpConversion : public mlir::OpRewritePattern<fir::DeclareOp> {
       else
         return mlir::failure();
     }
+    // Extract dummy_arg_no attribute if present
+    mlir::IntegerAttr dummyArgNoAttr;
+    if (auto attr = declareOp->getAttrOfType<mlir::IntegerAttr>("dummy_arg_no"))
+      dummyArgNoAttr = attr;
     // FIXME: Add FortranAttrs and CudaAttrs
     auto xDeclOp = fir::cg::XDeclareOp::create(
         rewriter, loc, declareOp.getType(), declareOp.getMemref(), shapeOpers,
         shiftOpers, declareOp.getTypeparams(), declareOp.getDummyScope(),
-        declareOp.getUniqName());
+        declareOp.getUniqName(), dummyArgNoAttr);
     LLVM_DEBUG(llvm::dbgs()
                << "rewriting " << declareOp << " to " << xDeclOp << '\n');
     rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults());
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 1332dc57fb086..8d6b888789c15 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -261,14 +261,12 @@ updateDeclaredInputTypeWithVolatility(mlir::Type inputType, mlir::Value memref,
   return std::make_pair(inputType, memref);
 }
 
-void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
-                             mlir::OperationState &result, mlir::Value memref,
-                             llvm::StringRef uniq_name, mlir::Value shape,
-                             mlir::ValueRange typeparams,
-                             mlir::Value dummy_scope, mlir::Value storage,
-                             std::uint64_t storage_offset,
-                             fir::FortranVariableFlagsAttr fortran_attrs,
-                             cuf::DataAttributeAttr data_attr) {
+void hlfir::DeclareOp::build(
+    mlir::OpBuilder &builder, mlir::OperationState &result, mlir::Value memref,
+    llvm::StringRef uniq_name, mlir::Value shape, mlir::ValueRange typeparams,
+    mlir::Value dummy_scope, mlir::Value storage, std::uint64_t storage_offset,
+    fir::FortranVariableFlagsAttr fortran_attrs,
+    cuf::DataAttributeAttr data_attr, unsigned dummy_arg_no) {
   auto nameAttr = builder.getStringAttr(uniq_name);
   mlir::Type inputType = memref.getType();
   bool hasExplicitLbs = hasExplicitLowerBounds(shape);
@@ -279,9 +277,12 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
   }
   auto [hlfirVariableType, firVarType] =
       getDeclareOutputTypes(inputType, hasExplicitLbs);
+  mlir::IntegerAttr argNoAttr;
+  if (dummy_arg_no > 0)
+    argNoAttr = builder.getUI32IntegerAttr(dummy_arg_no);
   build(builder, result, {hlfirVariableType, firVarType}, memref, shape,
         typeparams, dummy_scope, storage, storage_offset, nameAttr,
-        fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{});
+        fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{}, argNoAttr);
 }
 
 llvm::LogicalResult hlfir::DeclareOp::verify() {
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index 6a57bf2ae6fec..4c3f37bdead3f 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -308,7 +308,8 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
         declareOp.getTypeparams(), declareOp.getDummyScope(),
         /*storage=*/declareOp.getStorage(),
         /*storage_offset=*/declareOp.getStorageOffset(),
-        declareOp.getUniqName(), fortranAttrs, dataAttr);
+        declareOp.getUniqName(), fortranAttrs, dataAttr,
+        declareOp.getDummyArgNoAttr());
 
     // Propagate other attributes from hlfir.declare to fir.declare.
     // OpenACC's acc.declare is one example. Right now, the propagation
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index e006d2e878fd8..00633b4104b6c 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -228,24 +228,11 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
     }
   }
 
-  // FIXME: There may be cases where an argument is processed a bit before
-  // DeclareOp is generated. In that case, DeclareOp may point to an
-  // intermediate op and not to BlockArgument.
-  // Moreover, with MLIR inlining we cannot use the BlockArgument
-  // position to identify the original number of the dummy argument.
-  // If we want to keep running AddDebugInfoPass late, the dummy argument
-  // position in the argument list has to be expressed in FIR (e.g. as a
-  // constant attribute of [hl]fir.declare/fircg.ext_declare operation that has
-  // a dummy_scope operand).
+  // Get the dummy argument position from the explicit attribute.
   unsigned argNo = 0;
   if (declOp.getDummyScope()) {
-    if (auto arg = llvm::dyn_cast<mlir::BlockArgument>(declOp.getMemref())) {
-      // Check if it is the BlockArgument of the function's entry block.
-      if (auto funcLikeOp =
-              declOp->getParentOfType<mlir::FunctionOpInterface>())
-        if (arg.getOwner() == &funcLikeOp.front())
-          argNo = arg.getArgNumber() + 1;
-    }
+    if (auto argNoOpt = declOp.getDummyArgNo())
+      argNo = *argNoOpt;
   }
 
   auto tyAttr = typeGen.convertType(fir::unwrapRefType(declOp.getType()),
diff --git a/flang/test/Fir/dispatch.f90 b/flang/test/Fir/dispatch.f90
index 2b1ae225986ca..9219e5453c779 100644
--- a/flang/test/Fir/dispatch.f90
+++ b/flang/test/Fir/dispatch.f90
@@ -195,7 +195,7 @@ program test_type_to_class
 
 ! CHECK-LABEL: func.func @_QMdispatch1Pdisplay_class(
 ! CHECK-SAME: %[[ARG:.*]]: [[CLASS:!fir.class<.*>>]]
-! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMdispatch1Fdisplay_classEp"} : (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>)
+! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QMdispatch1Fdisplay_classEp"} : (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.dscope) -> (!fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>, !fir.class<!fir.type<_QMdispatch1Tp1{a:i32,b:i32}>>)
 
 ! Check dynamic dispatch equal to `call p%display2()` with binding index = 2.
 ! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG_DECL]]#0 : ([[CLASS]]) -> !fir.tdesc<none>
diff --git a/flang/test/HLFIR/assumed-type-actual-args.f90 b/flang/test/HLFIR/assumed-type-actual-args.f90
index aaac98...
[truncated]

``````````

</details>


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


More information about the flang-commits mailing list