problem with value attribute with c_ptr

problem with value attribute with c_ptr

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:

! 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)
	    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

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

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.

Retired 12/31/2016

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.

Retired 12/31/2016

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...

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.

Retired 12/31/2016

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

Retired 12/31/2016


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?


I had forgotten about this page:

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

Leave a Comment

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