Go Back   Rhinocerus > Newsgroup > Newsgroup comp.lang.* 1 > Newsgroup comp.lang.fortran

Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old 06-23-2012, 06:32 PM
Nasser M. Abbasi
Guest
 
Posts: n/a
Default question on intent(in) and changing the input inside a subroutine

I was looking at this web page of best practices in Fortran

http://fortran90.org/src/best-practices.html#arrays

and it shows this code fragment:

-----------------------------
subroutine f(r)
real(dp), intent(in) :: r(
integer :: n, i
n = size(r)
do i = 1, n
r(i) = 1.0_dp / i**2
enddo
end subroutine
--------------------------

The first strange thing I noticed is that the formal
parameter r is declared as 'in' yet it is being written
to inside the subroutine. But based on Fortran standard:

"intent(in) means that the variable value can enter, but not be changed"


So, what is going on here?

When I tried it on my end, I am getting an error.

Here is my code to test the above. all in same one file.

------------ t6.f90 -------------------------
module inc
implicit none
contains

subroutine f(r)
integer, parameter:: dp=kind(0.d0)
real(dp), intent(in) :: r(
integer :: n, i
n = size(r)
do i = 1, n
r(i) = 1.0_dp / i**2
enddo
end subroutine f
end module inc

program main
use inc
implicit none

integer, parameter:: dp=kind(0.d0)
real(dp) :: r(5)
call f(r)

end program main
----------------------------

---------------------------
>gfortran -fcheck=all -Wall t6.f90

t6.f90:11.10:

r(i) = 1.0_dp / i**2
1
Error: Dummy argument 'r' with INTENT(IN) in variable definition context (assignment) at (1)
t6.f90:17.8:

use inc
1
Fatal Error: Can't open module file 'inc.mod' for reading at (1): No such file or directory
>

------------------------------

Am I doing something wrong? could the web page really be wrong?
Has the standard changed and once it was allowed to write
to an 'in' parameter? does not make much sense.

I am not good enough in Fortran to say that a Fortran90.org
'best practices' page is wrong ! But it sure looks like it.

thanks,
--Nasser
Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #2 (permalink)  
Old 06-23-2012, 06:53 PM
Richard Maine
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

Nasser M. Abbasi <nma@12000.org> wrote:

> I was looking at this web page of best practices in Fortran
>
> http://fortran90.org/src/best-practices.html#arrays
>
> and it shows this code fragment:
>
> -----------------------------
> subroutine f(r)
> real(dp), intent(in) :: r(
> integer :: n, i
> n = size(r)
> do i = 1, n
> r(i) = 1.0_dp / i**2
> enddo
> end subroutine
> --------------------------
>
> The first strange thing I noticed is that the formal
> parameter r is declared as 'in' yet it is being written
> to inside the subroutine. But based on Fortran standard:

....
> I am not good enough in Fortran to say that a Fortran90.org
> 'best practices' page is wrong ! But it sure looks like it.


Yes, that is a clear error in that web page. Do note that the web page
in question is mostly the effort of one individual. It isn't as though
it is anything official or widely vetted. Of course, it can have errors.
(It also has a pretty explicitly stated slant towards people with a
prior background in Python, which largely leaves me out). While
certainly a worthwhile effort, my biggest comment would be that it is
pretty narrow. There are a *LOT* of other things I would personally
consider to be best practices. But then I'm in no position to criticize;
it isn't as though I've put in the work to write up something more
comprehensive.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
Reply With Quote
  #3 (permalink)  
Old 06-23-2012, 06:55 PM
Jos Bergervoet
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On 6/23/2012 8:32 PM, Nasser M. Abbasi wrote:
..
> I am not good enough in Fortran to say that a Fortran90.org
> 'best practices' page is wrong ! But it sure looks like it.


Yes. Unless of course they were listing test cases
for the compilers error detection capability! (I didn't
look it up.. so I don't know why they wrote it.)

BTW: what was the second strange thing?

--
Jos

Reply With Quote
  #4 (permalink)  
Old 06-23-2012, 07:48 PM
Nasser M. Abbasi
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On 6/23/2012 1:55 PM, Jos Bergervoet wrote:

>
> BTW: what was the second strange thing?
>


This:

"Integer Division
(N - 1.0_dp)/N

As long as one of the / operands is a float, a floating
point division will be used."

I found this behavior really strange and can lead to errors.

--------------------------
program main
implicit none

integer, parameter:: dp=kind(0.d0)
integer, parameter:: N=3
real(dp) :: r

r = (N-1)/N
Print *,r

end program main
-----------------------

>gfortran -fcheck=all -Wall t7.f90
>./a.out

0.0000000000000000

Because one 'forgot' to make 'one' of the variables
in that line real. The compiler did not even warn about it.

Compare this to Ada:

----------------------
procedure foo is
N : integer := 3;
r : float;
begin
r := (N-1)/N;
end foo;
----------------------

>gnatmake foo.adb

gcc-4.6 -c foo.adb
foo.adb:5:14: expected type "Standard.Float"
foo.adb:5:14: found type "Standard.Integer"
gnatmake: "foo.adb" compilation error
>


The program will not even compile. Which is good. Ada
wants an explicit cast, else will not compile.

So, what I found strange is a rule which says
"As long as ". Whenever I read things like this, I get
really nervous. I keep worrying about a bridge falling, or
something like this becuase I forgot to add _dp to 'one'
of the parmaters in that line above.

--Nasser
Reply With Quote
  #5 (permalink)  
Old 06-23-2012, 08:18 PM
Gordon Sande
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On 2012-06-23 16:48:56 -0300, Nasser M. Abbasi said:

> On 6/23/2012 1:55 PM, Jos Bergervoet wrote:
>
>>
>> BTW: what was the second strange thing?
>>

>
> This:
>
> "Integer Division
> (N - 1.0_dp)/N
>
> As long as one of the / operands is a float, a floating
> point division will be used."
>
> I found this behavior really strange and can lead to errors.


Mixed mode is a problematic area. Perhaps this tells you something
about the quality of the "best practices" site you are looking at.
The internet is like that. The cynics in the crowd would probably say
it was put there by some starting student with too much time on their
hands. You can check to see if it has had much updating after it was
started. It is not a good sign if it has a few updates right after it
started and none for the last several years. Or if there is only one
author.

Once you have accumulated some amount of scar tissue from making dumb
mistakes you learn to not play games with mixed mode. Fortran is very
old so for historical continuity reasons permits the users to play
with fire. Other languages with less history, and much smaller libraries
of useful stuff, provide less access to the fire.

> --------------------------
> program main
> implicit none
>
> integer, parameter:: dp=kind(0.d0)
> integer, parameter:: N=3
> real(dp) :: r
>
> r = (N-1)/N
> Print *,r
> end program main
> -----------------------
>
>> gfortran -fcheck=all -Wall t7.f90
>> ./a.out

> 0.0000000000000000
>
> Because one 'forgot' to make 'one' of the variables
> in that line real. The compiler did not even warn about it.
>
> Compare this to Ada:
>
> ----------------------
> procedure foo is
> N : integer := 3;
> r : float;
> begin
> r := (N-1)/N;
> end foo;
> ----------------------
>
>> gnatmake foo.adb

> gcc-4.6 -c foo.adb
> foo.adb:5:14: expected type "Standard.Float"
> foo.adb:5:14: found type "Standard.Integer"
> gnatmake: "foo.adb" compilation error
>>

>
> The program will not even compile. Which is good. Ada
> wants an explicit cast, else will not compile.
>
> So, what I found strange is a rule which says
> "As long as ". Whenever I read things like this, I get
> really nervous. I keep worrying about a bridge falling, or
> something like this becuase I forgot to add _dp to 'one'
> of the parmaters in that line above.
>
> --Nasser



Reply With Quote
  #6 (permalink)  
Old 06-23-2012, 09:07 PM
Tobias Burnus
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

Nasser M. Abbasi wrote:
> --------------------------
> program main
> implicit none
>
> integer, parameter:: dp=kind(0.d0)
> integer, parameter:: N=3
> real(dp) :: r
>
> r = (N-1)/N
> Print *,r
>
> end program main
> -----------------------
>
>> gfortran -fcheck=all -Wall t7.f90
>> ./a.out

> 0.0000000000000000
>
> Because one 'forgot' to make 'one' of the variables
> in that line real. The compiler did not even warn about it.


Unfortunately, there is too many valid code to warn in cases like you
had. Such code has typically the form:

complex = real ! esp. "0.0"
real = integer ! esp. "0" or some loop variable

Thus, any attempt to warn for those will produce way to many warning to
be useful in the general case.

Actually, gfortran provides two kind of warnings: -Wconversion which is
implied by -Wall. That one produces only few warnings which mostly point
to bugs.

And -Wconversion-extra which can be handy to find bugs of the kind you
had in your code. However, that flag will produce tons of false
positives in real-world code. (But I managed to find real issues with
that flag, hidden in about a thousand warning lines.)

For your program, gfortran gives with the -Wconversion-extra flag:

r = (N-1)/N
1
Warning: Conversion from INTEGER(4) to REAL(8) at (1)


Tobias
Reply With Quote
  #7 (permalink)  
Old 06-23-2012, 09:09 PM
glen herrmannsfeldt
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

Gordon Sande <Gordon.Sande@gmail.com> wrote:

(snip)
>> "Integer Division
>> (N - 1.0_dp)/N


>> As long as one of the / operands is a float, a floating
>> point division will be used."


>> I found this behavior really strange and can lead to errors.


A favorite programming problem for new programmers is a
temperature conversion table between C and F or F and C.

If not before, that is usually when one learns about integer
division and, usually, doesn't forget after that. (Not that
one never slips up, which is different from not forgetting.)

> Mixed mode is a problematic area. Perhaps this tells you something
> about the quality of the "best practices" site you are looking at.
> The internet is like that. The cynics in the crowd would probably say
> it was put there by some starting student with too much time on their
> hands. You can check to see if it has had much updating after it was
> started. It is not a good sign if it has a few updates right after it
> started and none for the last several years. Or if there is only one
> author.


It might be using examples of how not to do it to teach
how best to do it. (I haven't looked at the site at all.)

I high-school I remember an assignment to write an essay using
as many cliches as we could. That would help remind us not to
use them in our writing later.

> Once you have accumulated some amount of scar tissue from making dumb
> mistakes you learn to not play games with mixed mode. Fortran is very
> old so for historical continuity reasons permits the users to play
> with fire. Other languages with less history, and much smaller libraries
> of useful stuff, provide less access to the fire.


Well, many other languages followed the mixed-mode rules
from Fortran. C does it pretty much the same way.

Java has some special rules related to widening and narrowing
conversions that will prevent some of the errors that one might
make in Fortran or C. Assigning an expression to a variable with
a narrower range requires a cast. (Range, not precision, so you
can assign int to float without a cast, but not the other way.)

-- glen
Reply With Quote
  #8 (permalink)  
Old 06-24-2012, 01:48 AM
Louisa
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On Jun 24, 4:32*am, "Nasser M. Abbasi" <n...@12000.org> wrote:
> I was looking at this web page of best practices in Fortran
>
> http://fortran90.org/src/best-practices.html#arrays
>
> and it shows this code fragment:
>
> -----------------------------
> subroutine f(r)
> real(dp), intent(in) :: r(
> integer :: n, i
> n = size(r)
> do i = 1, n
> * * *r(i) = 1.0_dp / i**2
> enddo
> end subroutine
> --------------------------
>
> The first strange thing I noticed is that the formal
> parameter r is declared as 'in' yet it is being written
> to inside the subroutine. But based on Fortran standard:
>
> "intent(in) means that the variable value can enter, but not be changed"
>
> So, what is going on here?
>
> When I tried it on my end, I am getting an error.
>
> Here is my code to test the above. all in same one file.
>
> ------------ t6.f90 -------------------------
> module inc
> * *implicit none
> * *contains
>
> * * *subroutine f(r)
> * * * *integer, parameter:: dp=kind(0.d0)
> * * * *real(dp), intent(in) :: r(
> * * * *integer :: n, i
> * * * *n = size(r)
> * * * *do i = 1, n
> * * * * * *r(i) = 1.0_dp / i**2
> * * * enddo
> * * *end subroutine f
> end module inc
>
> program main
> * use inc
> * implicit none
>
> * integer, parameter:: dp=kind(0.d0)
> * real(dp) :: r(5)
> * call f(r)
>
> end program main
> ----------------------------
>
> --------------------------->gfortran -fcheck=all -Wall t6.f90
>
> t6.f90:11.10:
>
> * * * * * *r(i) = 1.0_dp / i**2
> * * * * * *1
> Error: Dummy argument 'r' with INTENT(IN) in variable definition context (assignment) at (1)
> t6.f90:17.8:
>
> * use inc
> * * * * *1
> Fatal Error: Can't open module file 'inc.mod' for reading at (1): No suchfile or directory
>
> ------------------------------
>
> Am I doing something wrong? could the web page really be wrong?
> Has the standard changed and once it was allowed to write
> to an 'in' parameter? does not make much sense.
>
> I am not good enough in Fortran to say that a Fortran90.org
> 'best practices' page is wrong ! But it sure looks like it.


It is. An INTENT(IN) dummy argument is not to be assigned.

And that's not the only thing that is suspect.
1.0_dp / i**2 isn't a good way to write the expression 1/i**2.
When i is large, i**2 will overflow without warning.
Thus, it should have been written 1/real(i, dp)**2
Reply With Quote
  #9 (permalink)  
Old 06-24-2012, 05:27 AM
robin.vowels@gmail.com
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On Sunday, 24 June 2012 05:48:56 UTC+10, Nasser M. Abbasi wrote:
> On 6/23/2012 1:55 PM, Jos Bergervoet wrote:
>
> >
> > BTW: what was the second strange thing?
> >

>
> This:
>
> "Integer Division
> (N - 1.0_dp)/N
>
> As long as one of the / operands is a float, a floating
> point division will be used."
>
> I found this behavior really strange and can lead to errors.
>
> --------------------------
> program main
> implicit none
>
> integer, parameter:: dp=kind(0.d0)
> integer, parameter:: N=3
> real(dp) :: r
>
> r = (N-1)/N
> Print *,r
>
> end program main
> -----------------------
>
> >gfortran -fcheck=all -Wall t7.f90
> >./a.out

> 0.0000000000000000
>
> Because one 'forgot' to make 'one' of the variables
> in that line real. The compiler did not even warn about it.


In PL/I, (N-1)/N gives 0.6666666666, as you would expect.

> Compare this to Ada:
>
> ----------------------
> procedure foo is
> N : integer := 3;
> r : float;
> begin
> r := (N-1)/N;
> end foo;
> ----------------------
>
> >gnatmake foo.adb

> gcc-4.6 -c foo.adb
> foo.adb:5:14: expected type "Standard.Float"
> foo.adb:5:14: found type "Standard.Integer"
> gnatmake: "foo.adb" compilation error
>
> The program will not even compile. Which is good. Ada
> wants an explicit cast, else will not compile.
>
> So, what I found strange is a rule which says
> "As long as ". Whenever I read things like this, I get
> really nervous. I keep worrying about a bridge falling, or
> something like this becuase I forgot to add _dp to 'one'
> of the parmaters in that line above.

Reply With Quote
  #10 (permalink)  
Old 06-24-2012, 07:12 AM
Jos Bergervoet
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On 6/23/2012 11:07 PM, Tobias Burnus wrote:
> Nasser M. Abbasi wrote:
>> --------------------------
>> program main
>> implicit none
>>
>> integer, parameter:: dp=kind(0.d0)
>> integer, parameter:: N=3
>> real(dp) :: r
>>
>> r = (N-1)/N
>> Print *,r
>>
>> end program main
>> -----------------------
>>
>>> gfortran -fcheck=all -Wall t7.f90
>>> ./a.out

>> 0.0000000000000000
>>
>> Because one 'forgot' to make 'one' of the variables
>> in that line real. The compiler did not even warn about it.

>
> Unfortunately, there is too many valid code to warn in cases like you
> had. Such code has typically the form:
>
> complex = real ! esp. "0.0"
> real = integer ! esp. "0" or some loop variable


No, that's widening and is the opposite of what the
complaint here is about! A similar problem with
complex does ,however, exist. A list of them:

integer :: i
real :: x
complex :: c = (1.0, 2.0)

x = c ! <-- should give error/warning !!!
i = x ! <-- should give error/warning !!!
x = 1/2 ! <-- should give error, warning or 0.5

> Thus, any attempt to warn for those will produce way to many warning to
> be useful in the general case.


A clever way to introduce the warnings only for
the new declaration style '::' could have been
introduced in f90. But they didn't.. Now it's
error prone.

--
Jos
Reply With Quote
  #11 (permalink)  
Old 06-24-2012, 07:14 AM
Jos Bergervoet
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On 6/23/2012 9:48 PM, Nasser M. Abbasi wrote:
> On 6/23/2012 1:55 PM, Jos Bergervoet wrote:
>
>>
>> BTW: what was the second strange thing?
>>

>
> This:
>
> "Integer Division
> (N - 1.0_dp)/N
>
> As long as one of the / operands is a float, a floating
> point division will be used."
>
> I found this behavior really strange and can lead to errors.
>
> --------------------------
> program main
> implicit none
>
> integer, parameter:: dp=kind(0.d0)
> integer, parameter:: N=3
> real(dp) :: r
>
> r = (N-1)/N
> Print *,r
>
> end program main
> -----------------------
>
>> gfortran -fcheck=all -Wall t7.f90
>> ./a.out

> 0.0000000000000000
>
> Because one 'forgot' to make 'one' of the variables
> in that line real. The compiler did not even warn about it.
>
> Compare this to Ada:


Yes, and many other languages too! But C-like
stuff and fortran does the rounding to zero. I
complained about that long ago..

--
Jos

Reply With Quote
  #12 (permalink)  
Old 06-24-2012, 08:14 AM
robin.vowels@gmail.com
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

On Sunday, 24 June 2012 17:12:24 UTC+10, Jos Bergervoet wrote:
> On 6/23/2012 11:07 PM, Tobias Burnus wrote:
> > Nasser M. Abbasi wrote:


> > Unfortunately, there is too many valid code to warn in cases like you
> > had. Such code has typically the form:
> >
> > complex = real ! esp. "0.0"
> > real = integer ! esp. "0" or some loop variable

>
> No, that's widening and is the opposite of what the
> complaint here is about! A similar problem with
> complex does ,however, exist. A list of them:
>
> integer :: i
> real :: x
> complex :: c = (1.0, 2.0)
>
> x = c ! <-- should give error/warning !!!
> i = x ! <-- should give error/warning !!!
> x = 1/2 ! <-- should give error, warning or 0.5
>
> > Thus, any attempt to warn for those will produce way to many warning to
> > be useful in the general case.

>
> A clever way to introduce the warnings only for
> the new declaration style '::' could have been
> introduced in f90. But they didn't.. Now it's
> error prone.


An error/warning message could still be given for expressions
like 1/2 etc.
Warnings could also be given for the other two cases.
Reply With Quote
  #13 (permalink)  
Old 06-24-2012, 08:47 AM
Tobias Burnus
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

Jos Bergervoet wrote:
> On 6/23/2012 11:07 PM, Tobias Burnus wrote:
>> Nasser M. Abbasi wrote:
>>> --------------------------
>>> integer, parameter:: N=3
>>> real(dp) :: r
>>> r = (N-1)/N
>>>
>>>> gfortran -fcheck=all -Wall t7.f90
>>>> ./a.out
>>> 0.0000000000000000
>>>
>>> Because one 'forgot' to make 'one' of the variables
>>> in that line real. The compiler did not even warn about it.

>>
>> Unfortunately, there is too many valid code to warn in cases like you
>> had. Such code has typically the form:
>>
>> complex = real ! esp. "0.0"
>> real = integer ! esp. "0" or some loop variable

>
> No, that's widening and is the opposite of what the
> complaint here is about!


Well, in the original code, the assignment of an integer to a real is
also a kind of widening (even if there can be precision loss for large
integers). At least there are many valid codes, where one has

real_var = integer_index_var

Additionally, widening is also not always correct. Think of the famous

double precision :: x
x = sqrt(2.0)

The code is perfectly valid, however, the programmer probably intended
to write "sqrt(2.0d0)".


> A similar problem with complex does ,however, exist. A list of them:
>
> integer :: i
> real :: x
> complex :: c = (1.0, 2.0)
>
> x = c ! <-- should give error/warning !!!
> i = x ! <-- should give error/warning !!!
> x = 1/2 ! <-- should give error, warning or 0.5


There shouldn't be an error as Fortran allows it. However, gfortran
warns for the first two with -Wconversion / -Wall.

As written before, "x = 1" or similar occurs too often in valid code to
warn with -Wall. (gfortran warns for it with -Wconversion-extra.)

One could start a complicated heuristic, which takes into account what
exactly is written on the right-hand side, e.g. warning if the RHS
contains an integer division while the LHS has is a floating-point
variable. But that starts to get rather complicated and is orthogonal to
the way Fortran evaluates expressions: Namely, first evaluating the RHS
without taking the LHS into account, before assigning to the LHS.


(Side remark: Due to popular demand, gfortran supports
real = z'FFFFF'
where the RHS is evaluated as real(z'FFFFFF'), though gfortran falls
back to regard the BOZ as integer as soon as the BOZ is in any kind of
expression. Other compilers use a more complicated heuristics.
Fortunately, Fortran 2003 allows to have BOZ literals as arguments to
REAL, INT and CMPLX, which solves this issue.)


* * *

I want to additionally note that giving the proper warning/error
messages is not that simple if a compiler wants to support everything
from Fortran 66/77 (with legacy extensions) to Fortran 2008 code, where
the latter could be also F66 code with few F2008 features.

Mere users usually prefer no errors/warnings and even if the compiler
points out a real problem, they rather like to have it swept under the
carpet rather than to think about solving the issue.

Developers of modern code would like to have strict checking and
extensive warnings (but without false positives!),* but also be able to
sweep some issues under the carpet, e.g. by getting away when using a
certain vendor extension - or construct from a newer version of the
standard.**

The whole is complicated by the fact that most compiler users do not
read the manual. The maximal one can expect that they know about -O<n>
for optimization, "-g" for debugging symbols, some way of turning on the
standard diagnostic (e.g. -std=f2003 or -stand f03 or ...), some
default-set of warnings (-Wall, -warn all, -w=all, ...) and turning
bound/other run-time checks on (-fcheck=all, -check all, -C, ...).

Tobias

* Some projects demand the compilation of "-Wall -Werror"

** gfortran provides the option -fall-intrinsics which enables all
vendor intrinsics and intrinsics of newer standards with, e.g., -std=f95.
Reply With Quote
  #14 (permalink)  
Old 06-24-2012, 09:05 AM
Nasser M. Abbasi
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine


Tobias;

What would be the most strict compiler options to use for
check for everything possible?

is it

-warn=all -fcheck=all -fall-intrinsics

I am looking for the most strict options that will check for
EVERYTHING, at compile time, and run time. I get little
confused by all the options. Would the above do it? I thought
you would know better. Which std= do you recommend to use
for the most strict checking? i.e. if I want more checking
done, should I use std=2008? or ? or it does not matter?

thanks,
--Nasser

On 6/24/2012 3:47 AM, Tobias Burnus wrote:
> Jos Bergervoet wrote:
>> On 6/23/2012 11:07 PM, Tobias Burnus wrote:
>>> Nasser M. Abbasi wrote:
>>>> --------------------------
>>>> integer, parameter:: N=3
>>>> real(dp) :: r
>>>> r = (N-1)/N
>>>>
>>>>> gfortran -fcheck=all -Wall t7.f90
>>>>> ./a.out
>>>> 0.0000000000000000
>>>>
>>>> Because one 'forgot' to make 'one' of the variables
>>>> in that line real. The compiler did not even warn about it.
>>>
>>> Unfortunately, there is too many valid code to warn in cases like you
>>> had. Such code has typically the form:
>>>
>>> complex = real ! esp. "0.0"
>>> real = integer ! esp. "0" or some loop variable

>>
>> No, that's widening and is the opposite of what the
>> complaint here is about!

>
> Well, in the original code, the assignment of an integer to a real is
> also a kind of widening (even if there can be precision loss for large
> integers). At least there are many valid codes, where one has
>
> real_var = integer_index_var
>
> Additionally, widening is also not always correct. Think of the famous
>
> double precision :: x
> x = sqrt(2.0)
>
> The code is perfectly valid, however, the programmer probably intended
> to write "sqrt(2.0d0)".
>
>
>> A similar problem with complex does ,however, exist. A list of them:
>>
>> integer :: i
>> real :: x
>> complex :: c = (1.0, 2.0)
>>
>> x = c ! <-- should give error/warning !!!
>> i = x ! <-- should give error/warning !!!
>> x = 1/2 ! <-- should give error, warning or 0.5

>
> There shouldn't be an error as Fortran allows it. However, gfortran
> warns for the first two with -Wconversion / -Wall.
>
> As written before, "x = 1" or similar occurs too often in valid code to
> warn with -Wall. (gfortran warns for it with -Wconversion-extra.)
>
> One could start a complicated heuristic, which takes into account what
> exactly is written on the right-hand side, e.g. warning if the RHS
> contains an integer division while the LHS has is a floating-point
> variable. But that starts to get rather complicated and is orthogonal to
> the way Fortran evaluates expressions: Namely, first evaluating the RHS
> without taking the LHS into account, before assigning to the LHS.
>
>
> (Side remark: Due to popular demand, gfortran supports
> real = z'FFFFF'
> where the RHS is evaluated as real(z'FFFFFF'), though gfortran falls
> back to regard the BOZ as integer as soon as the BOZ is in any kind of
> expression. Other compilers use a more complicated heuristics.
> Fortunately, Fortran 2003 allows to have BOZ literals as arguments to
> REAL, INT and CMPLX, which solves this issue.)
>
>
> * * *
>
> I want to additionally note that giving the proper warning/error
> messages is not that simple if a compiler wants to support everything
> from Fortran 66/77 (with legacy extensions) to Fortran 2008 code, where
> the latter could be also F66 code with few F2008 features.
>
> Mere users usually prefer no errors/warnings and even if the compiler
> points out a real problem, they rather like to have it swept under the
> carpet rather than to think about solving the issue.
>
> Developers of modern code would like to have strict checking and
> extensive warnings (but without false positives!),* but also be able to
> sweep some issues under the carpet, e.g. by getting away when using a
> certain vendor extension - or construct from a newer version of the
> standard.**
>
> The whole is complicated by the fact that most compiler users do not
> read the manual. The maximal one can expect that they know about -O<n>
> for optimization, "-g" for debugging symbols, some way of turning on the
> standard diagnostic (e.g. -std=f2003 or -stand f03 or ...), some
> default-set of warnings (-Wall, -warn all, -w=all, ...) and turning
> bound/other run-time checks on (-fcheck=all, -check all, -C, ...).
>
> Tobias
>
> * Some projects demand the compilation of "-Wall -Werror"
>
> ** gfortran provides the option -fall-intrinsics which enables all
> vendor intrinsics and intrinsics of newer standards with, e.g., -std=f95.
>


Reply With Quote
  #15 (permalink)  
Old 06-24-2012, 10:00 AM
Tobias Burnus
Guest
 
Posts: n/a
Default Re: question on intent(in) and changing the input inside a subroutine

Nasser M. Abbasi wrote:
> What would be the most strict compiler options to use for
> check for everything possible?
>
> is it
> -warn=all -fcheck=all -fall-intrinsics


-fcheck=all turns on all run-time checks
(Including "array-temps" whose output is only an aid to performance tuning.)

-std=f95/f2003/f2008/f2008ts - reject vendor extensions (or newer
language features)

-fall-intrinsics does not really fall into this list. If you use
-std=f95/f2003/f2008 it actually the opposite: Instead of warning that
an intrinsic is not in the selected standard, it silently accepts vendor
intrinsics and intrinsics which are only in newer standards.


Regarding warnings: I think the following set encompasses all Fortran
warnings; there might be some more middle-end warnings, I haven't
checked - but -Wall/-Wextra should also cover most of those warnings. (*
= new in GCC 4.8, ** = before enabled by default.)

-Wall -Wextra -Wconversion-extra -Wc-binding-type*,**
-Wcharacter-truncation -Wimplicit-interface -Wsurprising -Wunderflow

(Additionally, there are the warnings which help with performance
tuning: -Warray-temporaries -Wrealloc-lhs* and -Wrealloc-lhs-all*)

-fimplicit-none - forces IMPLICIT NONE, which helps to find bugs if one
has forgotten to specify it manually.

(-pedantic can also give some diagnostic)


For a description of the flags, see the manual; e.g.
http://gcc.gnu.org/onlinedocs/gfortr...n-Summary.html - and for
general GCC flags see also
http://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html


> Which std= do you recommend to use
> for the most strict checking? i.e. if I want more checking
> done, should I use std=2008? or ? or it does not matter?


Well, the "strictest" is -std=f95 as it also rejects the features which
were added in Fortran 2003 and Fortran 2008. However, the question is
more which Fortran standard you want to use. Fortran 95 is most widely
supported but certain features of Fortran 2003 and Fortran 2008 are very
useful, but are available in fewer compilers.

I think the best choice for wide compatibility would be Fortran 95 plus
Technical Report (TR) 15581, which added allocatable components/dummy
arguments.

As gfortran does not have such a flag, -std=f2003 has to be used in that
case. But also in general, -std=f2003 is probably a good choice as
Fortran 2003 has many useful features, many of which have been
implemented in several compilers.

Using -std=f2008 (or with GCC 4.8 even -std=f2008ts) can make sense as
Fortran 2008 added some nice features. Though, the number of compilers
which support parts of Fortran 2008 is even lower.


(-std=f2008ts will allow the additions of the post-F2008 Technical
Specifications (TS), namely TS29113 on Further Interoperability of
Fortran with C and the upcoming coarray TS. Parts of TS29113 are already
implemented in gfortran - and will be used internally for the
implementation of Fortran 2003's FINAL subroutines.)

Tobias
Reply With Quote
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 07:14 PM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.