Created attachment 55085 [details] Fortran/C/Makfile. Changing the optimization level in the makefile reproduces the behaviour. For a TYPE(C_PTR), INTENT(OUT), buf, which is being passed through a Fortran subroutine to get the value set in a C function, an optimization of >= -O1 gives the warning "used uninitialized [-Wuninitialized]" and then the program Segmentation faults - invalid memory reference. It works for gfortran 12 but fails for gfortran 13 and 14. It works if the INTENT is INOUT.
I believe the sample code is misleading, and the behavior is expected: SUBROUTINE h5aread_async_f(buf) TYPE(C_PTR), INTENT(OUT) :: buf You can see what happens if you specify the flag -fdump-tree-original as part of F90FLAGS. Now compare the dump-tree for INTENT(INOUT) vs. INTENT(OUT): --- fcode.F90.005t.original.inout 2023-05-15 20:03:07.292148948 +0200 +++ fcode.F90.005t.original.out 2023-05-15 20:03:36.292208016 +0200 @@ -19,6 +19,7 @@ D.4223 = (void *) &attr_rdata0; f_ptr = D.4223; } + f_ptr = {CLOBBER}; h5aread_async_f (&f_ptr); { struct __st_parameter_dt dt_parm.0; When the dummy argument buf is declared with INTENT(OUT), we mark the actual argument in the caller with CLOBBER, which means that the optimizer may throw away previous calculations and assignments as they do not matter. If you add a line print '(Z16.16)', buf into that subroutine, you'll see that the clobber annotation serves its purpose once optimization is enabled. I think that you might want to cross-check your testcase with the NAG compiler, or some other compiler which provides a means to initialize INTENT(OUT) arguments to detect such code.
(In reply to anlauf from comment #1) > I think that you might want to cross-check your testcase with the NAG > compiler, or some other compiler which provides a means to initialize > INTENT(OUT) arguments to detect such code. I've just checked: NAG behaves similarly to gfortran; the code crashes with INTENT(OUT) and works with INTENT(INOUT) as well as INTENT(IN).
I see the same issue with NAG, regardless of the optimization level. Our CI testing had missed it because this was a parallel test, and we don't test parallel with NAG. I guess the issue is whether marking TYPE(C_PTR) as CLOBBER is correct. I looked through the 2018 standard and could not locate anything that addresses this use case. Are you interpreting the possibility that a TYPE(C_PTR) should not be declared INTENT(OUT)? I can instead change the subroutine to declare buf as INTEGER(C_INT), INTENT(OUT), TARGET :: buf and f_ptr = C_LOC(buf) and there is no issue. So it seems to depend on the TYPE of the argument being passed.
(In reply to Scot Breitenfeld from comment #3) > I guess the issue is whether marking TYPE(C_PTR) as CLOBBER is correct. I > looked through the 2018 standard and could not locate anything that > addresses this use case. Are you interpreting the possibility that a > TYPE(C_PTR) should not be declared INTENT(OUT)? Maybe I am missing your intention, but I interpret your code that you want to pass a (C) pointer to variable attr_rdata0 to return your result. But that needs to be intent(in). Your subroutine is not really supposed to return a pointer but a result in the location the pointer dereferences. Feel free to correct me. > I can instead change the subroutine to declare buf as > > INTEGER(C_INT), INTENT(OUT), TARGET :: buf > > and f_ptr = C_LOC(buf) and there is no issue. I cannot confirm this with my gcc installations, and there is no reason that this should make a difference. > So it seems to depend on the > TYPE of the argument being passed. There are cases where no clobber is currently generated. For example, if the dummy variable is a Fortran pointer, which has a completely different semantics from TYPE(C_PTR). Still I don't understand why you don't use INTENT(IN) for the pointer. In that case you could do things in the main like: CALL H5Aread_async_f(C_LOC(attr_rdata0)) which appears to represent what I am guessing, and which gets rejected for INTENT /= IN with a possibly more helpful error message.
(In reply to Scot Breitenfeld from comment #3) > I see the same issue with NAG, regardless of the optimization level. Our CI > testing had missed it because this was a parallel test, and we don't test > parallel with NAG. > > I guess the issue is whether marking TYPE(C_PTR) as CLOBBER is correct. I > looked through the 2018 standard and could not locate anything that > addresses this use case. Are you interpreting the possibility that a > TYPE(C_PTR) should not be declared INTENT(OUT)? Fortran 2023, 8.5.10 The INTENT (OUT) attribute for a nonpointer dummy argument specifies that the dummy argument becomes undefined on invocation of the procedure, except for any subcomponents that are default-initialized (7.5.4.6).
Thanks for the standard reference. That is indeed what I was looking for. I understand now that, in this case, the INTENT refers to whether C_PTR can be changed and does not relate to the INTENT state of the target. I should change all my usage cases to INTENT(IN) since none of the Fortran wrappers allow changes to the pointer itself.