Problem after XE 15.0.0.108 install

Problem after XE 15.0.0.108 install

After  the install some code I has gave a number of build errors most of which are now resolved but there are a few things I really do not understand. Consider the source below which is a  simple pared down to the bare bones example... 

program Console4
    use OpenGL_GLU
    implicit none
    real(8)    :: rad=1.0_8
    real(8)    :: fred=0.0_8
    integer(4) :: slices=16
    integer(4) :: loops=2 
    integer(4) :: quad=1234  
    call gludisk(quad, fred, rad, slices, loops) 
end program Console4


!DEC$ objcomment lib:"glu32.lib"
MODULE OpenGL_GLU
    PUBLIC :: gluDisk
    INTERFACE
        SUBROUTINE gluDisk(quad, inner, outer, slices, loops)                         
            !DEC$ ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS:"gluDisk" :: gluDisk
            IMPORT
            INTEGER(4) :: slices
            INTEGER(4) :: loops
            REAL(8)    :: inner
            REAL(8)    :: outer
            integer(4) :: quad
        END SUBROUTINE gluDisk
    END INTERFACE
END MODULE OpenGL_GLU

The above are two separate source files for a x32 build (I will post the build log to the thread).  I get the error:

Console4.obj : error LNK2019: unresolved external symbol _gluDisk@20 referenced in function _MAIN__

I set the link to verbose to check that glu32.lib was actually searched and where the lib used resided. If I do a dumpbin of that LIB the symbol  is   _gluDisk@28 which is what I would expect as we have 2*8 + 3*4  = 28bytes on the call. Where are things going wrong????

 

31 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Build log attached I(I hope)

Attachments: 

AttachmentSize
Download BuildLog_2.txt12.84 KB

REFERENCE ?

(as in querying the keyword on line 18...  that's not a request for a citation...)

All passed by value including the quad object 'pointer' I think their-in lies the problem though as I am looking at the thread for some compiler changes to passing by value.

Got It! The original code had:

SUBROUTINE gluDisk(quad, inner, outer, slices, loops)                         
    !DEC$ ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS:"gluDisk" :: gluDisk
    IMPORT
    INTEGER(GLint), VALUE       :: slices, loops
    REAL(GLdouble), VALUE       :: inner, outer
    !TYPE(C_PTR), VALUE         :: quad
    integer(C_INTPTR_T), VALUE  :: quad
END SUBROUTINE gluDisk

 

The pesky refererence does nothing as the value attribute is applied. This gives a correct interface on 13 but not on 15 and now I can fix it! Strange how you can look hard at things and be blind to what is in front of you! Thank for the pointer Mr H.

ninja'd

The change in meaning for VALUE when not used in conjunction with BIND(C) is discussed in the release notes. This was done to conform to the standard. 

Steve - Intel Developer Support

Quote:

Steve Lionel (Intel) wrote:

The change in meaning for VALUE when not used in conjunction with BIND(C) is discussed in the release notes. This was done to conform to the standard. 

I noted that thanks.

As BIND(C) and ATTRIBUTE STDCALL are now permitted, is there any change with the problem of passing the derived type C_PTR now?

We fixed the C_PTR problem quite a while ago. Do note that adding STDCALL to BIND(C) changes only the calling convention (and name decoration) - it doesn't have any of the other effects of STDCALL used without BIND(C). The mixed-language programming section of the documentation was revised to reflect this.

Steve - Intel Developer Support

So we are supposed to use !DEC$ ATTRIBUTES VALUE rather than standard Fortran VALUE attribute for arguments to !DEC$ ATTRIBUTES STDCALL procedures unless BIND(C) is also declared as an attribute in which case either usage would be fine, right?

If !DEC$ ATTRIBUTES STDCALL is declared along with BIND(C) and we don't want decoration, we then must add !DEC$ ATTRIBUTES NODECORATE, correct?

BTW Steve, how do you get 170 X 30 pixels when the most the rest of us can get is 100 pixels in either direction?  The way it should work is that clicking on the thumbnail in the forum post should take the user to the appropriate profile page (as it does now) but that clicking on the (possibly slightly higher resolution) thumbnail in the profile page should take the user to the beautiful high-resolution action picture that was actually uploaded rather than repeating the view of the thumbnail.

If BIND(C) is not specified, then ATTRIBUTES STDCALL implies ATTRIBUTES VALUE - same as it always did. The only thing we changed was to allow you to now specify ATTRIBUTES STDCALL when BIND(C) was also specified - before that was an error.

The idea was that BIND(C) provides a standard-way of defining an interface, including pass-by-value, but we didn't allow that with STDCALL meaning that if you wanted to declare a Windows API routine you had to use a complex ATTRIBUTES directive. gfortran allowed their verson of ATTRIBUTES STDCALL with BIND(C) and, while initially we didn't think that was a good idea, we came around to it eventually.

If you don't want decoration, then don't use BIND(C), because that always decorates, as specified by the standard (in that it does exactly what the companion C processor would do.) You can change the spelling and case of the name using NAME= in BIND(C), but you can't change the decoration. We don't allow ALIAS, DECORATE or NODECORATE (is there such a thing? I didn't think so) with BIND(C).

You can see a picture of me? All I see is a broken image - a problem I keep having from time to time.

Steve - Intel Developer Support

But isn't the Fortran standard VALUE attribute different from !DEC$ ATTRIBUTES VALUE in that the former is actually pass by reference to a temporary copy unless the callee is BIND(C) whereas the latter is true pass by value?  That was the issue in Post #5 as I understood it because the !DEC$ ATTRIBUTES REFERENCE part reset the default so it was no longer !DEC$ ATTRIBUTES VALUE and the specification-part of the procedure then declared the Fortran standard VALUE attribute for all dummy arguments so that they were passed by reference to temporary copies.  Had app4619 instead declared all dummy arguments individually to be !DEC$ ATTRIBUTES VALUE everything should have worked OK even though the default for the procedure was !DEC$ ATTRIBUTES REFERENCE, is that right?  Is it permitted to declare a variable to have the Fortran standard VALUE attribute and at the same time declare it with !DEC$ ATTRIBUTES VALUE, or does the compiler properly ICE at the thought of this? For a !DEC$ ATTRIBUTES STDCALL procedure without the !DEC$ ATTRIBUTES REFERENCE or BIND(C) attribute, can the programmer declare a dummy argument with the Fortran standard VALUE attribute, and if so will the actual argument be passed by reference to a temporary copy or truly by value?

I've never seen a STDCALL procedure without decoration, but if you needed it you would be out of luck in gfortran and there seems to be no documented !DEC$ ATTRIBUTES NODECORATE in ifort, either.

Your picture is blank to me as well, but right-clicking and selecting Properties I get 75 X 13 pixels in your posts and 170 X 30 pixels in your profile page.

For what it is worth I ended up with:

PUBLIC :: gluDisk
INTERFACE
SUBROUTINE gluDisk(quad, inner, outer, slices, loops) BIND(C,NAME="gluDisk")                        
    !DEC$ ATTRIBUTES STDCALL :: gluDisk
    IMPORT
    INTEGER(GLint), VALUE       :: slices, loops
    REAL(GLdouble), VALUE       :: inner, outer
    !TYPE(C_PTR), VALUE         :: quad
    integer(C_INTPTR_T), VALUE  :: quad
END SUBROUTINE gluDisk
END INTERFACE

On the ground that it seemed the least non-standard if that makes sense. That works but I have not tested x64 and I am still not 100% sure of the correctness!

@ app4619: yeah, that's what you would have gotten had you searched the web for gfortran interfaces such as in http://home.comcast.net/~kmbtib/Fortran_stuff/example3.zip and duplicated the !GCC$ lines as !DEC$ lines, so that now the code should work both in gfortran and ifort, 32- and 64-bit modes.

Quote:

Repeat Offender wrote:

@ app4619: yeah, that's what you would have gotten had you searched the web for gfortran interfaces such as in http://home.comcast.net/~kmbtib/Fortran_stuff/example3.zip and duplicated the !GCC$ lines as !DEC$ lines, so that now the code should work both in gfortran and ifort, 32- and 64-bit modes.

 

Thanks for the link the OGL/GLU interfaces look more pukka and complete than my own (and I only fixed the routines I am currently using) and are more current/standard than the ifort supplied ones. I will look at that further at some point. I suspect replacing GCC with DEC and using IFWINTY and the job might be done! BIND(C), STDCALL is definitely a good way to get more standard. I have been winging about omission this for some time so chapeau Intel ! :-)

 

RO, I'm having a bit of trouble understanding all the points of your post, but let me try anyway.

  • Yes, F03 VALUE is different from ATTRIBUTES VALUE when the procedure is not BIND(C). Our implementation didn't get this right for many years, but now it does. If BIND(C) is not used, tthen F03 VALUE means pass a temporary copy which is then discarded on return.
  • If you have ATTRIBUTES STDCALL, REFERENCE, the REFERENCE changes the default back to reference from value. You can still override it with an ATTRIBUTES VALUE on individual arguments
  • Regarding name decoration - Calls from .NET languages such as VB don't apply decoration, so being able to disable the decoration is important. This is what our ATTRIBUTES ALIAS does (when you don't also say DECORATE).
  • The compiler should properly complain if you say BIND(C) and also any of the ATTRIBUTES other than STDCALL. I would hope it never gives an ICE.

Did I miss anything?

Steve - Intel Developer Support

Let me attempt to clarify with actual code. Start with a C subroutine that can read the value:

subroutine sub(dummy) bind(C,name='sub')
   use ISO_C_BINDING
   implicit none
   integer(C_INTPTR_T), value :: dummy
   character(20) fmt
   write(fmt,'(a,i0,a)') '(Z0.',2*C_SIZEOF(dummy),')'
   write(*,fmt) dummy
end subroutine sub

Now the examples:

program value
   call test1
   call test2
   call test3
   call test4
   call test5
end program value

subroutine test1
   use ISO_C_BINDING
   implicit none
   interface
      subroutine sub(dummy) bind(C,name='sub')
         use ISO_C_BINDING
         implicit none
         integer(C_INTPTR_T), value :: dummy
      end subroutine sub
   end interface
   integer(C_INTPTR_T) actual
   actual = 1
   call sub(actual)
end subroutine test1

subroutine test2
   use ISO_C_BINDING
   implicit none
   interface
      subroutine sub(dummy)
         use ISO_C_BINDING
         implicit none
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'sub' :: sub
!DEC$ ATTRIBUTES value :: dummy
         integer(C_INTPTR_T) dummy
      end subroutine sub
   end interface
   integer(C_INTPTR_T) actual
   actual = 2
   call sub(actual)
end subroutine test2

subroutine test3
   use ISO_C_BINDING
   implicit none
   interface
      subroutine sub(dummy)
         use ISO_C_BINDING
         implicit none
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'sub' :: sub
         integer(C_INTPTR_T) dummy
      end subroutine sub
   end interface
   integer(C_INTPTR_T) actual
   actual = 3
   call sub(actual)
end subroutine test3

subroutine test4
   use ISO_C_BINDING
   implicit none
   interface
      subroutine sub(dummy)
         use ISO_C_BINDING
         implicit none
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'sub' :: sub
         integer(C_INTPTR_T), value :: dummy
      end subroutine sub
   end interface
   integer(C_INTPTR_T) actual
   actual = 4
   call sub(actual)
end subroutine test4

subroutine test5
   use ISO_C_BINDING
   implicit none
   interface
      subroutine sub(dummy)
         use ISO_C_BINDING
         implicit none
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'sub' :: sub
!DEC$ ATTRIBUTES VALUE :: dummy
         integer(C_INTPTR_T), value :: dummy
      end subroutine sub
   end interface
   integer(C_INTPTR_T) actual
   actual = 5
   call sub(actual)
end subroutine test5

First I hope that subroutine test5 is invalid and should be detected as such by the compiler and then should be elided because of conflicting attributes for dummy variable dummy.

Then I hope we all agree that subroutine test1 should print out 1 because the interface is specified as BIND(C) and only true value is possible.

Also I think that subroutine test2 should print out 2 because we have only confirmed the default !DEC$ ATTRIBUTES VALUE attribute of dummy argument dummy.

I also think that subroutine test3 should print out 3 because we have !DEC$ ATTRIBUTES C implies !DEC$ATTRIBUTES VALUE, not the Fortran standard VALUE attribute although it's a little difficult to find this in the documentation.

But subroutine test4 should print out some random address in hex because we have overridden the default !DEC$ ATTRIBUTES VALUE attribute with the Fortran standard VALUE attribute, thus passing actual argument actual by reference to a temporary copy.

What is version 15's behavior for these tests?

Version 15 displays:

00000001
00000002
00000003
00000004
00000005

I don't think this is wrong. The F03 VALUE attribute says pass a copy, but when you have ATTRIBUTES C or VALUE you have gone outside the standard. In this case, we pass the copy by value.

I modified the program to have sub change the value of dummy to 314 and then have test4 and test5 display the value of actual afterward. I got this:

00000001
00000002
00000003
00000004
 On return in test4, actual=           4
00000005
 On return in test5, actual=           5

which is exactly what I expected.

Steve - Intel Developer Support

If those results are supposed to be OK, then I just don't get it. Going back to post #5, app4619 had

!DEC$ ATTRIBUTES STDCALL, REFERENCE :: gluDisk

real(GLdouble), value :: inner

Now, the first line above tells the compiler to pass all arguments by reference, unless overridden.

The second line above tells the compiler to override the first line for dummy argument inner, passing by value. He said this worked in version 13, but failed in version 15, and you said in post #7 that this was because the Fortran standard VALUE attribute was applied in this case, not the !DEC$ ATTRIBUTES VALUE attribute, so now what was getting passed was the address of a copy of the actual argument, not the value of the actual argument.

But now you say in post #18, that in subroutine test4 where we see

!DEC$ ATTRIBUTES C :: sub

integer(C_INTPTR_T), value :: dummy

The first line this time tells the compiler to pass all arguments using the !DEC$ ATTRIBUTES VALUE attribute, unless overridden.

The second line tells the compiler to override the first line for dummy argument dummy, passing by Fortran standard value, one might expect from the results of post #5, but you say this doesn't happen. It seems to me these results are completely inconsistent. Where is my reasoning flawing and where would I look in ifort documentation to be unambiguously able to predict both outcomes correctly?

@RO #19, bear in mind the #5 code fails in 15 because the stdcall decoration fails so it won't link. I don't know if that helps if I had forced the correct LIB name via alias instead I am not sure what would have happened....

 

Well, there's one way to check what happened. Please compile this with ifort v. 15 and post the results:

module glu
   use ISO_C_BINDING
   implicit none
   integer, parameter :: GLint = C_INT
   integer, parameter :: GLdouble = C_DOUBLE
   interface
      subroutine gluDisk5(quad,inner,outer,slices,loops)
         import
         implicit none
         !DEC$ ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS:"gluDisk" :: gluDisk5
         integer(GLint), value :: slices, loops
         real(GLdouble), value :: inner, outer
         type(C_PTR), value :: quad
      end subroutine gluDisk5
   end interface
   interface
      subroutine gluDisk13(quad,inner,outer,slices,loops) bind(C,name='gluDisk')
         import
         implicit none
         !DEC$ ATTRIBUTES STDCALL :: gluDisk13
         integer(GLint), value :: slices, loops
         real(GLdouble), value :: inner, outer
         type(C_PTR), value :: quad
      end subroutine gluDisk13
   end interface
   contains
      subroutine gluDisk20(quad,inner,outer,slices,loops) bind(C,name='gluDisk')
         !DEC$ ATTRIBUTES STDCALL :: gluDisk20
         type(C_PTR), value :: quad,inner,outer,slices,loops
         type(C_PTR) cptr
         integer(GLint), pointer :: iptr
         real(GLdouble), pointer :: dptr
         type(C_PTR), pointer :: aptr
         character(20) fmt
         write(*,'(a)') '_gluDisk@20 invoked'
         write(fmt,'(a,i0,a)') '(Z0.',2*C_SIZEOF(aptr),')'
         write(*,fmt) transfer(quad,0_C_INTPTR_T)
         call C_F_POINTER(quad,aptr)
         write(*,fmt) transfer(aptr,0_C_INTPTR_T)
         write(*,fmt) transfer(inner,0_C_INTPTR_T)
         call C_F_POINTER(inner,dptr)
         write(*,'(Z0.16)') transfer(dptr,0_C_INT64_T)
         write(*,fmt) transfer(outer,0_C_INTPTR_T)
         call C_F_POINTER(outer,dptr)
         write(*,'(Z0.16)') transfer(dptr,0_C_INT64_T)
         write(*,fmt) transfer(slices,0_C_INTPTR_T)
         call C_F_POINTER(slices,iptr)
         write(*,'(Z0.8)') iptr
         write(*,fmt) transfer(loops,0_C_INTPTR_T)
         call C_F_POINTER(loops,iptr)
         write(*,'(Z0.8)') iptr
      end subroutine gluDisk20
      subroutine gluDisk28(quad,inner,outer,slices,loops) bind(C,name='gluDisk')
         !DEC$ ATTRIBUTES STDCALL :: gluDisk28
         integer(GLint), value, target :: slices, loops
         real(GLdouble), value, target :: inner, outer
         type(C_PTR), value, target :: quad
         type(C_PTR) cptr
         character(20) fmt
         write(*,'(a)') '_gluDisk@28 invoked'
         write(fmt,'(a,i0,a)') '(Z0.',2*C_SIZEOF(cptr),')'
         cptr = C_LOC(quad)
         write(*,fmt) transfer(cptr,0_C_INTPTR_T)
         write(*,fmt) transfer(quad,0_C_INTPTR_T)
         cptr = C_LOC(inner)
         write(*,fmt) transfer(cptr,0_C_INTPTR_T)
         write(*,'(Z0.16)') transfer(inner,0_C_INT64_T)
         cptr = C_LOC(outer)
         write(*,fmt) transfer(cptr,0_C_INTPTR_T)
         write(*,'(Z0.16)') transfer(outer,0_C_INT64_T)
         cptr = C_LOC(slices)
         write(*,fmt) transfer(cptr,0_C_INTPTR_T)
         write(*,'(Z0.8)') slices
         cptr = C_LOC(loops)
         write(*,fmt) transfer(cptr,0_C_INTPTR_T)
         write(*,'(Z0.8)') loops
      end subroutine gluDisk28
end module glu

program value
   use glu
   implicit none
   type(C_PTR) quad
   integer(GLint) loops,slices
   real(GLdouble) inner, outer
   quad = transfer(int(Z'DEADBEEF',C_INTPTR_T),quad)
   inner = 1.0_GLdouble
   outer = 1.5_GLdouble
   slices = 4
   loops = 5
   call gluDisk5(quad,inner,outer,slices,loops)
   call gluDisk13(quad,inner,outer,slices,loops)
end program value

I'm hoping you get something like:

_gluDisk@20 invoked
0023FDD0
DEADBEEF
0023FDE8
3FF0000000000000
0023FDD8
3FF8000000000000
0023FDCC
00000004
0023FDE4
00000005
_gluDisk@28 invoked
0023FD80
DEADBEEF
0023FD88
3FF0000000000000
0023FD90
3FF8000000000000
0023FD98
00000004
0023FDA0
00000005

Where those 0023FDXX numbers are any random addresses, but the other values should be as given. But please post, don't just say yes or no :)

with ifort 15>>>

1>------ Build started: Project: Console4, Configuration: Debug Win32 ------
1>Compiling with Intel(R) Visual Fortran Compiler XE 15.0.0.108 [IA-32]...
1>Console4.f90
1>C:\Users\...Console4\Console4.f90(53): error #5508: Declaration of routine 'GLUDISK28' conflicts with a previous declaration
1>compilation aborted for C:\Users\,,,\Console4\Console4.f90 (code 1)

I guess the conflict is with a decorated name, not quite getting that.

 

Hmm - I see what RO wants to do.One can do this with ALIAS, maybe not with BIND(C), given that both gludisk20 and gludisk28 have the same binding label (which does not include decoration), and the standard disallows that.

Steve - Intel Developer Support

Quite frustrating bug in the standard. The same binding label doesn't imply the same externally visible name. gfortran complained as well. The workaround is to change the binding name of gluDisk5 and gluDisk20 to 'gluDiskA', or separate compilation so the compiler can't see them both at once. Also add the line

iptr = 500

at the end of subroutine gluDisk20.

I don't agree that this is a bug in the standard in that you can't run into this problem until you step outside the standard. It will be moot soon anyway as 32-bit development tapers off. I'm seeing more and more applications require x64, which doesn't have STDCALL as a calling convention.

So if you want to play STDCALL naming games like this, you can't use BIND(C).

Steve - Intel Developer Support

I was looking to get this clear in my mind so I had a look at the documents. Release_Notes_F_2015_W_EN.pdf says:

3.2.4.1 ATTRIBUTES STDCALL now allowed with BIND(C)
As of compiler version 15.0, the ATTRIBUTES STDCALL directive may be specified for an 
interoperable procedure (a procedure whose declaration includes the BIND(C) language binding 
attribute.) This combination has the following effects for Windows* applications targeting IA-32 
architecture:
 The calling mechanism is changed to STDCALL, which affects how the stack is cleaned 
up on procedure exit
 The external name from the BIND attribute is suffixed with “@n”, where n is the number 
of bytes to be removed from the stack on return.
No other effects from STDCALL, such as pass-by-value, are provided. The Fortran standard 
VALUE attribute (not ATTRIBUTES VALUE) may be used if desired. For all other platforms, 
specifying STDCALL with BIND(C) has no effect.

and the help says:

The BIND attribute is similar to directive !DIR$ ATTRIBUTES C as follows:

  • The compiler applies the same naming rules, that is, names are lowercase (unless NAME= specifies otherwise).
  • The compiler applies the appropriate platform decoration, such as a leading underscore.

However, procedure argument passing differs. When BIND is specified, procedure arguments are passed by reference unless the VALUE attribute is also specified.

 

So why to I get the error:

error #8039: The INTENT(OUT) or INTENT(INOUT) attribute is not allowed for arguments received by value.   [PARAMS]  

For the code:

SUBROUTINE glGetPointerv(pname, params) BIND(C,NAME="glGetPointerv")
    !DEC$ ATTRIBUTES STDCALL  :: glGetPointerv
    IMPORT
    INTEGER(GLenum), VALUE :: pname
    integer(C_INTPTR_T), INTENT(OUT) :: params 
END SUBROUTINE glGetPointerv

 

To get that to compile you have to add !DEC$ ATTRIBUTES REFERENCE :: params  which should not be so IMO 

That's probably a bug. We'll check it out.

Steve - Intel Developer Support

I keep thinking that more comprehensive tests are desirable. What happens if we have a file called 'include.f90':

         type(C_PTR), value :: X
         integer(C_INTPTR_T) I
         integer(C_INTPTR_T), pointer :: V
         I = transfer(X,I)
         if(I == 0) then
            R = 0
         else
            call C_F_POINTER(X,V)
            if(V == 0) then
               R = 1
               V = 1
            else
               R = 2
            end if
         end if
      end subroutine S
end module M

program P
   use M
   implicit none
   integer(C_INTPTR_T) X
   X = 0
   call test(X)
   open(10,file='VALUE.txt',status='OLD',position='APPEND')
   write(10,'(5(a:1x))',advance='no') BINDC,CLASS,GLOBAL,LOCAL,VALUE
   select case(R)
      case(0)
         write(10,'(1x,a)') 'VALUE'
      case(1)
         if(X == 0) then
            write(10,'(1x,a)') 'COPY'
         else if(X == 1) then
            write(10,'(1x,a)') 'REFERENCE'
         else
            write(10,'(1x,a)') 'UNKNOWN'
         end if
      case(2)
         write(10,'(1x,a)') 'UNKNOWN'
   end select
   flush 10
   close(10)
end program P

And a driver program that compiles it for various combinations of attributes, here called 'testall.f90':

program testall
   use ISO_C_BINDING
   implicit none
   integer BINDC,CLASS,GLOBAL,LOCAL,VALUE
   integer EXITSTAT
   open(10,file='VALUE.txt',status='REPLACE')
   write(10,'(6(a:1x))') ' BINDC ',' CLASS ',' GLOBAL',' LOCAL ',' VALUE ','RESULT'
   flush 10
   close(10)
   do BINDC = 1,2
      do CLASS = 1,3
         do GLOBAL = 1,3
            do LOCAL = 1,3
               do VALUE = 1,2
                  open(10,file='test.f90',status='REPLACE')
                  write(10,'(a)') "module M"
                  write(10,'(a)') "   use ISO_C_BINDING"
                  write(10,'(a)') "   implicit none"
                  if(BINDC == 1) then
                     write(10,'(a)') "   character(*), parameter :: BINDC = 'FORTRAN'"
                  else
                     write(10,'(a)') "   character(*), parameter :: BINDC = 'BIND(C)'"
                  end if
                  if(CLASS == 1) then
                     write(10,'(a)') "   character(*), parameter :: CLASS = 'DEFAULT'"
                  else if(CLASS == 2) then
                     write(10,'(a)') "   character(*), parameter :: CLASS = '   C   '"
                  else
                     write(10,'(a)') "   character(*), parameter :: CLASS = 'STDCALL'"
                  end if
                  if(GLOBAL == 1) then
                     write(10,'(a)') "   character(*), parameter :: GLOBAL = 'DEFAULT'"
                  else if(GLOBAL == 2) then
                     write(10,'(a)') "   character(*), parameter :: GLOBAL = '  REF  '"
                  else
                     write(10,'(a)') "   character(*), parameter :: GLOBAL = ' VALUE '"
                  end if
                  if(LOCAL == 1) then
                     write(10,'(a)') "   character(*), parameter :: LOCAL = 'DEFAULT'"
                  else if(LOCAL == 2) then
                     write(10,'(a)') "   character(*), parameter :: LOCAL = '  REF  '"
                  else
                     write(10,'(a)') "   character(*), parameter :: LOCAL = ' VALUE '"
                  end if
                  if(VALUE == 1) then
                     write(10,'(a)') "   character(*), parameter :: VALUE = 'DEFAULT'"
                  else
                     write(10,'(a)') "   character(*), parameter :: VALUE = ' VALUE '"
                  end if
                  write(10,'(a)') "   integer R"
                  write(10,'(a)') "   interface"
                  if(BINDC == 1) then
                     write(10,'(a)') "      subroutine test(X)"
                     write(10,'(a)') "         import"
                     write(10,'(a)') "         implicit none"
                     write(10,'(a)') "!DEC$ATTRIBUTES DECORATE,ALIAS: 's' :: test"
                  else
                     write(10,'(a)') "      subroutine test(X) bind(C,name = 's')"
                     write(10,'(a)') "         import"
                     write(10,'(a)') "         implicit none"
                  end if
                  if(CLASS == 2) then
                     write(10,'(a)') "!DEC$ATTRIBUTES C :: test"
                  else if(CLASS == 3) then
                     write(10,'(a)') "!DEC$ATTRIBUTES STDCALL :: test"
                  end if
                  if(GLOBAL == 2) then
                     write(10,'(a)') "!DEC$ATTRIBUTES REFERENCE :: test"
                  else if(GLOBAL == 3) then
                     write(10,'(a)') "!DEC$ATTRIBUTES VALUE :: test"
                  end if
                  if(LOCAL == 2) then
                     write(10,'(a)') "!DEC$ATTRIBUTES REFERENCE :: X"
                  else if(LOCAL == 3) then
                     write(10,'(a)') "!DEC$ATTRIBUTES VALUE :: X"
                  end if
                  if(VALUE == 1) then
                     write(10,'(a)') "         integer(C_INTPTR_T) :: X"
                  else
                     write(10,'(a)') "         integer(C_INTPTR_T), value :: X"
                  end if
                  write(10,'(a)') "      end subroutine test"
                  write(10,'(a)') "   end interface"
                  write(10,'(a)') "   contains"
                  write(10,'(a)') "      subroutine S(X) bind(C,name = 's')"
                  write(10,'(a)') "         implicit none"
                  if(CLASS == 2) then
                     write(10,'(a)') "!DEC$ATTRIBUTES STDCALL :: S"
                  end if
                  write(10,'(a)') "include 'include.f90'"
                  flush 10
                  close(10)
                  call EXECUTE_COMMAND_LINE('ifort test.f90',EXITSTAT=EXITSTAT)
                  if(EXITSTAT == 0) then
                     call EXECUTE_COMMAND_LINE('test')
                  else
                     open(10,file='VALUE.txt',status='OLD',position='APPEND')
                     if(BINDC == 1) then
                        write(10,'(a)',advance='no') 'FORTRAN'
                     else
                        write(10,'(a)',advance='no') 'BIND(C)'
                     end if
                     if(CLASS == 1) then
                        write(10,'(1x,a)',advance='no') 'DEFAULT'
                     else if(CLASS == 2) then
                        write(10,'(1x,a)',advance='no') '   C   '
                     else
                        write(10,'(1x,a)',advance='no') 'STDCALL'
                     end if
                     if(GLOBAL == 1) then
                        write(10,'(1x,a)',advance='no') 'DEFAULT'
                     else if(GLOBAL == 2) then
                        write(10,'(1x,a)',advance='no') '  REF  '
                     else
                        write(10,'(1x,a)',advance='no') ' VALUE '
                     end if
                     if(LOCAL == 1) then
                        write(10,'(1x,a)',advance='no') 'DEFAULT'
                     else if(LOCAL == 2) then
                        write(10,'(1x,a)',advance='no') '  REF  '
                     else
                        write(10,'(1x,a)',advance='no') ' VALUE '
                     end if
                     if(VALUE == 1) then
                        write(10,'(1x,a)',advance='no') 'DEFAULT'
                     else
                        write(10,'(1x,a)',advance='no') ' VALUE '
                     end if
                     write(10,'(1x,a)') 'COMPILATION FAILED'
                     flush 10
                     close(10)
                  end if
               end do
            end do
         end do
      end do
   end do
end program testall

Now we are hoping that testall.f90 can be compiled and run at the command prompt to yield a VALUE.txt output file. If it works, could you please attach the resulting VALUE.txt?

Quote:

Steve Lionel (Intel) wrote:

That's probably a bug. We'll check it out.

Did you conclude on this Steve? Since then I have come across this for a number of new api interfaces I had to make and have taken to having the "intent(out)" just added as a comment on the end of the code line as a workaround. I presume it is a problem with the code checking only not the actual object code  generation correctness?

 

 

 

I hadn't gotten to that yet - hope to do so tomorrow. I suspect it's just a wrong check, probably not recognizing the new stdcall+bind(C) combination.

Steve - Intel Developer Support

Escalated as issue DPD200360618. It is just the error check that is wrong.

Steve - Intel Developer Support

Leave a Comment

Please sign in to add a comment. Not a member? Join today