Silverfrost Forums

Welcome to our forums

Run time check for modification of agument expression

2 Jan 2012 5:52 #9433

Checkmate (/CHECK and /CHECKMATE) should generate a run time error when an attempt is made to modify a dummy argument when the corresponding actual argument is an expression.

I find this does not work for module procedures, but does work for external procedures. In the following code, suba is inside a module, subb is an external procedure. No runtime error occurs when suba is called, but the correct error occurs when subb is called.

Moreover, I have found that the following calls, which also have simple expressions for arguments (being parenthesised variables) are not detected at all!

call suba((k)) call subb((k))

Perhaps these inconsistencies could be addressed in some future revision.

I'm still using 6.10 here.

module foo
contains

   subroutine suba(i)
      print *, i
      i = 6 !< Should get a run-time error here. But I don't!
   end subroutine suba

end module foo

!********************************

subroutine subb(i)
   print *, i
   i = 6 !< Should get a run-time error here. And I do!
end subroutine subb

!********************************

program anon
   use foo
   
   integer :: k
   
   k = 5
   call suba(k*10)
   print *, k

   k = 5
   call subb(k*10)
   print *, k
   
end program anon
3 Jan 2012 11:25 #9434

I have made a note of this for further investigation.

4 Jan 2012 7:07 (Edited: 16 Feb 2012 8:41) #9435

Thanks for looking at this.

This problem also arises in the following 'code 1'.

The argument a is changed on exit from subroutine bar even though it has the INTENT(IN) attribute! No run time error occurs and a has the value 2.0 on exit from bar.

! Code 1
module foo
contains
   subroutine bar(a)
      real, intent(in) :: a
      call mar(a)
   end subroutine bar

   subroutine mar(a)
      real :: a
      a = 2.0
   end subroutine mar
end module foo

program anon
   use foo

   real :: a = 1.0
   
   call bar(a)
   
   print *, a  !< Prints the value 2.0
end program anon

However, with the following 'code 2' the correct run-time error (Error 14) occurs.

! Code 2
module foo
contains
   subroutine bar(a)
      real, intent(in) :: a
      call mar(a)
   end subroutine bar
end module foo

subroutine mar(a)
   real :: a
   a = 2.0   !< Run time error occurs here as expected.
end subroutine mar

program anon
   use foo

   real :: a = 1.0
   
   call bar(a)
   
   print *, a
end program anon
15 Feb 2012 5:10 #9615

I have investigated the first problem and find that modules are explicitly excluded from this checking process.

If I allow modules to be checked then I get the right outcome for your sample program but then a significant number of programs in our test suite fail.

It looks like a major task to put everything 'right' so the best I can do is offer a special command line option so that you can experimentally bypass this exclusion. Evidently our test suite demonstrates that the result may be unsafe in ways that I cannot predict.

16 Feb 2012 7:25 #9618

Thank you for investigating Paul. It is most appreciated.

For module procedures, I always use INTENT(IN) which detects this kind of error at compile time. However, the additional assurance of a run-rime check would be useful for codes where INTENT(IN) is not used, or where the module procedure calls another module procedure which does not use INTENT(IN), as in my second example (code 1) above.

It is difficult to see how enabling this run time checking for module procedures would break your test suite unless some of the code in the test suite is not valid. But, of course, this might be the case, and you may not want to make changes to the test suite if the work required is considerable.

However, the errors that such run-time checks can expose may be just the sort of things that it would be useful to expose in your customers fortran codes, especially for codes that contain a mix of module and non-module procedures. Certainly, there can be no valid codes which make changes to constant arguments since this is expressly forbidden by the Fortran Standard, so the inclusion of such checks cannot cause issues on correct code.

Would it be possible to enable this run time check for module procedures when /CHECK is used and simply compile your test suite with the /SUPPRESS_ARG_CHECK option specified?. This would be a much neater solution than an additional command line argument. Customers could use /SUPPRESS_ARG_CHECK if the use of /CHECK 'breaks' their codes.

If this is not possible then an additional command line argument should be implemented (something like /CONST_ARG_CHECK ?).

David.

20 Feb 2012 3:25 #9654

I have revisited this issue and relaxed this limitation when using /check. This means that (in the next release) your initial program above will now fault as expected.

The runtime checking process is not clever enough to handle every type of call to a module subprogram. This are apparent in our test suite in code that is valid but produces a false runtime checking error. Hence the need to relax the limitation rather than remove it altogether.

I am trusting that this change will enhance the checking features but there is an attendant risk of breaking some valid code when /check is used. However, /check should never be used to create executables/dlls for release so this will only impact code under development. If anyone encounters any adverse effects from this change then they can use /check with /inhibit_check 15 in order to revert to the former state of affairs. But remember this will not apply until the next release.

23 Jun 2012 9:20 #10405

These run-time checks are working fine now in version 6.30 with all my tests.

Thanks. 😃

Please login to reply.