- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
in the following example, should the program not behave the same way,whether I assign a variable to itself enclosed or not in parentheses ?
module m_test type t_1 integer :: i,j,k contains procedure, private :: t_1_ass_t_1 generic :: assignment(=) => t_1_ass_t_1 end type contains subroutine t_1_ass_t_1(var, expr) class(t_1), intent(out) :: var class(t_1), intent(in) :: expr var%i = 0 var%j = 0 var%k = 0 if (expr%i > 0) then var%i = expr%i var%j = expr%j var%k = expr%k endif end subroutine end module program test use m_test type(t_1) :: x,y x = t_1(1,2,3) x = x print *, x y = t_1(1,2,3) y = (y) print *, y end program
However the output is:
C:\TEMP>ifort test.f90 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 16.0.0.110 Build 20150815 Copyright (C) 1985-2015 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 11.00.61030.0 Copyright (C) Microsoft Corporation. All rights reserved. -out:test.exe -subsystem:console test.obj C:\TEMP>test 0 0 0 1 2 3 C:\TEMP>
In clause 12.4.3.4.3 the Fortran 2008 standard says "A defined assignment is treated as a reference to the subroutine, with the left-hand side as the first argument and the right-hand side enclosed in parentheses as the second argument."
Johny
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
At first, I wondered if the statement x = x, which results in the call t_1_ass_t_1(x, x), is in violation of the rules that prohibit subroutine arguments being aliased. When you do x = (x), the call is made with (x, copy_of_x) as the arguments, so there is no aliasing.
However, reading your post again, I see that the quote of the standard already states that the second argument is to be considered as being the R.H.S. expression in parentheses, so there should be no aliasing question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You're right that it should work the way you expect. We had this problem for a long time but I thought we had fixed it a couple of releases ago. Your example clearly demonstrates we have more work to do - I will send this on to the developers. Thanks for the nice example. Issue ID is DPD200381046.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am not sure to understand, but when assigning x to x on line 29, does this not do the same as calling t_1_ass_t_1(x,x) where the first lines are nullifying the values of var (=x) and then because expr%i (i.e. x%i) is equal to zero leave var (=x) equal to zero ? For me that's the only explanation I can find but I am not sure about what the standard says or what the compiler should do. However my main question is: what does y = (y) means on line 32? (mainly in that case what is the purpose of the parenthesis?) and why does this not produce the same results as for x = x?
Best regards,
Phil.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Surrounding an argument with parentheses causes evaluation of the expression within the parentheses, if needed, copying the result to an anonymous temporary variable, and passing the anonymous copy to the subroutine. When a variable is passed this way, the called routine can alter the copy, but the original is protected since the called subroutine does not even know about its existence. Try this test code:
program pararg implicit none integer :: x(3) = [1,7,3] call sub(x,(x)) write(*,*)x end program pararg subroutine sub(x,y) integer x(3),y(3) x(1:3)=0 where(y > 1)x = y return end subroutine sub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
mecej4 wrote:
Surrounding an argument with parentheses causes evaluation of the expression within the parentheses, if needed, copying the result to an anonymous temporary variable, and passing the anonymous copy to the subroutine. When a variable is passed this way, the called routine can alter the copy, but the original is protected since the called subroutine does not even know about its existence. Try this test code:
program pararg implicit none integer :: x(3) = [1,7,3] call sub(x,(x)) write(*,*)x end program pararg subroutine sub(x,y) integer x(3),y(3) x(1:3)=0 where(y > 1)x = y return end subroutine sub
Thanks a lot for the explanation. I did not think that could behave differently with and without the parentheses
Best regards,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is one of those language features that is not frequently used and, when you first see it, may appear rather quixotic.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This should be a caution to someone writing a formatting program to tabulate, indent, and otherwise cleanup source code to not remove seemingly unnecessary parenthesis.
Jim Dempsey
![](/skins/images/7B0AB6865064EAE32B30EC9A4E94B48A/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page