forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Compiler capability
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Suggestions
View previous topic :: View next topic  
Author Message
wahorger



Joined: 13 Oct 2014
Posts: 581
Location: Morrison, CO, USA

PostPosted: Fri Jan 11, 2019 11:17 pm    Post subject: Compiler capability Reply with quote

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
View user's profile Send private message Visit poster's website
mecej4



Joined: 31 Oct 2006
Posts: 1124

PostPosted: Sat Jan 12, 2019 12:46 am    Post subject: Reply with quote

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
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 581
Location: Morrison, CO, USA

PostPosted: Sat Jan 12, 2019 1:11 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2079
Location: Sydney

PostPosted: Sat Jan 12, 2019 1:38 am    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1124

PostPosted: Sat Jan 12, 2019 1:53 am    Post subject: Reply with quote

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
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 581
Location: Morrison, CO, USA

PostPosted: Sat Jan 12, 2019 2:31 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2079
Location: Sydney

PostPosted: Sat Jan 12, 2019 4:47 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 5910
Location: Salford, UK

PostPosted: Sat Jan 12, 2019 9:10 am    Post subject: Reply with quote

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
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 581
Location: Morrison, CO, USA

PostPosted: Sat Jan 12, 2019 4:32 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 5910
Location: Salford, UK

PostPosted: Sun Jan 13, 2019 9:26 am    Post subject: Reply with quote

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
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 581
Location: Morrison, CO, USA

PostPosted: Sun Jan 13, 2019 11:26 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 5910
Location: Salford, UK

PostPosted: Sun Jan 13, 2019 2:02 pm    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1124

PostPosted: Sun Jan 13, 2019 5:09 pm    Post subject: Reply with quote

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
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 581
Location: Morrison, CO, USA

PostPosted: Mon Jan 14, 2019 6:59 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 5910
Location: Salford, UK

PostPosted: Mon Jan 14, 2019 8:26 am    Post subject: Reply with quote

mecej4

There may be a fault in gFortran. For me gFortran also gives an error report when SEQUENCE is omitted.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Suggestions All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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