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 

Incorrect value of PRESENT

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
simon



Joined: 05 Jul 2006
Posts: 268

PostPosted: Thu Nov 26, 2015 4:12 am    Post subject: Incorrect value of PRESENT Reply with quote

The following example of code seems to return an incorrect value for the intrinsic function PRESENT. The main program calls subroutine s1, passing a function for s1 to call. This function has an optional argument, but s1 does not pass this argument. However, the intrinsic function PRESENT returns .true.. The problem only seems to occur because the function f is passed as a procedure argument.

Code:
MODULE m1
CONTAINS
 SUBROUTINE s1(f)
  INTEGER, EXTERNAL :: f
  INTEGER :: j
  j=f()
 END SUBROUTINE s1
 INTEGER FUNCTION f1 (i)
  INTEGER, INTENT(IN), OPTIONAL :: i
  PRINT *, PRESENT (i)
  f1=0
 END FUNCTION f1
END MODULE m1

PROGRAM p
 USE m1
 CALL s1 (f1)
END PROGRAM p
[/code]
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Thu Nov 26, 2015 9:46 am    Post subject: Reply with quote

gFortran gives the same incorrect result.
It could be a nasty one to try to fix.
I will log it for investigation.
Back to top
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Thu Nov 26, 2015 12:33 pm    Post subject: Reply with quote

My reading of the test code is a bit different. The program is non-conforming for the reason given below, and the compiler is not required to diagnose the problem.

The caller of a subprogram with an OPTIONAL argument must be provided with an explicit interface to the callee. In the test code, instead of such an interface being provided, the argument is declared EXTERNAL, so the compiler is going to use an implicit interface which is incorrect. In such a situation, no compiler is likely to diagnose the problem unless run-time checks are requested for argument consistency.
Back to top
View user's profile Send private message
simon



Joined: 05 Jul 2006
Posts: 268

PostPosted: Thu Nov 26, 2015 2:14 pm    Post subject: Reply with quote

Many thanks for the quick responses. I have tested NAGWare, and that has the same problem also. The suggestion to include an explicit interface works (see below). I had thought the interface was not needed since the function is in module m1. However, it does seem that the EXTERNAL statement over-rides that.

Code:
MODULE m1
CONTAINS
 SUBROUTINE s1(f)
  INTERFACE
   INTEGER FUNCTION f (i)
   INTEGER, INTENT(IN), OPTIONAL :: i
   END FUNCTION f
  END INTERFACE
  INTEGER :: j
  j=f()
 END SUBROUTINE s1
 INTEGER FUNCTION f1 (i)
  INTEGER, INTENT(IN), OPTIONAL :: i
  PRINT *, PRESENT (i)
  f1=0
 END FUNCTION f1
END MODULE m1

PROGRAM p
 USE m1
 CALL s1 (f1)
END PROGRAM p
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Thu Nov 26, 2015 4:05 pm    Post subject: Reply with quote

I think that the presence of optional arguments in the test program is a red herring. The real point to note is that when entities that are accessible by host association are re-declared in a local scope, the host entities become hidden. Please see "16.5.1.4 Host association", item 2(10) of F2008. Here is an example to illustrate this, using subprograms for which no explicit interface is needed:
Code:

MODULE m1
implicit none
CONTAINS
 SUBROUTINE s1(f1,i)
  INTEGER, EXTERNAL :: f1
  INTEGER :: i
  i=f1(i)
  RETURN
 END SUBROUTINE s1
 INTEGER FUNCTION f1 (i)
  INTEGER, INTENT(IN) :: i
  PRINT *,  'F1, arg_in = ',i
  f1=10
 END FUNCTION f1
 INTEGER FUNCTION f2 (i)
  INTEGER, INTENT(IN) :: i
  PRINT *,  'F2, arg_in = ',i
  f2=20
 END FUNCTION f2
END MODULE m1

PROGRAM p
 USE m1
 IMPLICIT NONE
 INTEGER :: i = 50
 CALL s1 (f2,i)
END PROGRAM p

The entities named 'f1' on lines 4 and 10 are distinct from each other. In fact, the running of the program should be unchanged if the body of the module procedure f1 is removed completely.
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Sat Nov 28, 2015 7:00 pm    Post subject: Reply with quote

Mecej4: I think that your first answer was right in the context of the question asked, and that is that a subprogram with optional arguments needs to have an explicit interface. Without the explicit interface the compiler should be building straightforward traditional subprogram code in which all the arguments are not optional, because it has no way of knowing from the perspective of the caller that the arguments are optional.

It is all too easy for a programmer to assume that the compiler takes into account absolutely every statement in the source code as it works through the file, and can determine the programmer’s intention from even the flimsiest of hints, but there is clearly a limitation to how far ahead in the source code it can look.

You didn’t put it in your own demonstrator, but it seems to me that if one does write a subprogram with optional arguments the first important step that one should take is to check that they are in fact present before using them. Probably the model for this lies in the treatment of the Clearwin+ function WINIO@ where the presence of other arguments is dependent on what is put into the first string argument. The traditionalist like myself has his mind boggled that this works at all, let alone as reliably as it does!

In fact, in your demonstration code it looks to me as if the declaration of F1 as being EXTERNAL is unnecessary* in subroutine S1, as F1 is simply used and not passed as an argument to another routine. It seemed to me at first that program P needed F2 declared as EXTERNAL, although because module M1 contains integer function F2 it is treated differently (as an internal function, not an external one, i.e. as one would treat a traditional statement function).

Eddie

*Not just unnecessarily, but probably incorrectly. I know that EXTERNAL is a rather benign thing to have in a declaration, and in the past I have been advised to put named BLOCK DATA routines in EXTERNAL statements so that the linker looks for them, but never having used named BLOCK DATA then the advice fell on deaf ears.
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Sat Nov 28, 2015 7:52 pm    Post subject: Reply with quote

Eddie, thanks for your comments; I agree with your point that EXTERNAL was unnecessary here, except for making the code more readable. Since f1 is a dummy argument, the compiler knows that 'f1' is not the actual name of the routine. To find the actual linker name, the caller chain will have to be traced to its beginning.

Only after posting my first response and reading Simon's reply to it did I realize that there were two separate issues: optional arguments and host association. I wrote my second response so that the host association issues could be exposed. Perhaps Simon did not care about host variables being hidden by local variables with the same name in his example, but I felt that this pitfall should be pointed out.
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 -> Support All times are GMT + 1 Hour
Page 1 of 1

 
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