Silverfrost Forums

Welcome to our forums

Failure to detect error in source code

22 Sep 2018 1:19 #22560

The program below contains one error: line-22 has chainp(b) instead of chainp(b:b). The bug is not difficult to diagnose at compile time, as Gfortran and NAG do.

FTN95 /64 /checkmate produces an EXE that crashes with an access violation when run. FTN95 /checkmate produces a 32-bit EXE that crashes with 'Attempt to execute privileged instruction'. FTN95 /opt leads to '...attempted to write to location 00000001'. In other words, the bug is not caught at compile or run time, even with /checkmate.

The test program is a modification of an earlier submission by user 'Sparge' in 2011, see https://forums.silverfrost.com/Forum/Topic/1689&highlight=attempted+access+location .

program strung_out
   implicit none
   integer, parameter :: nb = 3

   character (len = nb) chintz, chance
   chintz = 'xyz'
   call charcoal (chance, chintz)
   print *,chance
   stop

   contains

   subroutine charcoal (champ, chimp)
      character (len = nb) champ, chimp
      champ = chaout (chimp)
   end subroutine charcoal

   character (len = nb) function chaout (chainp)
      character (len = nb) chainp
      integer b, inp (nb)
      do b = 1, nb
         inp (b) = ichar (chainp (b))    ! ***ERROR***
!         inp (b) = ichar (chainp (b:b))   ! ***CORRECT***
      end do
      chaout = char (inp (2)) // char (inp (3)) // char (inp (1))
   end function chaout
end program strung_out
23 Sep 2018 5:39 #22561

Thank you for the feedback. I will make a note of this.

27 Sep 2018 1:17 #22575

I have had a look at this and the basic problem is that chaout is called before it has been defined. So without multiple passes through the code, the compiler thinks that chainp could be a function returning a character variable. Maybe the compiler ought to be using multiple passes at this point - I would have to look that up.

As it is, in this context FTN95 requires the order of the CONTAINed subprograms to be changed (so that chaout is called after it has been defined) before you get a clear error report at compile time. With the given order, you are only alerted to an error when you get an access violation at run time.

27 Sep 2018 2:18 #22576

One of the great advantages of having several compilers available for use is that the same source code can be run through each to find problems picked up by one that another misses.

27 Sep 2018 2:51 #22577

Quoted from PaulLaidler I have had a look at this and the basic problem is that chaout is called before it has been defined. So without multiple passes through the code, the compiler thinks that chainp could be a function returning a character variable. Maybe the compiler ought to be using multiple passes at this point - I would have to look that up.

Section 12.3.2 of the Fortran 95 Standard contains this note:

NOTE 12.3 An interface block cannot be used to describe the interface of an internal procedure, a module procedure, or an intrinsic procedure because the interfaces of such procedures are already explicit.

CHAOUT and CHARCOAL are internal procedures contained in the same module. The compiler has to make at least two passes when it compiles modules with contained procedures, although in the first pass it only needs to do just enough to gather the correct interfaces.

27 Sep 2018 4:02 #22578

mecej4

I think that you are probably right. I know that FTN95 does do multiply passes but apparently not adequately in this context.

Until we can get this fixed it will be necessary to make it easier for the compiler by using the ordering that does not need the double pass. To me this is more natural to define a thing before it is used.

27 Sep 2018 9:13 #22579

Suppose then that the order of the two functions is reversed. What effect does that have:

program strung_out implicit none integer, parameter :: nb = 3

character (len = nb) chintz, chance chintz = 'xyz' call charcoal (chance, chintz) print *,chance stop

contains

character (len = nb) function chaout (chainp) character (len = nb) chainp integer b, inp (nb) do b = 1, nb inp (b) = ichar (chainp (b)) ! ERROR ! inp (b) = ichar (chainp (b:b)) ! CORRECT end do chaout = char (inp (2)) // char (inp (3)) // char (inp (1)) end function chaout

subroutine charcoal (champ, chimp) character (len = nb) champ, chimp champ = chaout (chimp) end subroutine charcoal

end program strung_out

What then? Even stranger, although the error occurs during compilation:

[FTN95/Win32 Ver. 8.30.0 Copyright (c) Silverfrost Ltd 1993-2018] NO ERRORS [<CHAOUT> FTN95 v8.30.0] 0025) champ = chaout (chimp) *** In the INTERFACE to CHAOUT, the first dummy argument (CHAINP) was of type CHARACTER(LEN=3) FUNCTION, whereas the actual argument is of type CHARACTER(LEN=3) 1 ERROR [<CHARCOAL> FTN95 v8.30.0] NO ERRORS [<STRUNG_OUT> FTN95 v8.30.0] *** Compilation failed

What's that about CHAINP being a FUNCTION?

10 Oct 2018 11:43 #22641

Sorry, Eddie, until now I had overlooked your example with the subroutines rearranged. In this case, however, what the compiler says is proper, although it may be a bit difficult to understand what (and why) it said. Given your code, Gfortran says

spargeddie.f90:25:16:

 champ = chaout (chimp)
                1
Error: Expected a procedure for argument 'chainp' at (1)

The explanation is as follows.

Let us look at the code of FUNCTION CHAOUT, which is a contained procedure and, therefore, has an explicit interface available across the entire program. The argument, 'chainp', is declared as a **scalar **character variable (of length nb). When the compiler sees 'chainp(b)', it has to recognise that as a function reference. What is given within the parentheses is not a valid substring index pair. Therefore, it must be an argument list with one member.

Note that the type of the dummy argument is detected only after the executable statement inside the DO loop is parsed. This feature is part of our legacy from Fortran 77 and earlier.

My complaint, then, is that the compiler should have given the same error even when the block of code for function CHAOUT was placed earlier (or elsewhere) in the source file.

10 Oct 2018 1:58 #22643

Hi Mecej4,

It was really in response to Paul about the order.

This sort of coding lies far outside my personal safe subset of Fortran.

Thanks for the explanation.

Eddie

17 Jul 2019 6:39 #24021

This has now been fixed for the next release of FTN95. FTN95 will provide the correct error report at compile time.

Please login to reply.