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

problem with value attribute with c_ptr

Andy_May
Beginner
574 Views

One of our developers has discovered a problem with ifort 14 regarding the value attribute when using c_ptr. They've made a cut-down with everything neatly included:

[fortran]! Compiler regression test case (ifort v14.0)
!
! Compilation
!   ifort -o test test.f90
!                                                                                                                                                                                                                                                                              
! Observed:                                                                                                                                                                                                                                                                    
!   - On calling a subroutine with a type(c_ptr) passed by value, the "value"                                                                                                                                                                                                  
!     attribute appears to be dropped, such that the receiving function                                                                                                                                                                                                        
!     is passed the address of the variable rather than its value.                                                                                                                                                                                                             
!   - This is clearly seen in a debugger.                                                                                                                                                                                                                                      
!                                                                                                                                                                                                                                                                              
! Observed output:                                                                                                                                                                                                                                                             
! In:                   1234                                                                                                                                                                                                                                                   
! Value:        140733278369776                                                                                                                                                                                                                                                
!                                                                                                                                                                                                                                                                              
!                                                                                                                                                                                                                                                                              
! Expected:                                                                                                                                                                                                                                                                    
!   - The receiving function should receive the paramater by value.                                                                                                                                                                                                            
!                                                                                                                                                                                                                                                                              
! Expected output:                                                                                                                                                                                                                                                             
! In:                   1234                                                                                                                                                                                                                                                   
! Value:                   1234                                                                                                                                                                                                                                                
!                                                                                                                                                                                                                                                                              
!                                                                                                                                                                                                                                                                              
! Compilers affected:                                                                                                                                                                                                                                                          
! Fails: ifort v14.0                                                                                                                                                                                                                                                           
! Passes: All other versions of ifort tried, gfortran, PGI, NAG                                                                                                                                                                                                                
!                                                                                                                                                                                                                                                                              
!                                                                                                                                                                                                                                                                              
! Notes: Indirection involving 64-bit integer and transfer is just to trivially                                                                                                                                                                                                
!        get data into/out of the type(c_ptr) in a way that can be printed                                                                                                                                                                                                     
!        and works on all compilers.                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                               
program test

    use iso_c_binding
    implicit none

    integer(selected_int_kind(15)) :: tmp
    type(c_ptr) :: val

    ! The indirection with a temporary value is just to provide a convenient
    ! way to get data in to the c_ptr (and to make printing easy).
    tmp = 1234
    val = transfer(tmp, val)
    write(6,*) 'In: ', tmp

    ! It appears that for type(c_ptr) the "value" attribute is ignored.
    call indirect(val)

contains

    subroutine indirect(a)
        type(c_ptr), intent(in), value :: a
        integer(selected_int_kind(15)) :: tmp

        tmp = transfer(a, tmp)
        write(6,*) 'Value: ', tmp
    end subroutine

end program[/fortran]

0 Kudos
7 Replies
Steven_L_Intel1
Employee
574 Views

The problem description isn't quite correct, but I see the issue. There's also a misunderstanding of what the VALUE attribute does.

In the absence of BIND(C) for the called routine, VALUE does NOT mean "pass-by-value". What the standard says is that a temporary, definable copy of the argument is passed and any effects on the copy are discarded when the called routine exits. This is what we do in 14.0  if you specify -standard-semantics.

If the called routine has BIND(C), then the VALUE attribute DOES mean pass-by-value. But you don't have that here nor would it be allowed for an internal procedure.

Ok, that's what SHOULD happen. What is going on? First, when we implemented VALUE many years ago, we goofed and made it be the same as !DEC$ ATTRIBUTES VALUE, meaning pass-by-value always. Only recently did we become aware of this. It was our intent to fix this and make the fix the default in the 14.0 compiler, but we discovered some compatibility issues that we didn't have time to resolve. So we left the default the same, added a new option -assume std_value, and included that with -standard-semantics. For a future release we will probably change the default.

Now as to C_PTR. You're right, the behavior of this program changed between 13.1 and 14.0. My guess is that we incompletely backed out the "fix". If you add -standard-semantics, you'll get 1234 in both places, but not because you've passed it by value. I will let the developers know about this glitch - thanks for the nice example.

0 Kudos
Steven_L_Intel1
Employee
574 Views

Escalated as issue DPD200249357. What is happening is that 14.0 is passing a copy of val (the standard behavior) but when it gets used in the subroutine, it's not being properly dereferenced. It should be consistent.

You will probably find that the other compilers are doing this right, making a copy passed by reference. If your intent is really pass-by-value, then you need a different approach.

0 Kudos
Simon_S_
Beginner
574 Views

Many thanks Steve. That is a horrible bit of standards writing.

In our usage that this test case was derived from, pass-by-value is the desired behaviour (it is from a rather nasty bit of hackery to manipulate function pointers in compilers pre-procedure pointer support). Not something that really ought to see the light of day. I have added bind(c) statements in the relevant places. I must admit to being suddenly surprised that this code has been working for years...

0 Kudos
Steven_L_Intel1
Employee
574 Views

I don't think the Fortran standard could have worded it better. The idea in the C interoperability stuff is to say "do what the companion C processor does", without restating or constraining it. But it certainly does lead to confusion at times.

0 Kudos
Steven_L_Intel1
Employee
574 Views

I expect the bug reported here to be fixed in Update 2, due late January (or maybe early February.)

0 Kudos
Alexis_R_
New Contributor I
574 Views

Steve Lionel (Intel) wrote:

I expect the bug reported here to be fixed in Update 2, due late January (or maybe early February.)

I am experiencing similar behaviour with c_ptr and value, but I'm not sure it's the exact same problem (I don't have a small reproducer yet).

Steve, could you confirm whether the bug reported above was fixed in Update 2?

Thanks

0 Kudos
Alexis_R_
New Contributor I
574 Views

I had forgotten about this page:

https://software.intel.com/en-us/articles/intel-composer-xe-2013-compilers-sp1-fixes-list

which says that DPD200249357 was fixed in Update 2 from February 2014.

0 Kudos
Reply