For Programmers: Free Programming Magazines  


Home > Archive > Fortran > March 2008 > KSIZE bug in Intel & Compaq compilers?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author KSIZE bug in Intel & Compaq compilers?
James Tursa

2008-03-11, 4:47 am


I think I uncovered a bug in Intel and Compaq compilers regarding the
name KSIZE. I was recompiling an older F77 program under a newer F95
compiler, specifically Intel 9.1 on PC WinXP, and got an error even
though it used to compile fine. So I wrote a minimal program that
reproduces the error, shown below:

program ksizetest1
implicit none
integer ksize
write(*,*) ksize(2)
end

integer function ksize(k)
implicit none
integer k
ksize = 4 * k
return
end

The error message I got was:

"Error: An array-valued argument is required in this context.
[KSIZE]"

and the error was pointing to the ksize(2) call.

I became suspicios as this error message sounded like an error I would
get by using the intrinsic SIZE function incorrectly, and suspected
that maybe KSIZE was a specific version of the generic SIZE function.
So I tried this:

program ksizetest2
implicit none
integer k(4,5)
write(*,*) ksize(k)
end

This program compiled fine and ran, giving the result:

20

which of course is what I would have expected from a call to the
intrinsic SIZE function.

So then I did a search through the Intel docs but found no reference
to KSIZE, and did a google search and found no references to a KSIZE
function there either. So I suspect that KSIZE is an undocumented
version of SIZE for Intel compilers, and probably for Compaq compilers
as well (I don't have one so can't verify this).

I tried the same programs on an Alpha mainframe, which I believe use
Compaq compilers, and got the same message for program ksizetest1, but
got a fatal internal comiler error message for the program ksizetest2,
asking me to report the problem.

I also tried the programs on a Sun 2500. ksizetest1 compiled and ran
fine. ksizetest2 did not compile, and I got the expected error "ksize
not declared".

And finally I tried this program:

program ksizetest3
implicit none
integer ksize(5)
data ksize /2,4,6,8,10/
write(*,*) ksize(3)
end

This program compiled and ran fine on the PC, printing the expected
result of 6. On the Alpha mainframe, however, it compiled fine but
generated a record error for every line when trying to link.

Any comments from the readers? Know of any other undocumented
name/function problems like this lurking in these compilers?

James Tursa

(P.S., I solved the original problem by simply renaming all of my
KSIZE to KKSIZE, so that is no longer an issue)
Arjen Markus

2008-03-11, 4:47 am

On 11 mrt, 08:11, James Tursa <aclassyguywithakno...@hotmail.com>
wrote:
> I think I uncovered a bug in Intel and Compaq compilers regarding the
> name KSIZE. I was recompiling an older F77 program under a newer F95
> compiler, specifically Intel 9.1 on PC WinXP, and got an error even
> though it used to compile fine. So I wrote a minimal program that
> reproduces the error, shown below:
>
> =A0 =A0 =A0 program ksizetest1
> =A0 =A0 =A0 implicit none
> =A0 =A0 =A0 integer ksize
> =A0 =A0 =A0 write(*,*) ksize(2)
> =A0 =A0 =A0 end
>
> =A0 =A0 =A0 integer function ksize(k)
> =A0 =A0 =A0 implicit none
> =A0 =A0 =A0 integer k
> =A0 =A0 =A0 ksize =3D 4 * k
> =A0 =A0 =A0 return
> =A0 =A0 =A0 end
>
> The error message I got was:


The error is not in the compiler, but in your program:
ksize is locally declared to be an integer variable, not an
integer function. Change the main program:

integer ksize
external ksize ! Makes the compiler aware an external function
! is meant, instead of a local variable

You could also do:

program ksizetest1
implicit none

write(*,*) ksize(2)

contains
integer function ksize(k)
implicit none
integer k
ksize =3D 4 * k
return
end function
end

That way the compiler will recognise that ksize is a
function without you having to resort to the external statement.

Regards,

Arjen
glen herrmannsfeldt

2008-03-11, 8:13 am

Arjen Markus wrote:

(snip)


(snip)
[color=darkred]
> The error is not in the compiler, but in your program:
> ksize is locally declared to be an integer variable, not an
> integer function. Change the main program:


In Fortran 77 there was no function declaration. Function return
types were declared the same as variables.

> integer ksize
> external ksize ! Makes the compiler aware an external function
> ! is meant, instead of a local variable


Instead of a local variable or intrinsic function.

This is always a good idea, as a new intrinsic function can always be
added to a later version of the standard. Some compilers have an
option to follow the standard without added (extension) functions.
If not, I would say the compiler is broken. If so, use that option.

-- glen

Richard Maine

2008-03-11, 7:23 pm

Arjen Markus <arjen.markus@wldelft.nl> wrote:

> On 11 mrt, 08:11, James Tursa <aclassyguywithakno...@hotmail.com>
> wrote:
>
> The error is not in the compiler, but in your program:
> ksize is locally declared to be an integer variable, not an
> integer function.


No, it is not declared to be an integer variable. In fact, there is no
explicit way to declare something to be a variable. I regard this as a
shortcoming of the language. The deduction that something is a variable
is always implicit, either from the lack of other declaration or from
the declaration of some property that is incompatible with being other
than a variable. In this case, ksize is implicitly declared to be a
function by its appearance as a function reference.

This code is standard conforming... but non-portable. You do have the
fix right (specify the external attribute or make the fuction
internal/module); just your diagnosis is wrong. The standard allows a
compiler to have additional intrinsic functions. If there is an external
function and an intrinsic function of the same name, a reference to that
name gets the intrinsic function unless you explicitly specify the
external attribute. The standard specifically recommends that programs
use the external attribute for external functions so as to avoid exactly
this kind of error. I echo that recommendation.

Neither the program nor the compiler violate the standard. But the code
is non-portable in that it won't work correctly on compilers that have
an intrinsic of that name. That is basically true of any proram that
uses external procedures without declaring them to be external. It is
just that the conflicts are rare enough that you don't get bit most of
the time.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
Ron Shepard

2008-03-11, 7:23 pm

In article <1idmq8z.11ohqzdif7pfeN%nospam@see.signature>,
nospam@see.signature (Richard Maine) wrote:

> The standard specifically recommends that programs
> use the external attribute for external functions so as to avoid exactly
> this kind of error.


This was also true for the f77 standard, so this recommendation is
about 30 years old now. Since the f90 standard (18 years ago),
there are now five different kinds of functions: intrinsic,
internal, module, statement, and external (and I'm not counting
references through dummy arguments). It might be easy for the
compiler to keep track of these without explicit declarations, but
it is much easier on humans if things are declared explicitly. And
in cases like this, it ensures that the code is portable too.

$.02 -Ron Shepard
Arjen Markus

2008-03-12, 4:46 am

On 11 mrt, 16:42, nos...@see.signature (Richard Maine) wrote:
>
> No, it is not declared to be an integer variable. In fact, there is no
> explicit way to declare something to be a variable. I regard this as a
> shortcoming of the language.


Thanks for clarifying that. It leaves me with a funny feeling
that there could be strange conflicts, beyond external and
intrinsic subroutines and functions with the same name,
but I could not come up with a plausible example.

Regards,

Arjen
Jan Vorbrüggen

2008-03-12, 4:46 am

> So then I did a search through the Intel docs but found no reference
> to KSIZE, and did a google search and found no references to a KSIZE
> function there either. So I suspect that KSIZE is an undocumented
> version of SIZE for Intel compilers, and probably for Compaq compilers
> as well (I don't have one so can't verify this).


The VAX Fortran compiler started the convention with specific versions
of intrinsics using the prefix I for longwords (32 bits), J for words
(16 bits) and K for bytes (8 bits). The DEC/Compaq/HP/Intel compiler
docs still show that, I believe, for the F77 intrinsics, such as there
are. It's probably an oversight that the extension to the F90 intrisics
wasn't (fully) documented.

IMO, they shouldn't be cluttering the compiler-internal namespace that
way - there is no reason I can think of that you would want to access
the specific of these intrinsics, just let the compiler choose them for you.

Jan
James Van Buskirk

2008-03-12, 7:32 pm

"Jan Vorbrüggen" <Jan.Vorbrueggen@not-thomson.net> wrote in message
news:fr8342$qqt$1@s1.news.oleane.net...

[color=darkred]
> The VAX Fortran compiler started the convention with specific versions of
> intrinsics using the prefix I for longwords (32 bits), J for words (16
> bits) and K for bytes (8 bits). The DEC/Compaq/HP/Intel compiler docs
> still show that, I believe, for the F77 intrinsics, such as there are.
> It's probably an oversight that the extension to the F90 intrisics wasn't
> (fully) documented.


> IMO, they shouldn't be cluttering the compiler-internal namespace that
> way - there is no reason I can think of that you would want to access the
> specific of these intrinsics, just let the compiler choose them for you.


Your memory of VAX Fortran conventions seems to be fading. I think
for VAX the convention was I for bytes, J for words, and K for
longwords. (Maybe my memory is fading too...) But looking at the
ifort docs for INT, we see that IINT is 16 bits, JINT is 32 bits, and
KINT is 64 bits. Here's an example:

C:\Program Files\Microsoft Visual Studio 8\James\clf\ksize_test>type
int_test.f9
0
program int_test
implicit none
real a(2)

a = 0
write(*,*) 'IINT ', kind(IINT(a))
write(*,*) 'JINT ', kind(JINT(a))
write(*,*) 'KINT ', kind(KINT(a))
write(*,*) 'KSIZE ', kind(KSIZE(a))
end program int_test

C:\Program Files\Microsoft Visual Studio 8\James\clf\ksize_test>ifort
int_test.f
90
Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1
Build 20061104
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.40310.39
Copyright (C) Microsoft Corporation. All rights reserved.

-out:int_test.exe
-subsystem:console
int_test.obj

C:\Program Files\Microsoft Visual Studio 8\James\clf\ksize_test>int_test
IINT 2
JINT 4
KINT 8
KSIZE 8

ifort doesn't support ISIZE nor JSIZE. Curiously, if IMPLICIT NONE
is omitted, ifort can compile syntax like

write(*,*) kind(isize(a))

but

write(*,*) isize(a)

fails at the link step. You don't need to actually invoke a
function to find out its result's KIND although you might
have to if you wanted to get its LEN or SHAPE.

KSIZE was probably implemented when Compaq decided that they
needed to be able to return INTEGER*8 values for array inquiry
functions on 64-bit machines. The other syntax they adopted, using
an OPTIONAL KIND= argument, subsequently became standard in f03.
At some stage they seem to have followed VAXish syntax to get
this KIND=8 result. Testing reveals that KINDEX, KLEN, KLEN_TRIM,
KSCAN, KVERIFY, KLBOUND, KSHAPE, KUBOUND, KCOUNT, KMAXLOC, and
KMINLOC are supported, but KLOGICAL is not. Neither is KLNBLNK.
None are documanted.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Ron Shepard

2008-03-12, 7:32 pm

In article <fr8342$qqt$1@s1.news.oleane.net>,
Jan Vorbrüggen <Jan.Vorbrueggen@not-thomson.net> wrote:

> IMO, they shouldn't be cluttering the compiler-internal namespace that
> way - there is no reason I can think of that you would want to access
> the specific of these intrinsics, just let the compiler choose them for you.


Some of them take one kind of integer as argument, and return
another kind of integer as the result. You need to reference the
specific function in these cases. You are right about the namespace
getting cluttered, but that is why intrinsic and external functions
should be declared explicitly as such.

$.02 -Ron Shepard
glen herrmannsfeldt

2008-03-12, 7:32 pm

James Van Buskirk wrote:

(snip)

> Your memory of VAX Fortran conventions seems to be fading. I think
> for VAX the convention was I for bytes, J for words, and K for
> longwords. (Maybe my memory is fading too...) But looking at the
> ifort docs for INT, we see that IINT is 16 bits, JINT is 32 bits, and
> KINT is 64 bits. Here's an example:


It may have come from PDP-11 Fortran before VAX, though technically
VAX is a branch of the PDP-11 family.

The PDP-11 Fortran IV compilers used 16 bit arithmetic for INTEGER
variables, normally storing them in one 16 bit word. For standard
compatibility, they could be stored in two words, but only one word
was actually used. The I names would naturally refer to the
INTEGER*2 versions. When 32 bit arithmetic was added, the J
functions were added to process them.

The RT-11 Fortran 77 compiler seems to have IINT (INTEGER*2) and
JINT (INTEGER*4), in addition to versions of the more traditional
IFIX, IIFIX and JIFIX.

As noted by others, the specific versions are needed where the result
type can't be determined from the argument, IINT and JINT being
examples. (As usual, the result type is not determined from context,
even when it seems obvious to the programmer. This was especially
true for the 16 bit PDP-11 where the overhead for 32 bit arithmetic
is fairly high.) The specific versions are also needed for the
compiler to call once it figures out which one is needed when
the generic name is used. (Many are real external routines.)

-- glen

Jan Vorbrüggen

2008-03-12, 7:32 pm

> As noted by others, the specific versions are needed where the result
> type can't be determined from the argument, IINT and JINT being
> examples.


Yeah, I hadn't thought of those. The proper reaction, IMNSHO, by the
compiler in such cases would be to warn the user that he will not be
accessing the intrinsic. No, it doesn't need to behave the same way as
for the standard-mandated intrinsic generics.

> The specific versions are also needed for the
> compiler to call once it figures out which one is needed when
> the generic name is used. (Many are real external routines.)


Due to the compiler support libraries or RTL usually being linked last,
this is not a problem if such a symbol is overridden by the programmer.

Jan
Steve Lionel

2008-03-12, 7:32 pm

On Mar 12, 1:53 pm, Jan Vorbr=FCggen <Jan.Vorbrueg...@not-thomson.net>
wrote:

> Yeah, I hadn't thought of those. The proper reaction, IMNSHO, by the
> compiler in such cases would be to warn the user that he will not be
> accessing the intrinsic. No, it doesn't need to behave the same way as
> for the standard-mandated intrinsic generics.


Actually, no. The standard allows a compiler to support additional
intrinsics. It should provide such a warning if a non-standard
intrinsic is used and standards checking is requested.

However, the behavior of ifort (and CVF) here is clearly not correct.
KSIZE would be a specific function returning an INTEGER(8) result. If
you declare it as having a different data type, I would expect some
sort of error. I'll bring this up to the ifort team.

If you want to avoid conflicts with potential non-standard intrinsics,
use EXTERNAL or, better, an explicit interface.

>
>
> Due to the compiler support libraries or RTL usually being linked last,
> this is not a problem if such a symbol is overridden by the programmer.


It generally isn't an issue at all - at least with the compilers I
have used - in that the actual linker name of the routine for
intrinsics has some sort of prefix or suffix that moves it out of the
"user namespace". Some platforms handle this better than others, of
course.

Steve
Steve Lionel

2008-03-12, 7:32 pm

On Mar 12, 3:37 pm, Steve Lionel <steve.lio...@intel.com> wrote:

> However, the behavior of ifort (and CVF) here is clearly not correct.
> KSIZE would be a specific function returning an INTEGER(8) result. If
> you declare it as having a different data type, I would expect some
> sort of error. I'll bring this up to the ifort team.


I did some more digging and it would appear that KSIZE is a leftover
table entry that should have been removed. To support this notion, I
see that the compiler does not recognize ISIZE nor JSIZE, which I
would expect it to if KSIZE was to be supported.

I'm unable to find wording in the standard that prohibits giving an
intrinsic a different type than is predefined.

Steve
Richard Maine

2008-03-12, 7:32 pm

Steve Lionel <steve.lionel@intel.com> wrote:

> I'm unable to find wording in the standard that prohibits giving an
> intrinsic a different type than is predefined.


In fact, for generic intrinsics, the standard specifically allows that.
There is a somewhat subtle statement somewhere, something along the line
of saying that a type declaration does not remove the generic property.
Thus, for example, it is perfectly valid (confusing, but valid) to do
something like

double precision sqrt
write (*,*) sqrt(2.0)

This should do a single precision sqrt. The double precision declaration
does nothing useful. Yes, there is a double precision version of the
generic sqrt, but that's not what the sqrt(2.0) invokes.

I'm not so sure about things like

character sqrt
write (*,*) sqrt(2.0)

I vaguely recall there being an interp about that one, but I don't
recall the answer - whether the declaration constitutes an error because
there is no character version of sqrt, or whether the declaration is
really completely useless. It is too stupid a thing to do for it to be a
issue for "real" programs, but compiler writers and compiler testers
need to know which answer is "right". I suppose it could concievably
matter in cases where some vendors add additional specifics for a
generic, in which case, the declaration might be a way to assert that
you want to at least be sure that such a specific exists, but that's a
bit marginal as utility goes.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
Steve Lionel

2008-03-12, 7:32 pm

On Mar 12, 4:35 pm, nos...@see.signature (Richard Maine) wrote:

> There is a somewhat subtle statement somewhere, something along the line
> of saying that a type declaration does not remove the generic property.


That would be this text on p74 of F2003:

9 A name that identifies a specific intrinsic function in a scoping
unit has a type as specified in 13.6. An
10 explicit type declaration statement is not required; however, it is
permitted. Specifying a type for a
11 generic intrinsic function name in a type declaration statement is
not sufficient, by itself, to remove the
12 generic properties from that function.

I could not get a sense from this what it meant if the type didn't
match, nor if the function name was NOT generic.

I don't have a problem with the intended (?) behavior to ignore the
type declaration for the intrinsic, but it just seems a bit weird.

Steve
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com