|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Fri Jan 11, 2019 11:17 pm Post subject: Compiler capability |
|
|
I use the compiler to help keep me honest. I collect all the routines and MAIN's in one file, and compile it. This let's me check for missing arguments, incorrect data types, etc.
I use a lot of TYPE's. So imagine the surprise when I ran a CHECKMATE version of my SW and it discovered, at run-time, a mistake in the TYPE being passed as an argument. My compile step to let the compiler check for me was completely error free. I ran some possible examples through PLATO and the compiler will detect some errors, but not across the module boundaries.
On reflection, it made sense to me that a new data type would be more difficult to detect as an error as if it were one of the elemental data types. On further reflection, though, I said to myself "Well, if the incorrect type can be found at run-time, then all the information to make this comparison is available at compile time."
So, I wondered if there were other's who might have a similar need to mine and would be in favor of some additional compile time checking. If that is at all possible. Or, is there another way I'm missing? |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1896
|
Posted: Sat Jan 12, 2019 12:46 am Post subject: |
|
|
The compiler can check an actual argument list for correct types if it has available to it a complete interface in the same program unit as the one containing the call, or if the subprogram heading and dummy argument declarations are available in the same file. I feel that the description you have given is rather broad, and I should prefer to see actual code that does what you described.
Consider this example, with arguments being passed in the wrong order.
Code: | program tst
implicit none
integer :: i, j
real :: x,y
i = 2
j = 3
x = 1.5
call sub(i,x,j,y)
end program
subroutine sub(i,j,x,y)
implicit none
integer :: i,j
real :: x,y
if(i /= j)then
y = x
else
y = -x
endif
return
end subroutine |
The compiler warns about the error at compile time and, if you link and run the program despite the warning, aborts with a message at run time.
Had the call said "call sub(i,j,y,x)", no compile time warning would be possible. Even run time detection would not be possible unless INTENTs were provided for the dummy arguments.
However, if the two program units are placed in separate files, no compile time warning is possible.
Please show the code.
Last edited by mecej4 on Sat Jan 12, 2019 1:13 am; edited 1 time in total |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Sat Jan 12, 2019 1:11 am Post subject: |
|
|
Yes, this works for intrinsic types. The following code does not generate a compile time error, but will throw an exception when compiled/run as CHECKMATE.
Code: | ! PROGRAM SIMPLE
PROGRAM MAIN
TYPE:: AAA
INTEGER:: B=0
END TYPE AAA
TYPE:: BBB
REAL:: B=0
END TYPE BBB
TYPE (AAA):: TYPE_A
TYPE (BBB):: TYPE_B
!CALL DEFG(TYPE_A,TYPE_B)
CALL DEFG(TYPE_B,TYPE_A)
END
SUBROUTINE DEFG(AA,BB)
TYPE:: AAA
SEQUENCE
INTEGER:: B=0
END TYPE AAA
TYPE:: BBB
SEQUENCE
REAL:: B=0
END TYPE BBB
TYPE (AAA):: AA
TYPE(BBB):: BB
AA%B = BB%B
RETURN
END
|
|
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2582 Location: Sydney
|
Posted: Sat Jan 12, 2019 1:38 am Post subject: |
|
|
I expected the following code would fail with FTN95, but it compiled with no errors using ver 8.20.0 ?
gFortran warns of a possible error.
This is my typical approach to address this problem. Code: | ! PROGRAM SIMPLE
module my_types
TYPE:: AAA
SEQUENCE
INTEGER:: B=1
END TYPE AAA
TYPE:: BBB
SEQUENCE
REAL:: B=2
END TYPE BBB
end module my_types
PROGRAM MAIN
use my_types
TYPE (AAA):: TYPE_A
TYPE (BBB):: TYPE_B
!CALL DEFG(TYPE_A,TYPE_B)
CALL DEFG(TYPE_B,TYPE_A)
write (*,*) type_a%b, type_b%b
END
SUBROUTINE DEFG(AA,BB)
use my_types
TYPE (AAA):: AA
TYPE(BBB):: BB
AA%B = BB%B
RETURN
END |
|
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1896
|
Posted: Sat Jan 12, 2019 1:53 am Post subject: |
|
|
Curioser and curioser!
Even with CALL DEFG(TYPE_A,TYPE_B) instead of CALL DEFG(TYPE_B,TYPE_A), the first program that you showed would be in error unless the SEQUENCE attribute is included in the derived type definitions. In that case, FTN95 /checkmate does not detect the error even at run time. |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Sat Jan 12, 2019 2:31 am Post subject: |
|
|
I removed the SEQUENCE just to make it shorter. That made no difference anyway. I don't expect these kinds of examples to necessarily produce good results. Just illustrate an error of one type or another.
That said, John, the MODULE is fine, but the issue I'm working is the call to DEFG with the arguments reversed. Not solved by the MODULE. However, an INTERFACE will solve the problem. I implemented that in one of the complex routines just to make sure I got the arguments TYPEd right in each of the calls...
I had expected the compiler to complain, and it didn't, so I went away doing more work, thinking all was well. In my case, SEQUENCE is used, and the desired TYPE was first up (nested) in the data structure that was being passed. And was /RELEASE, so no errors. It wasn't until I had to run a /CHECKMATE version of the code that the error was revealed. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2582 Location: Sydney
|
Posted: Sat Jan 12, 2019 4:47 am Post subject: |
|
|
Interesting, intrinsic types appear to be tested but not derived types; based on the following example extension Code: | ! PROGRAM SIMPLE
module my_types
TYPE:: AAA
SEQUENCE
INTEGER:: B=1
END TYPE AAA
TYPE:: BBB
SEQUENCE
REAL:: B=2
END TYPE BBB
end module my_types
PROGRAM MAIN
use my_types
TYPE (AAA):: TYPE_A
TYPE (BBB):: TYPE_B
integer :: aa=1
real :: bb=2
!CALL DEFG(TYPE_A,TYPE_B)
CALL DEFG(TYPE_B,TYPE_A)
write (*,*) type_a%b, type_b%b
CALL Dintrinsic (bb,aa)
write (*,*) bb, aa
END
SUBROUTINE DEFG(AA,BB)
use my_types
TYPE (AAA):: AA
TYPE(BBB):: BB
AA%B = BB%B
RETURN
END
SUBROUTINE Dintrinsic(AA,BB)
integer :: aa
real :: bb
AA = BB
RETURN
END |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8012 Location: Salford, UK
|
Posted: Sat Jan 12, 2019 9:10 am Post subject: |
|
|
Runtime checking for matching argument types can sometimes go wrong (giving false error reports or missing errors). Equally there are some really messy situations where FTN95 simply makes no attempt to check the type of the arguments.
I would need illustrative sample code in order to work out this particular case. |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Sat Jan 12, 2019 4:32 pm Post subject: |
|
|
Paul, I'm not all that concerned about run-time checking for individual elements of a TYPE. Whatever /CHECKMATE is doing for seeing if the name of the TYPE is the same between modules at run-time would satisfy many, if not most, occurrences.
I was more concerned about the compile time check. Again, not the individual elements of the TYPE, but even just the NAME of the type should be enough.
The example I gave illustrates that a compile time check is not performed. The fact that the run-time error is trapped would suggest that there is sufficient information at compile time to make that check.
If you need a more detailed example, I'd be happy to try and gen one up. I'd just need to know what kinds of examples you'd need. And if I am unable to do so, perhaps someone else can weigh in with examples that might help.
Bill |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8012 Location: Salford, UK
|
Posted: Sun Jan 13, 2019 9:26 am Post subject: |
|
|
Bill
Sorry but I missed the significance of your example.
The presenting fault is that the call to DEFG from the main program requires an interface for DEFG in the code. In other words the given code is not correct Fortran.
I have not tested this but if you include the required interface then everything should work as expected. |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Sun Jan 13, 2019 11:26 am Post subject: |
|
|
Paul, thanks.
Yes, with the proper interface, the compiler does catch the error.
I had hoped that the compiler could/would without this, since it is in the same compilation module, similar to what happens when one has errors in intrinsic types.
In my example, if you change TYPE_A to INTEGER, and TYPE_B to REAL throughout, then compile it, the compiler will tell you that you had a difference in the argument types.
Code: | ! PROGRAM SIMPLE
PROGRAM MAIN
INTEGER:: TYPE_A
REAL:: TYPE_B
CALL DEFG(TYPE_B,TYPE_A)
END
SUBROUTINE DEFG(AA,BB)
INTEGER:: aa
REAL:: bb
aa=bb
RETURN
END
|
which generates the error message:
Quote: | : warning 676 - In a call to DEFG from another procedure, the first argument was of type REAL(KIND=1), it is now INTEGER(KIND=3) |
It is that warning that is "good enough" for me to go check what the heck I did wrong! |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8012 Location: Salford, UK
|
Posted: Sun Jan 13, 2019 2:02 pm Post subject: |
|
|
Bill
Strangely the converse might be better. Sometimes the fact that FTN95 remembers some things from one independent program/routine to another in the same file can cause problems and it might make more sense and be simpler for compilation process if this were not the case. |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1896
|
Posted: Sun Jan 13, 2019 5:09 pm Post subject: |
|
|
Consider the following variant of Bill's test program:
Code: | PROGRAM MAIN
TYPE:: AAA
INTEGER:: B
END TYPE AAA
TYPE:: BBB
REAL:: B
END TYPE BBB
TYPE (AAA):: TYPE_A
TYPE (BBB):: TYPE_B
TYPE_B%B = 2.5
CALL DEFG(TYPE_A,TYPE_B)
print *,TYPE_A%B
contains
SUBROUTINE DEFG(AA,BB)
TYPE:: AAA
SEQUENCE
INTEGER:: B
END TYPE AAA
TYPE:: BBB
SEQUENCE
REAL:: B
END TYPE BBB
TYPE (AAA):: AA
TYPE(BBB):: BB
AA%B = BB%B
RETURN
END SUBROUTINE
end program |
The derived types AAA and BBB in the main program do not match the derived types of the same names in the contained subroutine, because the former ones (in the main program) do not contain SEQUENCE. For this program, Gfortran 6.3 says:
Quote: | wah1.f90:11:27:
CALL DEFG(TYPE_A,TYPE_B)
1
Error: Type mismatch in argument 'aa' at (1); passed TYPE(aaa) to TYPE(aaa) |
Even with /CHECKMATE, FTN95 compiles the program with no error messages and the resulting program outputs "2" as the result. |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Mon Jan 14, 2019 6:59 am Post subject: |
|
|
Paul, I have experienced exactly that behavior a couple of years back. I wish I could remember what it was. Simple to just break the multiple modules into separate files, so I think that is what I did.
I'll be OK with whatever course of action (or inaction) you decide to take.
Bill |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8012 Location: Salford, UK
|
Posted: Mon Jan 14, 2019 8:26 am Post subject: |
|
|
mecej4
There may be a fault in gFortran. For me gFortran also gives an error report when SEQUENCE is omitted. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|