flang-compiler / flang

Flang is a Fortran language front-end designed for integration with LLVM.
Other
801 stars 136 forks source link

plplot: surprising interactions within the code: interface nested into subroutine defined into one interface causes previous defined interface appear undefined #367

Closed pawosm-arm closed 5 years ago

pawosm-arm commented 6 years ago

Following is the original report. Visit comments below for my latest findings.

Wile compiling plplot-5.13.0 I've encountered bizarre error:

F90-S-0155-Illegal POINTER assignment - type mismatch (plplot-5.13.0/bindings/fortran/plplot_double.f90: 1559)
  0 inform,   0 warnings,   1 severes, 0 fatal for plcont_impl_data
F90-S-0155-Illegal POINTER assignment - type mismatch (plplot-5.13.0/bindings/fortran/plplot_double.f90: 2244)
  0 inform,   0 warnings,   1 severes, 0 fatal for plimagefr_impl_data
F90-S-0155-Illegal POINTER assignment - type mismatch (plplot-5.13.0/bindings/fortran/plplot_double.f90: 3527)
  0 inform,   0 warnings,   1 severes, 0 fatal for plshade_impl_data
F90-S-0155-Illegal POINTER assignment - type mismatch (plplot-5.13.0/bindings/fortran/plplot_double.f90: 3715)
  0 inform,   0 warnings,   1 severes, 0 fatal for plshades_impl_data
F90-S-0155-Illegal POINTER assignment - type mismatch (plplot-5.13.0/bindings/fortran/plplot_double.f90: 4284)
  0 inform,   0 warnings,   1 severes, 0 fatal for plvect_impl_data
F90-S-0155-Illegal POINTER assignment - type mismatch (plplot-5.13.0/bindings/fortran/plplot_double.f90: 167)
  0 inform,   0 warnings,   1 severes, 0 fatal for plstransform_impl_data

The only common detail of those lines listed above is that they try to assign a pointer to procedure(pltransform_proc_data) which is defined in an abstract interface:

    abstract interface
        subroutine pltransform_proc_data( x, y, tx, ty, data )
            import :: wp, c_ptr
            implicit none
            real(kind=wp), intent(in) :: x, y
            real(kind=wp), intent(out) :: tx, ty
            type(c_ptr), intent(in) :: data
        end subroutine pltransform_proc_data
    end interface
    procedure(pltransform_proc_data), pointer :: pltransform_data
    private:: pltransform_proc_data, pltransform_data

The strange thing about it is that all other abstract interfaces (some even more complicated than this one!) were fine. The only thing I could say about this one is that it's the last one defined. So I added some phony abstract interface, nowhere used in the program, right after this one and the whole thing compiled! This error does not occur when compiling with gfortran.

pawosm-arm commented 6 years ago

My new findings: I couldn't find any traces in flang code for the behavior as described in my original bug report. Therefore I started to look at this problem from different angles. I found that the problem is not in the (abstract) interface definition itself, it's the things in the next defined interface that causes the havoc. In my proposed workaround, by adding fake interface definition (as it turned out, it does not need to be abstract and the subroutine in it does not need to accept any parameters at all), I have only hidden the real problem under the carpet. The real problem is that the next interface defines subroutine in which another interface is nested (it's unnamed, but adding it an explicit name does not help with anything). Somehow presence of interface nested into subroutine causing surprising interaction with the list of interfaces defined so far. Original plplot code causing the havoc:

    abstract interface
        subroutine pltransform_proc_data( x, y, tx, ty, data )
            import :: wp, c_ptr
            implicit none
            real(kind=wp), intent(in) :: x, y
            real(kind=wp), intent(out) :: tx, ty
            type(c_ptr), intent(in) :: data
        end subroutine pltransform_proc_data
    end interface
    procedure(pltransform_proc_data), pointer :: pltransform_data
    private:: pltransform_proc_data, pltransform_data

    interface
        subroutine interface_plcont( z, nx, ny, kx, lx, ky, ly, clevel, nlevel, transform, data ) &
               bind(c,name='c_plcont')
            import :: c_funptr, c_ptr
            import :: private_plint, private_plflt
            implicit none
            integer(kind=private_plint), value, intent(in) :: nx, ny, kx, lx, ky, ly, nlevel
            type(c_ptr), dimension(*), intent(in)  :: z
            real(kind=private_plflt), dimension(*), intent(in) :: clevel
            type(c_ptr), value, intent(in) :: data
            interface
                subroutine transform( x, y, tx, ty, data ) bind(c)
                    import :: private_plflt
                    import :: c_ptr
                    implicit none
                    real(kind=private_plflt), value, intent(in) :: x, y
                    real(kind=private_plflt), intent(out) :: tx, ty
                    type(c_ptr), value, intent(in) :: data
                end subroutine transform
            end interface
        end subroutine interface_plcont
    end interface
    private :: interface_plcont
pawosm-arm commented 5 years ago

bumping this one.

pawosm-arm commented 5 years ago

Works for me now. Closing it.