- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I recently came to an issue which was not easy to find (even if the source code is quite small) with a derived type passed as argument and declared with the INTENT(OUT) statement in the called subroutine. I read the section of the help relating to the INTENT statement but without getting a clear answer.
Originally, there was a programming error from my side since the argument should have been declared INTENT(INOUT) since some its elements are used without being set before in the routine (they are defined in a parent subroutine) and some others are calculated in the routine.
My question is, why the compiler didn't warn me about the fact that I was using an element of a derived type before it was set (i.e. being on the right-hand side of an assignement expression but never found on the left-hand side of another one before) because of the INTENT(OUT) declaration?
For a simple scalar variable, the compiler would have given the following message:
warning #6843: A dummy argument with an explicit INTENT(OUT) declaration is not given an explicit value. [Var]
I agree that for complex UDTs with a lot of subitems, issuing a warning for all the items that are not set before the return may be a bit too much, but at least for those who are used would be nice, or in this particular case of INTENT(OUT), should I activate additional compiler diagnostics to get this message?
Best regards,
Phil.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The declaration of a UDT implicitly has a constructor, either implicit or explicit. Therefor the INTENT(OUT) is sufficient to construct the returned object.
Furthermore, there is no way to specify which UDT member: variables, arrays, allocatables pointers, or embedded UDT's are required to be set via =.
IOW the implicit/explicit constructor is sufficient to define the returned object.
Jim Dempsey
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The intent serves two purposes it signals what the programmers design is meant to do, and it gives the compiler and opportunity to do some validation which is useful in flagging up many stupid code errors. It is not always practical (or possible) for the compiler to check intent, for example any args passed on in a call to an external subprogram without an explicit interface is a total unknown. The intent is therefore a safety guard but not an infallible one and I don't think the standards are prescriptive on this issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The declaration of a UDT implicitly has a constructor, either implicit or explicit. Therefor the INTENT(OUT) is sufficient to construct the returned object.
Furthermore, there is no way to specify which UDT member: variables, arrays, allocatables pointers, or embedded UDT's are required to be set via =.
IOW the implicit/explicit constructor is sufficient to define the returned object.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Re: "why the compiler didn't warn me about the fact that I was using an element of a derived type before it was set," I will withhold any judgment on what it might take for a compiler to develop further user-friendly static code analysis and linting facilities. It may take you forever if at all you manage to convince Intel Fortran team to add such a new feature to warn you in such situations.
In the meantime, something you can immediately consider to mitigate the problem you faced in future might be default initialization of your derived type components. And to use `INTENT(OUT)` only when the use case for it is strong in a given code. But let me guess based on prior posts, your response will be that you knew about all this already but you could not make use of it for legacy reasons x, y, and z, and so this threads of yours is only about the compiler but not your coding practices which then places you back in the scenario of the previous paragraph! Thus the blurb below may be more for any other reader who may be open to using the facilities in the language.
module m
type :: t
integer :: n = 42 !<-- default initialization; applies to INTENT(OUT) cases also
end type
contains
subroutine sub( a )
type(t), intent(out) :: a
integer :: n
print *, "In sub: a%n = ", a%n, "; expected is 42"
n = a%n
a%n = -99
end subroutine
end module
use m
type(t) :: u
u%n = 1000
call sub( u )
print *, u%n, "; expected is -99"
end
C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.0 Build 20220726_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.33.31630.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:p.exe
-subsystem:console
p.obj
C:\temp>p.exe
In sub: a%n = 42 ; expected is 42
-99 ; expected is -99
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Thanks for your answers.
I was not expecting the compiler to add an implicit constructor since the UDT is passed by reference, I assumed it was initialized when declared in the calling routine (with the default initialization I used, zero in my case), furthermore some of its components might be already intialized in a parent subroutine and only some others are modified in the called subroutine. That's what I thought (apparently incorrectly) the INTENT(OUT) was telling the compiler. The use of default initialization of the UDT components was the source of the problem because the other components were calculated elsewhere and then lost. I don't know if this is related but my wrong coding was working correctly for months (I was able to compare the results with another version of the code without the UDT arg, which was used to replace a COMMON bloc) and the behavior changed recently when I switched the floating-point option /fp:fast=2 to /fp:source.
Anyway, this was a good lesson about the need to correctly check the INTENT attributes of the dummy args, especially for UDTs! I spent some time to understand what was happening but fortunately a colleague was using another version (older) of the code, so we were able to run debug sessions in parallel and compare the calculated values.
Best regards,
Phil.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page