Silverfrost Forums

Welcome to our forums

Compiler bug: only warning for variable used as Spec. Expr.

7 Jun 2015 1:00 (Edited: 7 Jun 2015 2:25) #16443

FTN95 compiles the following subroutine code with only a warning.

      integer function cbd () 
      character*(MaxLng) text
      cbd = len(text)/2 
      return
      end

The code is in error because the length specifier for the variable 'text' is neither a constant nor a dummy argument. The function is an external function, so there is no question of MaxLng being available by host or USE association.

For the same code, FTN77 says

0002)       character*(MaxLng) text
*** A constant expression must be used in this case
*** A constant expression must be used in this case
0003)       cbd = len(text)/2
*** LEN is an intrinsic function used with invalid argument(s)
     3 ERRORS  [<CBD>FTN77 Ver 4.03]

This compiler bug is at the heart of the rather long and devious discussion in a recent thread, 'Attributes of File', at https://forums.silverfrost.com/Forum/Topic/2746

7 Jun 2015 2:05 #16444

In my simple world, with implicit typing MaxLng is clearly INTEGER (good) but undefined (bad) with no route to define it. This depends on there being a simple scoping rule.

Under modern scoping rules MaxLng as I understand it could have been defined and initialised elsewhere, so surely this is evidence that the syntax check in FTN95 considers only what it finds inside an individual routine?

Eddie

7 Jun 2015 2:45 (Edited: 7 Jun 2015 7:35) #16445

Quoted from LitusSaxonicum Under modern scoping rules MaxLng as I understand it could have been defined and initialised elsewhere, so surely this is evidence that the syntax check in FTN95 considers only what it finds inside an individual routine?

No, and FTN95 could not even be called a Fortran-90 compiler with that limitation. The code given is a complete compilation unit. If the code is modified and augmented to

      module cnsts
      integer, parameter :: MaxLng = 132
      end module
      
      integer function cbd () 
      use cnsts
      character*(MaxLng) text
      cbd = len(text)/2 
      return
      end
      
      program xcbd
      integer cbd
      print *,cbd()
      end program

the modified program prints the correct result, '66'. In this case, there is an 'elsewhere', and the function could not have given the correct result without being given and without using the information in the module.

There is a twist in the modified program. The variable 'text' is undefined, and the compiler issues a corresponding warning. However, the length of 'text' can be deduced without having to know the value of 'text', so no error occurs even if the program is compiled with /UNDEF.

7 Jun 2015 7:07 #16446

You are right and I misunderstood. I now see 'there is no question of MaxLng being available by host or USE association'. It has to be an error not a warning.

The twist is interesting.

7 Jun 2015 9:10 (Edited: 7 Jun 2015 9:41) #16447

A minor issue in a similar context: if ftn95 is used without flags (apart from /LINK), intent(out) clauses are ignored at compilation and at runtime. Nevertheless, a suitable runtime error is displayed if /CHECKMATE is used (a compilation error would be better). If intent(out) is replaced with an equally wrong 'intent(in)', the error is detected in all cases.

program test
real x
x=3
call sub(x)
print*,x ! Shows 5. Thus, sub uses the value in x in spite of intent(out) 
end program

subroutine sub(x)
real,intent(out)::x
x=x+2
end subroutine
7 Jun 2015 9:41 #16448

I have a vague recollection of someone writing that specifying INTENT has the effect of placing restrictions on the programmer rather than the compiler. In fact, the F2008 standard says, in Note 5.17: '...A slightly more sophisticated processor could check to see whether an INTENT (OUT) dummy argument could possibly be referenced before it is defined.'

In your example code, in addition to the INTENT error there is a questionable line of code. Strictly speaking, at entry to a subprogram an INTENT(OUT) variable becomes undefined, so assigning a value to x before the call is wasteful. Some compilers do catch such errors, but usually only if asked to do so.

7 Jun 2015 9:49 (Edited: 7 Jun 2015 10:39) #16449

OK,

On the other hand, a similar intend(in) error is thoroughly catched. Its seems very assymetric.

Note that at entry to my subprogram, the intent(out) variable x does not become undefined (maybe it should). The example has been chosen because I (a beginer in Fortran) was expecting an output x=2, x=undefined or an error message

7 Jun 2015 10:27 #16450

Quoted from AntonioGJerez Note that at entry to my subprogram, the intent(out) variable x does not become undefined (maybe it should).

Here is what the Fortran 95 Standard says in section 5.1.2.3:

'The INTENT (OUT) attribute specifies that the dummy argument shall be defined before a reference to the dummy argument is made within the procedure and any actual argument that becomes associated with such a dummy argument shall be definable. On invocation of the procedure, such a dummy argument becomes undefined except for components of an object of derived type for which default initialization has been specified.'

However, since it takes a lot of extra machine code to make things work as specified in the last sentence of the quotation, few compilers implement the standard literally unless an option such as /CHECKMATE or /UNDEF is specified.

10 Jun 2015 6:08 #16463

With INTENT(OUT) the user has an obligation not to reference the variable unless he/she first defines it. Formally he/she must assume the variable is undefined when the subroutine or function is entered.

If you do reference the variable without first defining it, then you, the programmer, is at fault. In such cases, the compiler (strictly the Fortran Processor) can do anything it wants. With FTN95 and /CHECKMATE the compiler will detect such events at run time (in most cases, there are a few corner cases that don't work properly).

The case of INTENT(IN) is completely different and isn't particularly a symmetric case to INTENT(OUT). INTENT(IN) is used to direct the programmer not to make any change to the variable, or to pass it to another subroutine or function where the dummy argument has the INTENT(IN) or INTENT(INOUT) attribute.

The compiler can usually check at compile time for most cases where the INTENT(IN) attribute is not respected by the programmer. One case where the compiler may not diagnose a programmer's error is when the variable is subsequently passed to an external subroutine or function which does not have an explicit interface where the corresponding dummy argument has the INTENT(OUT) or INTENT(INOUT) attribute.

In all cases, it is up to the programmer to ensure the code complies with the standard (and any extensions provided by Silverfrost). The compiler and run time systems can help but can't enforce compliance in all cases.

Please login to reply.