I have come across a bug in the Intel v12 compiler (12.1.6 20120928), where the value connected to a pointer reference cannot be accessed when sent to a subprogram. I have a user defined type that functions as a linked list that contains an internal pointer to another object. When I reference an allocated instance of the type via the linked list, I can access the value, but if I send that same reference to a subroutine, I cannot access the value.
The attached program demonstrates the issue, along with my preferred work-around that uses an associate block when calling the routine. I have checked this program with v15 and v17 and it works as it should in both cases. In v12, it does not:
# Intel v12 $ ifort test3.f90 && ./a.out run update routine using linked list pointer 1.000000 0.0000000E+00 # THIS IS WRONG run update routine using associate block 1.000000 20.00000 # Intel v17 $ ifort test3.f90 && ./a.out run update routine using linked list pointer 1.000000 20.00000 run update routine using associate block 1.000000 20.00000
Due to factors out of my control, I must use the older compiler for this project. Intel wasn't able to give me any information, because v12 is deprecated. Also, keep in mind that the example code is only to demonstrate the bug.
That being said, I am hoping someone might be familiar with this bug and know more about it. Not knowing what else this bug affects makes it more risky to develop a work-around that isn't actually going to solve the problem. Thanks.
Does changing the declaration of the prev and next components of TComponent (and perhaps the ptr, root and cur pointers) to be non-polymorphic also help?
There have been quite a few issues with polymorphic components over the years - I'll go so far as to say that you need to have a relatively current compiler if you are going to use them in production code. 12.1 is way off the pace.
I was afraid of that. I heard from an older friend once that he would never use anything other that f77 constructs and I balked at him. I am sure that is an over-reaction, but having to back track this issue is going to be painful.
Using class(*) pointers for everything seems to work too, but I think this is because I have to wrap the call to update in a select type construct -- that is, you can't have "class(*), pointer :: root" and then try to access root%p1%x.
Interestingly, changing the pointer p1 to a polymorphic pointer of base type TPoint is one fix (inside of TComponent definition, "class(TPoint), pointer :: p1"). I didn't like this solution, because I couldn't figure out why the compiler wanted TPoint to be polymorphic.
Right now, (in the actual code) I am using type bound procedures connected to TComponent and all of the types that extend that type. If this bug is bad enough, I think I can change around the routines to use "type(TComponetX)" and initialize appropriate pointers and call the routine directly, rather than using type bound procedures.
What compiler version (oldest) seems to be polymorphic component ready for production code?
It is pretty hard to judge which (oldest) is best. Looking at past polymorphic related submitted defects, a large number were fixed in the 13.x release (PSXE 2013); however, many others were fixed in the releases following that one. There are also still open defects in this area. Of course the latest PSXE 2017 update 1 (17.0 compiler) contains the most current features and bug fix content.
Whatever the underlying defect is, it appear it was fixed in our initial 13.0 (PSXE 2013 - l_fcompxe_2013.0.079). I confirmed your test case fails with the final 12.x update release and passes with the initial 13.0 release. As was noted, there have been a number of issues in this area so you're probably better served by the more current releases.
Thanks for the replies and looking into the defects in the older compilers.
The obvious quick answer is just to use the latest compiler, which I have; but as mentioned at the top there are issues with a client that are beyond my control and I have to test the code against the v12 compiler to meet their requirements.
Right now, I am using the work-around (using an associate block). Do you have any information about the underlying defect that might give me an indication of whether or not this code has an internal flaw (when using the v12 compiler) that is lurking in the corner? Should I try to re-tool the whole code to not use any polymorphic pointers? What about type bound procedures, are there problems with those?
Right now the work-around seems to be OK and the results are comparable with both v12 and v17. I am hoping that means the other defects are use cases of language features (related to polymorphic pointers and such) that I am just not using.
The only way you could get a practical answer to those questions is for you to do extensive testing of the compiler against your own code.
(And for your friend's benefit, sticking to Fortran 77 doesn't necessarily help - I can think of at least one bug involving only Fortran 77 language features that I've stumbled across in the last few years.)
I inquired w/Development and they do not recall or recognize the specifics of the underlying issue given the information provided. This particular issue appears to date back almost 7 years ago and they have made a lot of changes in that timeframe. They said that in the 12.0 timeframe (development done in ~2009/2010), the support for polymorphism and type bound procedures was quite new, and finalization was very, very new, so there were more defects in those areas at that time. In sticking with 12.x, avoiding those newer features might offer more stability. They also stressed you should move to a more recent compiler.