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

warning #8860: The IMPORT statement specified is not standard Fortran 2008.

DataScientist
Valued Contributor I
847 Views

Is the ifort warning given in the title correct? I thought IMPORT was already part of the Fortran 2008 standard.  The IMPORT statement used is something like the following:

import  :: This_type
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.4.245 Build 20190417
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

warning #8860: The IMPORT statement specified is not standard Fortran 2008.
        import :: This_type

 

0 Kudos
16 Replies
DataScientist
Valued Contributor I
847 Views

Update: It seems like the warning is issued when the import statement is unnecessary,  that is, the IMPORTed entity is not used in the interface. Does this warning message then imply that unnecessary IMPORT is illegal in Fortran 2008?

0 Kudos
FortranFan
Honored Contributor II
847 Views

A. King wrote:

Update: It seems like the warning is issued when the import statement is unnecessary,  that is, the IMPORTed entity is not used in the interface. Does this warning message then imply that unnecessary IMPORT is illegal in Fortran 2008?

Fortran standard, starting with the 2008 revision, states IMPORT statements shall not be present in several scoping units: main program, modules, external subprograms, and block data.  It's a good thing Intel Fortran issues the warning as mentioned in this thread.

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

On one of the other threads a user had an issue in a mixed C++/Fortran program whereby the user desired to have a global variable declared and initialized in C++ then referenced in Fortran.

While DLLIMPORT can be used, or at least could have been used on Windows systems, but is (now) non-compliant with the standards.

Also, unfortunately, EXTERNAL cannot be used to declare a variable with external linkage.

I think what this leaves to the user for external linkage is to use a named COMMON. But this flies against the intentions of the standards committee to depreciate COMMON from the language. Or alternatively use a get/put function call.

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
847 Views

Show more code.

F2018 permits the import statement to appear in additional contexts to F2008 and F2003.  Perhaps the warned about statement is being used in one of those additional contexts (in which case, if you have asked for F2008 compliance warnings - the warning is correct), or perhaps the compiler is a little confused as a result of the changes to it to handle import in those additional contexts.

But we don't know the context that the problematic statement is being used in without seeing that context.

 

(The Fortran import statement has nothing to do with DLLs - it controls host association in a scoping unit.  The DLLIMPORT attribute that ifort offers as an extension has never been part of the standard - it can't be - the concept of a DLL is not covered by the standard.  Language standard methods exist to combine Fortran and C/C++ code, these methods don't require DLLs, nor do they require use of common.)

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

IanH,

Correct me if I am wrong...

In the "a user had an issue in a mixed C++/Fortran program whereby the user desired to have a global variable declared and initialized in C++ then referenced in Fortran." case, the Fortran IMPORT cannot be used because it applies outer (host) scoping unit (IOW Fortran scoping unit) and not to an external variable provided by C++.

This would then seem to leave using a named COMMON to "import" a symbol (variable) from C/C++.

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
847 Views

Import just controls host association into a scoping unit from its host.  It is orthogonal to combining C/Fortran code. 

It is very typical for a Fortran module variable to be bound to a C global variable (no common in sight), and for that Fortran module variable to then be host associated in child scoping units.  Pre F2018, host association applied by default, F2018 just gives you more control over host association - you can say "no thanks - I don't want all the host variables to be visible in this scoping unit - I just want these specific ones".  What used to work in F2003 and F2008 still continues to work.

(Which specific thread are you talking about in terms of C/Fortran issues?  There was one recently where someone was trying to initialize a variable in both Fortran and C at the same time, but obviously that has issues.)

0 Kudos
FortranFan
Honored Contributor II
847 Views

A. King wrote:

Update: It seems like the warning is issued when the import statement is unnecessary,  that is, the IMPORTed entity is not used in the interface. Does this warning message then imply that unnecessary IMPORT is illegal in Fortran 2008?

Consider the following:

C:\Temp>type p.f90
   import
end

C:\Temp>ifort /c /standard-semantics p.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version
19.0.5.281 Build 20190815
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

p.f90(1): error #8851: An IMPORT statement may not appear in the scoping unit of a main-program, external subprogram, module, or block-data.
   import
---^
compilation aborted for p.f90 (code 1)

C:\Temp>

The error message shown above essentially has the same wording as constraint C896 (in section 8.8 IMPORT statement) of the standard.  Given the constraint, a standard-conforming processor is required to issue the diagnostic.  It's good to see Intel Fortran compiler do so.

0 Kudos
FortranFan
Honored Contributor II
847 Views

jimdempseyatthecove (Blackbelt) wrote:

On one of the other threads a user had an issue in a mixed C++/Fortran program whereby the user desired to have a global variable declared and initialized in C++ then referenced in Fortran...

Jim, if you're referring to this thread (https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/827546) , the indications are all about C, not C++.  I say this because, as you know, the Fortran standard only includes interoperability with a companion C processor, it makes no mention of C++.

Just a check: have you referred to section 18.9 Interoperation with C global variables in the Fortran standard?

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

>>the indications are all about C, not C++.

In a C++ program:

    extern int foo=1234;

generates an undecorated external symbol (IOW makes no difference if extern included "C").

>>have you referred to section 18.9 Interoperation with C global variables in the Fortran standard?

I was using the Intel 19.0 documentation https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-global-data-overview

In the other thread, the poster had an issue where the external (global) symbol was declared and initialized on the C side (actually C++ source), an attempted to be referenced by the Fortran side. The issue he had was that this resulted in a link time error of having the same symbol defined twice. Which implies that the Fortran side provided a placeholder containing uninitialized data.

Note, that when the C (C++) declared extern variable is .NOT. initialized in C/C++, that there is no issue with the Fortran side provided placeholder containing either initialized or uninitialized data.

I haven't run a test of this, but I assume in the case of an extern int with initialization on C/C++ will work using the named common as outlined in the Intel v19.0 link above.

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

Additionally, my "theory" as to why the named common technique will work for the external C declared and initialized variable is that in Fortran, a procedure with a named COMMON without corresponding DATA initialization can reference an external Fortran procedure with the same named COMMON and containing a corresponding DATA initialization.

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
847 Views

jimdempseyatthecove (Blackbelt) wrote:

In the other thread, the poster had an issue where the external (global) symbol was declared and initialized on the C side (actually C++ source), an attempted to be referenced by the Fortran side. The issue he had was that this resulted in a link time error of having the same symbol defined twice. Which implies that the Fortran side provided a placeholder containing uninitialized data.

...and this has nothing to do with an import statement.

(In the recent thread "C interoperability, passing constants", the variable was being initialized by both languages (to different values!), hence the linker complained.)

 

0 Kudos
FortranFan
Honored Contributor II
847 Views

jimdempseyatthecove (Blackbelt) wrote:

Additionally, my "theory" as to why the named common technique will work for the external C declared and initialized variable is that in Fortran, a procedure with a named COMMON without corresponding DATA initialization can reference an external Fortran procedure with the same named COMMON and containing a corresponding DATA initialization.

Jim Dempsey

Jim,

To some extent, you're trying to conflate what are OS and linker-specific aspects (which, by the way, are extraneous to the Fortran standard the way it sees itself) with Fortran language and processor considerations in terms of entities and their scope and which generally pertain to complie-time.

To address the aspects you bring up, consider the following C++ main and a Fortran module:

#include <iostream>
using namespace std;

extern "C" {
   extern const int bar;    //<--- I1
   void Fsub( void );
   int16_t foo( int16_t );  //<--- I2
}
//extern const int bar;  //<--- O1
//int16_t foo(int16_t);  //<--- O2

int main(void)
{
   Fsub();
   return EXIT_SUCCESS;
}

int16_t foo(int16_t i) {
   cout << "bar = " << bar << endl;
   return ++i;
}
module m
   use, intrinsic :: iso_c_binding, only : IK => c_int
   integer(IK), bind(C, name="bar"), protected :: bar = 42
   interface
      function foo( x ) result(r) bind(C, name="foo")
         use, intrinsic :: iso_c_binding, only : IK => c_int16_t
         import, none
         implicit none
         integer(IK), intent(in), value :: x
         integer(IK) :: r
      end function
   end interface
contains
   subroutine Fsub() bind(C, name="Fsub")
      use, intrinsic :: iso_c_binding, only : IK => c_int16_t
      import, only : foo
      print *, "Hello World!"
      print *, "foo = ", foo( 1_ik )
   end subroutine
end module

Following compilation and linking, the execution:

C:\Temp>type f.f90
module m
   use, intrinsic :: iso_c_binding, only : IK => c_int
   integer(IK), bind(C, name="bar"), protected :: bar = 42
   interface
      function foo( x ) result(r) bind(C, name="foo")
         use, intrinsic :: iso_c_binding, only : IK => c_int16_t
         import, none
         implicit none
         integer(IK), intent(in), value :: x
         integer(IK) :: r
      end function
   end interface
contains
   subroutine Fsub() bind(C, name="Fsub")
      use, intrinsic :: iso_c_binding, only : IK => c_int16_t
      import, only : foo
      print *, "Hello World!"
      print *, "foo = ", foo( 1_ik )
   end subroutine
end module

C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 f.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.5.281 Build 20190815
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.


C:\Temp>type c++.cpp
#include <iostream>
using namespace std;

extern "C" {
   extern const int bar;    //<--- I1
   void Fsub( void );
   int16_t foo( int16_t );  //<--- I2
}
//extern const int bar;  //<--- O1
//int16_t foo(int16_t);  //<--- O2

int main(void)
{
   Fsub();
   return EXIT_SUCCESS;
}

int16_t foo(int16_t i) {
   cout << "bar = " << bar << endl;
   return ++i;
}

C:\Temp>cl /c /W4 /EHsc c++.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.23.28106.4 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

c++.cpp

C:\Temp>link c++.obj f.obj /subsystem:console /out:c++.exe
Microsoft (R) Incremental Linker Version 14.23.28106.4
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>c++.exe
 Hello World!
bar = 42
 foo =  2

C:\Temp>

Now in the above C++ code, you can comment out lines marked I1 and I2 and uncomment lines marked O1 and O2 and try to compile and link to see what happens.  As you know, Fortran standard essentially only provides interoperability with C, not C++ and thus, you will note the relevance of extern "C".

Also, in the Fortran module, you can review how IMPORT is used to effectively inform the Fortran processor the specifics of data types, interfaces, etc.  But note this is not essential: the bulk of FORTRAN 77 is still supported by the current standard and one can adopt a Flintstones' era coding style and still get the code to link.  It's just that if one wants to use all the extra "bladeguards" introduced later in the language such as INTERFACE blocks and improved facilities such as procedures in CONTAINS sections and BLOCK constructs, IMPORT allows better control over the so-called 'host association" during compilation; it doesn't really come into play during linking.  

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

FF,

Your line 5 in the first section of the C/C++ code and line 3 in the Fortran code are not compliant with the issue presented. To be compliant with the issue you will have to initialize bar on the C side

extern const int bar = 42; // and remove the bar = 42 on the Fortran side

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

About IMPORT

As documented in example sub1 on https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-import

I find IMPORT (to parody Seinfeld) from bizarro-land. By this I mean it is a verb describing the actions on outer scoped variables .NOT. listed, and no action on those outer scoped variables listed.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor II
847 Views

jimdempseyatthecove (Blackbelt) wrote:

FF,

Your line 5 in the first section of the C/C++ code and line 3 in the Fortran code are not compliant with the issue presented. To be compliant with the issue you will have to initialize bar on the C side

extern const int bar = 42; // and remove the bar = 42 on the Fortran side

Jim Dempsey

What's your point?  Did you try the code in Quote #13 by yourself and try to switch around the locale of initialization and recheck?

Unless one demands the Fortran processor to do something in a manner extraneous to the Fortran standard such as with an initialization instruction e.g., via some compiler option (/Qinit?) which then conflicts with a diktat in the Fortran standard "A variable, or part of a variable, shall not be explicitly initialized more than once in a program", I fail to see any issue here?  

0 Kudos
jimdempseyatthecove
Honored Contributor III
847 Views

My bad.... Intel V19u3 (on Windows) does work with the initialization made on the C side using your example (modified for initialization).

Jim Dempsey

0 Kudos
Reply