Wildcat
Wildcat

Reputation: 8870

A portable way to suppress an "unused dummy argument" warning in Fortran

Is there any portable way to suppress an "unused dummy argument" warning in Fortran for a specific variable similar to the (void)var; trick in C/C++?


A motivational example (by a request from Vladimir F). The strategy pattern, GoF example with different line-breaking strategies, unnecessary details omitted.

module linebreaking

  type, abstract :: linebreaking_compositor
  contains
    procedure(linebreaking_compositor_compose), deferred, pass(this) :: compose
  end type

  abstract interface
    subroutine linebreaking_compositor_compose(this)
      import linebreaking_compositor
      class(linebreaking_compositor), intent(in) :: this       
    end subroutine linebreaking_compositor_compose
  end interface

  type, extends(linebreaking_compositor) :: linebreaking_simple_compositor
  contains
    procedure, pass(this) :: compose => linebreaking_simple_compositor_compose
  end type linebreaking_simple_compositor

  type, extends(linebreaking_compositor) :: linebreaking_tex_compositor
  contains
    procedure, pass(this) :: compose => linebreaking_tex_compositor_compose
  end type linebreaking_tex_compositor

  type, extends(linebreaking_compositor) :: linebreaking_array_compositor
  private
    integer :: interval
  contains
    procedure, pass(this) :: compose => linebreaking_array_compositor_compose
  end type linebreaking_array_compositor

contains

  subroutine linebreaking_simple_compositor_compose(this)
    class(linebreaking_simple_compositor), intent(in) :: this
    print *, "Composing using a simple compositor."
  end subroutine linebreaking_simple_compositor_compose

  subroutine linebreaking_tex_compositor_compose(this)
    class(linebreaking_tex_compositor), intent(in) :: this
    print *, "Composing using a TeX compositor."
  end subroutine linebreaking_tex_compositor_compose

  subroutine linebreaking_array_compositor_compose(this)
    class(linebreaking_array_compositor), intent(in) :: this
    print *, "Composing using an array compositor with interval", this%interval, "."
  end subroutine linebreaking_array_compositor_compose

end module linebreaking

As you can see the passed-object dummy argument this is required in compose method of linebreaking_array_compositor, but is not used in the same method of two other compositors. GFortran complains about this not being used, and I don't want to complicate the build process by having specific rules (like -Wno-unused-dummy-argument) for specific files.

Upvotes: 3

Views: 2776

Answers (3)

Tom Clune
Tom Clune

Reputation: 19

What I have been using without issue for some time is a macro:

#define _UNUSED_DUMMY(x) if (.false.) print*,shape(x)

Upvotes: 1

IanH
IanH

Reputation: 21431

I have no entirely satisfactory solution to the problem.

Care needs to be take with whatever simple source construct gets used that it doesn't inadvertently turn conforming code with an unused dummy argument into non-conforming code. My experience has been that it is easy to get this wrong, be careful that the cost of the cure does not exceed the cost of the disease. More often than not these days, I just ignore the warning in the compiler's output.

(From my perspective, use of the preprocessor comes with a cost far greater than that of the actual warning - in that the code is no longer standard conforming.)

For non-pointer, non-allocatable, non-optional, INTENT(IN)-like dummy arguments of numeric intrinsic type that I know will be defined I use a pattern such as IF (arg /= 0) CONTINUE. Eliminate the comparison for LOGICAL, use LEN(arg) /= 0 for CHARACTER.

For non-pointer, non-allocatable, non-optional, intent(in) dummy arguments of derived type, the conditional expression has to be specific to the derived type - perhaps there is a convenient non-allocatable, non-pointer component of intrinsic type that can be tested. In some cases I have explicitly added such a component to a derived type that might otherwise be empty.

For optional dummy arguments, test the presence of the argument. For pointer dummy arguments that are known to have defined association status, test the association status. For allocatable arguments, test the allocation status.

In all the cases above the use of CONTINUE as the action statement for an IF statement is easy enough to identify in source by a reader or some sort of text search pattern. When compiling with optimisation enabled, a reasonable optimising compiler is likely to completely eliminate this otherwise pointless test.

Failure to define an INTENT(OUT)-like argument plausibly suggests a programming error, if not, and the actual argument is known to always be definable (!) - just define the argument, perhaps with a dummy value. Similarly, the situation where the definition status of an argument (or the pointer association status of a pointer argument) may be undefined also suggests a latent coding/code design issue - define the relevant actual argument (perhaps will a dummy value) prior to the call.

Upvotes: 4

roygvib
roygvib

Reputation: 7395

To disable the warning about some selected, unused dummy argument, we probably need to do some "no operation" thing (e.g. dummy assignment, IF tests, getting the address, etc). As one such approach, how about defining a macro like

#define nop(x) associate( x => x ); end associate

and using this as

  subroutine linebreaking_simple_compositor_compose(this)
    class(linebreaking_simple_compositor), intent(in) :: this
    nop( this )
    print *, "Composing using a simple compositor."
  end subroutine linebreaking_simple_compositor_compose

On my computer, ifort-14 and gfortran >=4.8 accepted this usage, giving no warning with -warn or -Wall. On the other hand, Sun fortran 8.7 did not accept this because there is no ASSOCIATE support yet... (I really hope it will support the latter!)

A small test code is attached below:

module mymod
    implicit none
    type T
        integer :: n
    endtype
contains
    subroutine mysub( this )
        class(T) :: this
        nop( this )
    endsubroutine

    subroutine mysub2( ptr )
        type(T), pointer :: ptr
        nop( ptr )
    endsubroutine
end

program main
    use mymod
    type(T) :: a
    type(T), pointer :: p
    call mysub( a )
    call mysub2( p )
endprogram

Upvotes: 5

Related Questions