Silverfrost Forums

Welcome to our forums

Possible bugs when using 2d arrays and interfaces in modules

16 Jul 2007 4:35 #2064

I have a possible bug/bugs that occur with a module containing a 2D array, type conversion, interfaces and the /check compiler option. There is an example at the end of the email showing the various problems (there is more info in the code comments):

  1. If the realVals declaration occurs after the ADT spec the compiler crashes with an access violation in make_new_variable. Actually this occurs even if /check is omitted.

  2. In SetTestType() the use of an int function with a kind parameter on an int-cast 2D array index where an index is a variable(!) causes the compiler to issue 'operand incompatible with opcode' error - if an intermediate integer is used then the problem goes away, or if /check is omitted, or if the array has constant indices

  3. In SetTestType2(), nint produces incorrect values with or without /check (although it's a different incorrect value).

Problems 2 & 3 disappear if their interfaces are removed.

Compiler version is 5.10 and I'm doing a Win32 build.

Alan

! Demonstrate comiler bug with 2D arrays in modules whit /check option and interface module TestMod

! Some values - if this goes after type def compiler crashes, even here the initialisation fails real:: realVals(10,10) = 42.55

type TestType integer*1:: intKind1 end TestType

!real:: realVals(10,10) = 42.55 ! causes a compiler crash if placed here (with or without init)

interface subroutine SetTestType(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx end subroutine SetTestType

subroutine SetTestType2(tt, idx)
  type(TestType), intent(in out):: tt
  integer, intent(in):: idx
end subroutine SetTestType2

end interface

contains

subroutine SetTestType(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx

tt%intKind1 = int(nint(realVals(idx,4)), 1)    ! generates 'operand incompatible with opcode' when realVals is 2D array
                                               ! creating an intermediate integer*4 solves the problem

end subroutine SetTestType

subroutine SetTestType2(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx

tt%intKind1 = nint(realVals(idx,4), 1)         ! this is 52 with /check, 0 without, should be 43 (okay if interface removed)

end subroutine SetTestType2

end module TestMod

winapp use TestMod type(TestType):: newtt

realVals = 42.59 ! init in module doesn't work

call SetTestType(newtt, 3) call SetTestType2(newtt, 4) end

17 Jul 2007 12:06 #2069

These are compiler bugs irrespective of whether the code is valid Fortran.

I will add this to the list of issues to be investigated.

20 Jul 2007 2:11 #2085

There is an error in your code. You need

type TestType integer*1:: intKind1 end type TestType

(on the last line, add the keyword 'type').

We have fixed this in the compiler so that it now reports this error in the program code.

30 Jul 2007 8:43 #2127

Okay that's fine, but this has no effect on the compilation errors which still occur whether or not there is an 'end type' 😦 Does the missing 'type' have any effect on the generated code ?

31 Jul 2007 5:37 #2129

I will try to have another look at this later this week.

With the current release, if you miss out the word 'type' after 'end' then FTN95 produces incorrect assembly code - i.e. it fails or gives incorrect results at runtime.

What it should do is report the omission as a compilation error.

2 Aug 2007 3:20 #2135

I have now rechecked your sample program.

The omission of the keyword 'type' from 'end type' causes a number of errors, all of which appear to be solved by inserting 'type' except for one...

The kind value 1 used in nint (within SetTestType2) does not appear to work in this context (it is omitted in SetTestType where it is applied to int instead).

This kind value is conveniently redundant because you are assigning to an integer*1 anyway. If you leave it out you get the right answer.

Note also that the interface statements are redundant.

3 Aug 2007 9:47 #2138

Paul,

I'm afraid I have no such luck - the only problem fixed by the 'end type' is the crash when initialising the 'realVals' array after the type decl. The 'operand incompatible with opcode' errors are all exactly the same - both in SetTestType and SetTestType2, even when I remove the kind parameter and just use nint, ie: tt%intKind1 = nint(realVals(idx,4))

The only way I can get it to work is to introduce an intermediate 32-bit integer, if I introduce an 8-bit integer it compiles but does not assign any value to the 8-bit int when run, so this works fine:

subroutine SetTestType(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx

integer:: i             ! 32-bit intermediate is okay
i = nint(realVals(idx,4))
tt%intKind1 = i

end subroutine SetTestType

but this compiles but doesn't doesn't actually assign a value to i:

subroutine SetTestType(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx

integer*1:: i       ! 8-bit int, the line below results in i being 'undefined'
i = nint(realVals(idx,4),1)
tt%intKind1 = i

end subroutine SetTestType

and if I omit the ,1 in nint the 'incompatible with opcode' compiler error appears again.

Maybe our compiler options are different ? I only get the error when I have 'checking code' (/check) on, and all other checking options off (if I enable any others my main code doesn't run properly due to the presence of binary data, or other problems with bounds checking of allocatable arrays). Incidentally, with /check off the nint(...,1) above does sets i (incorrectly) to 0 rather than undefined.

I can supply you with my full Visual Studio 2005 project if it helps

Thanks for the info on interfaces - I must admit to being a bit paranoid about them having had lots of problems in the past with optional parameters and things going wrong when, for example, I pass an 8-bit integer in to a 32-bit parameter. However it all seems okay in the test program so I will relax it a bit.

Alan

3 Aug 2007 1:49 #2139

Alan,

I once had a perplexing 'illegal instruction' error problem that manifested on some machines and not others - I can't remember whether it was 'operand incompatible with opcode' or not (though it rings a bell). Anyway, it turns out that there is a compiler switch /P6 (uses some instructions only available on a Pentium 6 or higher) which I was inadvertently using for the app in question - and some of the machines were insufficiently speccy.

So check your project properties carefully for compiler options - this switch can cause problems if your machine is not up to scratch.

Funnily enough, I noticed just the other day that one of my projects had this switch activated for all of the checkmate, debug and release build properties (I use Plato not Visual Studio), and wondered how it got there. I've certainly never applied it myself intentionally. I just created a new project to see if /P6 is used by default, but no. I haven't checked any other projects, but at the moment, of the two I have checked, one does and one doesn't. I'm wondering if it has been on by default in a previous release of Plato, and is now off by default?

I'm off to check a few more now. I've been having a variety of odd problems with a new version of an app of mine recently, which has to run on some quite old machines, and I'm wondering if this switch is ) on and b) implicated.

Andy

3 Aug 2007 2:46 #2140

Sorry for following up to self, but I've checked quite a few projects now, and it's all rather curious.

  1. I checked 13 'projects' that I created between March 2005 and July 2007. I say 'projects' because the amount of code in each is tiny - each one has been created when I have needed to produce code to illustrate a bug report or a technical query. These are good because they tend to get completed quickly and then ignored, so the project file timestamp is probably an accurate indication of when they were created. I can find no evidence for the /P6 switch being on before a certain date, and off afterwards. In every case, the switch is either on or off in all of the three builds (checkmate, debug and release). Of the 13 projects, 5 have the switch on (Mar 05, Oct 05, Aug 06 and 2 x Jan 07), and 8 off (Jul 06 - Jul 07).

  2. Of three real projects that are ongoing, one does not have the switch on, one does - and curiously, one is 'mixed' (it's on in the checkmate build, and off in the other two builds).

As I said, I have never knowingly used this switch. No idea how to interpret these findings, I'm just passing them on in hope a Silverfrostian may be able to.

Andy

3 Aug 2007 5:37 #2141

There is a command log in Visual Studio and also in the latest version of Plato so you can see what the default options are.

My guess is that P6 is on by default in Visual Studio. I think Plato had it as the default for a while but not any longer because there are still some old processors around.

I cannot help any further with the basic problem for a while. If you want to post a new sample with the version number of FTN95 and the exact command line then I will look at it when I can.

6 Aug 2007 7:18 #2145

Paul,

Here's the build log and code that fails on compile - code is pretty much as it was but with correct end type and no interface. Remove /CHECK and it compiles but the value assigned in SetTestType2 is wrong (0 in XP, 120 in Vista).

Cheers, Alan

Build log:

Compiling...

Compiling file: FreeFormat1.f95 FTN95.EXE 'D:\Alan\Documents\Source\IntCompileBug\IntCompileBug\FreeFormat1.f95' /NO_BANNER /DEBUG /CHECK /P6 /FPP/VS8 /DELETE_OBJ_ON_ERROR /ERROR_NUMBERS /UNLIMITED_ERRORS /BINARY 'Debug\Win32\FreeFormat1.obj' Compiler output: D:\Alan\Documents\Source\IntCompileBug\IntCompileBug\FreeFormat1.F95(16) : error 137: Operand incompatible with opcode D:\Alan\Documents\Source\IntCompileBug\IntCompileBug\FreeFormat1.F95(12) : error 52: Compilation abandoned

There were compile errors, no link performed

Code log:

! Demonstrate comiler bug with 2D arrays in modules whth /check option module TestMod

type TestType integer*1:: intKind1 end type TestType

real:: realVals(10,10) = 42.55

contains

subroutine SetTestType(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx

tt%intKind1 = nint(realVals(idx,4))     ! generates 'operand incompatible with opcode' when realVals is 2D array
                                        ! creating an intermediate integer*4 solves the problem

end subroutine SetTestType

subroutine SetTestType2(tt, idx) type(TestType), intent(in out):: tt integer, intent(in):: idx

tt%intKind1 = nint(realVals(idx,4), 1)  ! this is 52 with /check, 0 without

end subroutine SetTestType2

end module TestMod

winapp use TestMod type(TestType):: newtt integer*1:: i1

call SetTestType(newtt, 3) call SetTestType2(newtt, 4) end

Please login to reply.