Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of optional arguments that aren't present #222

Open
LiamPattinson opened this issue Dec 11, 2024 · 4 comments
Open

Use of optional arguments that aren't present #222

LiamPattinson opened this issue Dec 11, 2024 · 4 comments
Labels
rule A new rule for the linter

Comments

@LiamPattinson
Copy link
Collaborator

The following compiles without issue with gfortran and seg-faults if x is not present:

integer function f(x) result(y)
  integer, intent(in), optional :: x

  y = x + 1

end function f

It should be something like:

integer function f(x) result(y)
  integer, intent(in), optional :: x

  if(present(x)) then
    y = x + 1
  else
    y = 1  ! default
  end if

end function f

The rule would have to catch instances of optional dummy arguments appearing outside of if statements containing present.

It could be tricky to catch every possibility without false positives, as the following works just fine:

  integer function f(x) result(y)
    integer, value, optional :: x

    if(.not. present(x)) x = 0
    y = x + 1

  end function f

It would also need to ensure the condition in the if statement can only be true if present(x) is true, as this also compiles just fine and seg-faults at run time:

integer function f(x) result(y)
  integer, intent(in), optional :: x

  if (present(x) .or. .true.) then
    y = x + 1
  else
    y = 1
  end if

end function f
@LiamPattinson LiamPattinson added the rule A new rule for the linter label Dec 11, 2024
@ZedThree
Copy link
Member

This is another one that's quite tricky, because the code might just be passing the argument off to another one with an optional argument:

subroutine foo(x)
  integer, intent(in), optional :: x
  call bar(1, x)
end subroutine foo

subroutine bar(a, b)
  integer, intent(in), optional :: a, b
end subroutine bar

The trick with value is neat, I'm not sure I've seen that before!

@ZedThree
Copy link
Member

The trick with value is actually a gfortran bug, and not something to actually be used

@LiamPattinson
Copy link
Collaborator Author

🙄 And here I thought I'd found a nice workaround to the usual method of:

if (present(x)) then
  x_but_not_optional = x
else
  x_but_not_optional = 0
end if

I always found this to be really clunky.

@ZedThree
Copy link
Member

F23 introduces ternaries, so you'll be able to have:

x_but_not_optional = present(x) ? x : 0

No compilers actually support this yet, of course.

I'm also disappointed they didn't go for Python style:

x_but_not_optional = x if present(x) else 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rule A new rule for the linter
Projects
None yet
Development

No branches or pull requests

2 participants