Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Conflicting definitions of NULL

markus
Beginner
2,347 Views

I have a (rather old, created with Digital Visual Fortran) win32 gui program which I compile now and then (with current versions of Intel Fortran).
Now it failed to compile with:

WGUTIL.F90(127): error #7112: This actual argument must not be the name of a procedure.   [NULL]
       ret=RegOpenKeyEx(HKEY_CURRENT_USER,C_SOFTWARE,NULL,  &

Obviously there is a conflict between INTEGER, PARAMETER :: NULL = 0 (somewhere in the win api modules, ifwinty actually) and the intrinsic function NULL().

To demonstrate this I have included here a demo code NULL-Intrinsic.f90.

The conflicting definitions in the demo are in module wintypes (INTEGER, PARAMETER :: NULL = 0) and in module dyndef, type declaration of dynstring_ (character(len=1), pointer :: s(:) => NULL()).

My questions:

1) The elements of derived type dynstring_ are declared private. Why does the definition of NULL() leak out there? Is this a compiler error? Is the Fortran standard precise enough to define such things?

2) The real program consists of about 10 source files (and approximately the same number of modules). The win32 api defines more than a dozen modules and I have a "utility" library with about 100 modules. So it took me some time to find out, from where the conflicting definitions came. Is there some aid in the compiler to help in such situations? Something like a cross reference or similar which tells from where type defnitions come from?

Markus

0 Kudos
17 Replies
IanH
Honored Contributor II
2,347 Views
(Your working code is missing an end statement.) How current a current Intel Fortran? I get an error about conflicting declarations with 13.0.0, which is what I'd (now) expect after a recent discussion on c.l.f that surprised me at the time (and I see there have been historical discussion on similar topics). The components of the derived type are private in your example, but the module entities are not. That means that anything "known" in the specification section of the module that isn't explicitly made private, including any intrinsic procedure used in the specification section, is a public entity of the module. This reinforced for me that good coding practice is to have a private statement in a module's specification part, and only explicitly make public the things that you really want to. So do that - pop a private statement in module dyndef (in the module itself, not in the derived type - you'll also need public :: init_p) to make your problem go away.
0 Kudos
IanH
Honored Contributor II
2,347 Views
Well, now I'm going to contradict myself, because the scoping unit that has the NULL() intrinsic is not the module's scoping unit (it's a nested scoping unit of the module's scoping unit), so the intrinsic NULL() shouldn't leak out, but regardless - use a private statement and avoid all this hapless confusion!
0 Kudos
Steven_L_Intel1
Employee
2,347 Views
I respectfully disagree with Ian - with some hesitation because he is almost always right when it comes to language issues. Not this time, I fear... In the "not working" case, NULL is used in an initialization expression while declaring the derived type dynstring_. It does not matter that the component being declared is private - that doesn't make references in initialization expressions private. The use of NULL is an implicit declaration of the NULL intrinsic and this does "leak out" of the module, since it is in module scope. It is NOT the use of NULL in the subroutine that is the problem, as noted in the comments. As for DVF/CVF, here is what CVF 6.6 does: [plain] C:\Projects>df /c null-intrinsic.f90 /fpp Compaq Visual Fortran Optimizing Compiler Version 6.6 (Update C) Copyright 2003 Compaq Computer Corp. All rights reserved. Compaq (R) Fortran Preprocessor Version 6.6-25 Copyright 2001 Compaq Computer Corporation. null-intrinsic.i90 null-intrinsic.f90(42) : Error: The same named entity from different modules and /or program units cannot be referenced. [NULL] write(*,*) 'NULL = ', null ------------------------^ null-intrinsic.f90(42) : Error: This name has already been used as an intrinsic function name. [NULL] write(*,*) 'NULL = ', null ------------------------^ [/plain] The compiler is correct. I agree that it would be nice if the compiler would help you identify the conflicting module - I will enter a feature request for this.
0 Kudos
Steven_L_Intel1
Employee
2,347 Views
I think our posts overlapped. The reference to NULL() is an implicit declaration of it, the same as if you had used a variable without declaring it. According to the standard, referencing an intrinsic procedure establishes its name as intrinsic in the scope where it appears.
0 Kudos
markus
Beginner
2,347 Views
[Edit: This is a response to IanH Mon, 10/15/2012 - 08:41 Steve's post crossed my answer. Don't be confused! ] First, thanks for your help! Regarding to your second post, it is a compiler error, isn't it? But: I don't share your opinion about "declaring everything". This is not Fortran style! Fortran style is to define only non default attributes. Or do you define i, j and n as integer? That said, there are two possible ways: Use the standalone statement "public" to set the default and define anything not public via private attributes. Or, secondly, the same the other way around. This are the obvious options if you look at the compiler documents. The problem here is the intrinsic function NULL(). It is not _defined_ within the module (so the private/public declaration rules do not apply), but it is _referenced_. Seems such references are not honored correctly. This seems to be a flaw in the compiler(s). I ran the tests with good old CVF also and it behaves the same. Maybe I try it with CFAL on my DS20, but I'm rather sure it will be the same!. Markus
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,347 Views
As a work-around Use FPP Add -DNULL=NULL_POINTER (define NULL_POINTER appropriately) Find and replace NULL() with null() You might look for "NULL{whitespace}(" as well This is a hack for sure. Jim Dempsey
0 Kudos
JVanB
Valued Contributor II
2,347 Views
I think the only thing you can do is to make the default accessibility PRIVATE in all modules and then declare everything you want to leak out as PUBLIC. Does ifort handle the attached programs correctly? By the discussion of this thread it should accept all except use5.f90, right?
0 Kudos
IanH
Honored Contributor II
2,347 Views
(I agree that the private components statement isn't relevant here.) This whole thing surprised (and disappointed) me when I read the c.l.f discussion, so I'm not going to pretend I really have a clue what's supposed to happen, but the reference to NULL isn't in the scope of the module, it is in the scope of the derived type definition (and the scoping unit of the module excludes "any scoping units in it"). If NULL() was used in an initialisation expression for a module variable (the declaration of the module variable being in the scoping unit of the module) then I'd have to agree with Steve - but the realisation that there was a difference in scoping unit is what made me repost above. I most surely do define i, j and n as integer, nearly all my modules have private accessibility by default.
0 Kudos
markus
Beginner
2,347 Views
I solved my problem by inserting a global private statement and declaring anything needed from outside public. (In the real program, not in the example code here, of course. It took some try and error compilation and link runs to identify those global items). Now I can use INTEGER, PARAMETER :: NULL = 0 again without the renaming technique (BTW: Look at iflogm.f90, module iflogm included with the compiler. They use the same trick: use ifwinty, NULLPTR => NULL). Just for clarification: The compilation error did not arise from changing compilers (as my first post may be interpreted). I added the dynstring module to my library more than a year ago so I was somewhat puzzled about the compiler error occuring recently. That's why I asked whether the compiler can help to detect the origin of conflicting declarations. But still, I don't understand why NULL() is in the scope of module dyndef and not in the scope of type dynstring.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,347 Views
The IVF documentation suggests: If you use module IFWIN or IFWINTY, you will have a name conflict if you use the NULL intrinsic. To avoid this problem, rename the integer parameter constant NULL to something else; for example: USE IFWIN, NULL0 => NULL This example lets you use both NULL0 and NULL( ) in the same program unit with no conflict. This will require you editing your CALLs with NULL to NULL0 (or NULL_POINTER, or NULL_C_PTR which may be more self explanitory). Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
2,347 Views
IanH wrote:

(I agree that the private components statement isn't relevant here.)

This whole thing surprised (and disappointed) me when I read the c.l.f discussion, so I'm not going to pretend I really have a clue what's supposed to happen, but the reference to NULL isn't in the scope of the module, it is in the scope of the derived type definition (and the scoping unit of the module excludes "any scoping units in it").

I agree that this is somewhat confusing in the standard. The text in the standard regarding implicit declarations in the context of type definitions was the subject of interpretation F03/0123 and the resulting edit incorporated in F2008 Corrigendum 1. Intel Fortran interprets this correctly. [plain] NUMBER: F03/0123 TITLE: Implicit typing in derived types KEYWORDS: Derived types, implicit typing DEFECT TYPE: Erratum STATUS: Passed by WG5 letter ballot QUESTION: Consider the program PROGRAM MAIN TYPE T INTEGER :: I = BIT_SIZE(J) END TYPE ! J = 0 CALL SUBR1 CONTAINS SUBROUTINE SUBR1 J = 1 CALL SUBR2 PRINT *, J END SUBROUTINE SUBROUTINE SUBR2 J = 2 END SUBROUTINE END Q1. Is this program standard-conforming? (In particular, is it permitted to have the first, or only, appearance of a local variable name appear within a type definition. The definition of implicit typing says that J is explicitly declared within T.) Q2. (a) If not, is it standard-conforming if the comment "! J = 0" is turned into the assignment statement "J = 0"? (b) If it is standard-conforming, what does it print? (If J is a local variable of MAIN, it should print 2.) ANSWER: A1. Yes, the program is standard-conforming. The definition of implicit typing is erroneous - J is a local entity of MAIN. An edit is supplied to correct this error. A2. (a) Not applicable. (b) The program will print the value 2. EDITS to 10-007r1: [109:22-23] In 5.5p4, After "The data entity is treated as if it were declared in an explicit type declaration" replace "in" with "; if", then after "the outermost inclusive scope in which it appears" insert "is not a type definition, it is declared in that scope, otherwise it is declared in the host of that scope". Note: This makes the whole sentence read "The data entity is treated as if it were declared in an explicit type declaration; if the outermost inclusive scope in which it appears is not a type definition, it is declared in that scope, otherwise it is declared in the host of that scope". [/plain]
0 Kudos
markus
Beginner
2,347 Views
Okay, since we now we have the authoritative definition, can some lawyer please translate it to us ;-) Excerpt from the example code: module dyndef integer, pointer :: p(:) type, public :: dynstring_ private ! Though private here NULL() is visible as intrinsic function from outside character(len=1), pointer :: s(:) => NULL() integer n end type contains subroutine init_p ! Using NULL() here does not leak the definition as intrinsic to outside p => NULL() end subroutine end module What is the "outermost inclusive scope" of NULL()? Is it type dynstring? [I am irritated about the word "outermost". I would have expected "innermost", meaning "as tight as possible". I'm not sure if I catch the (english) meaning of the standard right.] What is the motivation of the standard to declare implicit type declarations in the host scope if the scope is a type definition?
0 Kudos
Steven_L_Intel1
Employee
2,347 Views
All this means is that references to "data entities" (and intrinsic functions are included in these) inside type declarations create implicit declarations in the scoping unit in which the type declaration appears (assuming the entity is not already declared). The scoping unit could be a program unit or a BLOCK (a F2008 feature we don't yet support). So in the context of your program, Markus, the appearance of NULL() in the initialization expression is an implicit declaration of NULL as an intrinsic function in the scope of module dyndef, NOT in type dynstring. The confusion arises because the F2008 standard includes "type declaration" as one kind of scoping unit, and the mess results from that. This interpretation clarifies that, for the purpose of implicit declarations, the scope of an implicit declaration inside a type definition is the BLOCK or program unit containing the type definition.
0 Kudos
IanH
Honored Contributor II
2,347 Views
Thanks for the explanation. Dare I ask what you think of RO's examples with the intrinsic operator in the only clause?
0 Kudos
Steven_L_Intel1
Employee
2,347 Views
Regarding RO's test programs: 1. Doesn't compile because ifort doesn't yet support SUM in an initialization expression. 2. Not legal, as far as I can tell. This is an entertaining example, though, as many of RO's are. There is no defined generic spec for OPERATOR(+) in module mod2. Operators are not data entities. 3. Same as #2. 4. This is fine - program prints F 5. Ooooh, I like it! But ifort doesn't, complaining that "Intrinsic operator can not be used on the right hand side of an OPERATOR rename clause". Looks like a bug to me - I think this should work. 6. TYPE(INTEGER) is not legal - this has to be a derived type.
0 Kudos
IanH
Honored Contributor II
2,347 Views
It was 2 and 3 that I wondered about. If they are allowed they are not terribly useful, because they don't change program interpretation at all. 5 is ruled out by the syntax rules for defined operators - so things that look like the intrinsic operators are not allowed in a rename. The syntax TYPE(integer) is ok in F2008, whether the type is something that is a public entity of the module was the basis of the recent c.l.f discussion. I think the conclusion was that it was more important for everyone to have a good lie down first.
0 Kudos
Steven_L_Intel1
Employee
2,347 Views
Ah, I had missed the bit about "not being the same as any intrinsic operator". Thanks for pointing that out.
0 Kudos
Reply