Bug 107441 - optional arguments are identified as "present" when missing
Summary: optional arguments are identified as "present" when missing
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 12.2.1
: P3 normal
Target Milestone: 13.0
Assignee: anlauf
URL:
Keywords: wrong-code
: 91196 (view as bug list)
Depends on:
Blocks:
 
Reported: 2022-10-27 17:56 UTC by Karl
Modified: 2023-04-08 18:39 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-10-27 00:00:00


Attachments
Patch (784 bytes, patch)
2022-10-27 20:07 UTC, anlauf
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Karl 2022-10-27 17:56:09 UTC
If the first argument to a function is of type "character" (of any length, from what I can tell, including ":" and "*") and the second parameter is both passed by value and optional, the second argument will be identified as "present" even when absent. The following short program reproduces the problem with gfortran 12.2.1:

program bugdemo

   implicit none
   character :: s
   integer :: t

   s = 'a'
   t = testoptional(s)
   print*, 'testoptional: ', t

contains

   function testoptional(w, x) result(t)

      character, intent(in) :: w
      integer, intent(in), value, optional :: x
      integer :: t

      print*, 'present(x) is ', present(x)
      t = 0

   end function testoptional

end program bugdemo
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

When compiled and run with gfortran 12.2.1, this gives the following output:
 present(x) is  T
 testoptional:            0
[clearly, the first line should have "F" instead of "T"]
Comment 1 anlauf 2022-10-27 18:41:34 UTC
Confirmed.

There is an inconsistency either in the generated code for the caller or
the callee:

integer(kind=4) testoptional (character(kind=1)[1:1] & restrict w, integer(kind=4) x, integer(kind=8) _w, logical(kind=1) _x)

vs.

  t = testoptional (&s, 0, 0, 1);

How does the ABI define the ordering of character length and presence flag?
Comment 2 kargls 2022-10-27 18:52:21 UTC
(In reply to anlauf from comment #1)
> Confirmed.
> 
> There is an inconsistency either in the generated code for the caller or
> the callee:
> 
> integer(kind=4) testoptional (character(kind=1)[1:1] & restrict w,
> integer(kind=4) x, integer(kind=8) _w, logical(kind=1) _x)
> 
> vs.
> 
>   t = testoptional (&s, 0, 0, 1);
> 
> How does the ABI define the ordering of character length and presence flag?

Yep, there's an API issue.  If you use

   character(len=13) :: s

the produced code is

     t = testoptional (&s, 0, 0, 13);

so the hidden charlen is tacked on last whereas I think the hidden presence argument is also expected to be last.  Likely a counting error in generating the interface.
Comment 3 anlauf 2022-10-27 19:20:59 UTC
(In reply to kargl from comment #2)
> so the hidden charlen is tacked on last whereas I think the hidden presence
> argument is also expected to be last.  Likely a counting error in generating
> the interface.

I've found the code generating the function call in gfc_conv_procedure_call
(trans-expr.cc:7680)

  /* Add the return arguments.  */
  vec_safe_splice (retargs, arglist);

  /* Add the hidden present status for optional+value to the arguments.  */
  vec_safe_splice (retargs, optionalargs);

  /* Add the hidden string length parameters to the arguments.  */
  vec_safe_splice (retargs, stringargs);

  /* We may want to append extra arguments here.  This is used e.g. for
     calls to libgfortran_matmul_??, which need extra information.  */
  vec_safe_splice (retargs, append_args);


We now need the corresponding part on the procedure side.
Comment 4 anlauf 2022-10-27 19:42:45 UTC
(In reply to anlauf from comment #3)
> We now need the corresponding part on the procedure side.

That might be create_function_arglist (trans-decl.cc).
There's currently a single hidden_arglist, which needs
to be aligned to the caller's side.

Is there a public documentation what the ordering should be?
Comment 5 anlauf 2022-10-27 19:49:38 UTC
(In reply to anlauf from comment #4)
> Is there a public documentation what the ordering should be?

It is actually documented for gfortran:

https://gcc.gnu.org/onlinedocs/gfortran/Argument-passing-conventions.html

The arguments are passed in the following order

* Result variable, when the function result is passed by reference
* Character length of the function result, if it is a of type CHARACTER and no C binding is used
* The arguments in the order in which they appear in the Fortran declaration
* The present status for optional arguments with value attribute, which are internally passed by value
* The character length and/or coarray token and offset for the first argument which is a CHARACTER or a nonallocatable coarray dummy argument, followed by the hidden arguments of the next dummy argument of such a type 

So it is create_function_arglist which is broken.
Comment 6 anlauf 2022-10-27 20:07:36 UTC
Created attachment 53782 [details]
Patch

Regtesting the attached patch.
Comment 7 anlauf 2022-10-27 20:52:38 UTC
(In reply to anlauf from comment #6)
> Created attachment 53782 [details]
> Patch
> 
> Regtesting the attached patch.

Looks good for the reported issue.

However, while working on variations of the testcase, I hit an ICE for:

subroutine test3 (w)
  character, intent(in), value, optional :: w
  print*, 'present(w) is ', present(w)
end subroutine test3

It is not new, though.
Comment 8 anlauf 2022-10-27 21:11:08 UTC
(In reply to anlauf from comment #7)
> However, while working on variations of the testcase, I hit an ICE for:
> 
> subroutine test3 (w)
>   character, intent(in), value, optional :: w
>   print*, 'present(w) is ', present(w)
> end subroutine test3
> 
> It is not new, though.

This is now tracked in PR107444.
Comment 9 Steve Kargl 2022-10-27 21:56:16 UTC
On Thu, Oct 27, 2022 at 09:11:08PM +0000, anlauf at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107441
> 
> --- Comment #8 from anlauf at gcc dot gnu.org ---
> (In reply to anlauf from comment #7)
> > However, while working on variations of the testcase, I hit an ICE for:
> > 
> > subroutine test3 (w)
> >   character, intent(in), value, optional :: w
> >   print*, 'present(w) is ', present(w)
> > end subroutine test3
> > 
> > It is not new, though.
> 
> This is now tracked in PR107444.
> 

If no other issues pop up and if this is an old issue,
you can probably commit your fix for current issue
as you've opened a new bug report.

Thanks for pecking away at gfortran bugs.
Comment 11 GCC Commits 2022-11-09 19:56:16 UTC
The master branch has been updated by Harald Anlauf <anlauf@gcc.gnu.org>:

https://gcc.gnu.org/g:e805adaa283129604a1fb305d0a1cf1e8a90c76e

commit r13-3863-ge805adaa283129604a1fb305d0a1cf1e8a90c76e
Author: Harald Anlauf <anlauf@gmx.de>
Date:   Fri Oct 28 21:58:08 2022 +0200

    Fortran: ordering of hidden procedure arguments [PR107441]
    
    The gfortran ABI specifies the order of given and hidden procedure arguments,
    where the hidden presence status flags of optional+value scalar arguments
    shall come before character length, coarray token and offset.  Respect that.
    
    gcc/fortran/ChangeLog:
    
            PR fortran/107441
            * trans-decl.cc (create_function_arglist): Adjust the ordering of
            automatically generated hidden procedure arguments to match the
            documented ABI for gfortran.
            * trans-types.cc (gfc_get_function_type): Separate hidden parameters
            so that the presence flag for optional+value arguments come before
            string length, coarray token and offset, as required.
    
    gcc/testsuite/ChangeLog:
    
            PR fortran/107441
            * gfortran.dg/coarray/pr107441-caf.f90: New test.
            * gfortran.dg/optional_absent_6.f90: New test.
            * gfortran.dg/optional_absent_7.f90: New test.
Comment 12 anlauf 2022-12-06 18:39:22 UTC
Fixed on mainline for gcc-13.  Closing.

Thanks for the report!
Comment 13 anlauf 2023-04-08 18:39:14 UTC
*** Bug 91196 has been marked as a duplicate of this bug. ***