PGI User Forum
 SearchSearch   MemberlistMemberlist     RegisterRegister   ProfileProfile    Log inLog in 

Free OpenACC Webinar

ICE (Lowering Error) in pgfortran 14.1
Goto page 1, 2  Next
 
Post new topic   Reply to topic    PGI User Forum Forum Index -> Programming and Compiling
View previous topic :: View next topic  
Author Message
Sean Patrick Santos



Joined: 15 Sep 2013
Posts: 15

PostPosted: Fri Apr 04, 2014 3:00 pm    Post subject: ICE (Lowering Error) in pgfortran 14.1 Reply with quote

I have a medium-sized (~650 lines) module, which uses Fortran 2003 OOP features, and PGI generates the following error when I try to compile it:

Lowering Error: array upper bound is not a symbol for datatype 176
Lowering Error: array extnt is not a symbol for datatype 176
PGF90-F-0000-Internal compiler error. Errors in Lowering 2 (/home/santos/CAM/gw_fixes/models/atm/cam/src/physics/cam/linear_1d_operators.F90: 202)
PGF90/x86-64 Linux 14.1-0: compilation aborted

Line 202 is simply the "contains" for the module, so it's not obvious to me where the real issue is. I'm wondering if there's a way to narrow this down somehow to work around it. There are a lot of things here that I haven't done with PGI before, so it's hard to narrow down.

This code is still very much under development, but I think that in its current state it is still valid Fortran; it looks right to me, and compiles with NAG and Intel compilers. Regardless, there should not be an ICE.

Edit: I want to point out that this can compile stand-alone. So I'm hoping that it's not hard to reproduce the compilation error I had, even without a full program to actually test it.

Here's the code itself:

Code:

module linear_1d_operators

! TODO: evaluate names, more comments, header here, error handling
!       (e.g. need to assert array bounds, and that boundary option is
!        valid in routines that use it)
! TODO: check to make sure that the input arrays are big enough for second
!       order methods

implicit none
private
save

public :: NeighborOp

! Diagonal matrix.
public :: diagonal_operator

! Derivatives on a non-uniform grid.
public :: first_derivative
public :: second_derivative

! Boundary types.
public :: BoundaryType
public :: BoundaryZero
public :: BoundaryFirstOrder
public :: BoundaryExtrap
public :: BoundaryFixedLayer
public :: BoundaryFixedFlux

! Pre-defined boundary condition options for derivatives.
public :: boundary_zero
public :: boundary_first_order
public :: boundary_extrap
public :: boundary_fixed_flux

! Boundary data types.
public :: BoundaryCond
public :: BoundaryNoData
public :: BoundaryData
public :: BoundaryFlux

! Pre-defined boundary condition.
public :: boundary_no_data

integer, parameter :: r8 = selected_real_kind(12)

! NeighborOp represents operators that can work just between nearest
! neighbors, except with some extra logic at the boundaries. The
! implementation is a tridiagonal matrix plus boundary info.
! nlev is the size of the matrix.
! spr, sub, and diag are the super-, sub-, and regular diagonals.
! lbound_term and rbound_term are extra terms to get a second order
! approximation to a value at the boundaries. They represent second-nearest
! neighbor crossterms for the boundary points.
type :: NeighborOp
   integer :: ncol
   integer :: nlev
   real(r8), allocatable :: spr(:,:)
   real(r8), allocatable :: sub(:,:)
   real(r8), allocatable :: diag(:,:)
   real(r8), allocatable :: lbound_term(:)
   real(r8), allocatable :: rbound_term(:)
 contains
   procedure, pass(self) :: apply_2d => apply_neighbor_to_2d
   generic, public :: apply => apply_2d
   procedure, pass(self) :: deriv_diag => make_neighbor_deriv_diag
   procedure, pass(self) :: lmult_as_diag => diagonal_lmult_neighbor
   procedure, pass(op1) :: sum_other_neighbor => sum_neighbor_ops
   generic, public :: operator(+) => sum_other_neighbor
end type NeighborOp

interface NeighborOp
   module procedure new_NeighborOp
end interface


! Boundary conditions for second-order derivative operators.
!
! BoundaryZero means that the operator always sets boundaries to 0.
! BoundaryFirstOrder means a one-sided approximation for the first
!     derivative, and a zero boundary condition for higher orders.
! BoundaryExtrap means that a second order approximation will be used,
!     even at the boundaries. Boundary points do this by using their next-
!     nearest neighbor to "extrapolate".
! BoundaryFixedLayer means that there's an extra layer outside of the given
!     grid, and with data that will be given separately from the mutable
!     data when the operator is actually applied.
! BoundaryFixedFlux is intended to provide a fixed-flux condition for
!     typical advection/diffusion operators. It tweaks the edge condition
!     to work on an input current rather than a value.
!
! At this time, it is not possible to request circular boundary conditions.

type, abstract :: BoundaryType
 contains
   procedure(make_boundary), deferred :: make_left
   procedure(make_boundary), deferred :: make_right
end type BoundaryType

abstract interface
   subroutine deriv_seed(del_p, del_m, sub, spr)
     import :: r8
     real(r8), intent(in) :: del_p(:)
     real(r8), intent(in) :: del_m(:)
     real(r8), intent(out) :: sub(:)
     real(r8), intent(out) :: spr(:)
   end subroutine deriv_seed
   subroutine make_boundary(self, grid_spacing, seed, &
        term1, term2)
     import :: BoundaryType, r8, deriv_seed
     class(BoundaryType) :: self
     real(r8), intent(in) :: grid_spacing(:,:)
     procedure(deriv_seed) :: seed
     real(r8), intent(out) :: term1(:)
     real(r8), intent(out) :: term2(:)
   end subroutine make_boundary
end interface

type, extends(BoundaryType) :: BoundaryZero
 contains
   procedure :: make_left => make_either_boundary_zero
   procedure :: make_right => make_either_boundary_zero
end type BoundaryZero

type, extends(BoundaryType) :: BoundaryFirstOrder
 contains
   procedure :: make_left => make_left_boundary_1st_ord
   procedure :: make_right => make_right_boundary_1st_ord
end type BoundaryFirstOrder

type, extends(BoundaryType) :: BoundaryExtrap
 contains
   procedure :: make_left => make_left_boundary_extrap
   procedure :: make_right => make_right_boundary_extrap
end type BoundaryExtrap

type, extends(BoundaryType) :: BoundaryFixedLayer
   real(r8), allocatable :: del_edge(:)
 contains
   procedure :: make_left => make_left_boundary_fixed
   procedure :: make_right => make_right_boundary_fixed
end type BoundaryFixedLayer

type, extends(BoundaryType) :: BoundaryFixedFlux
 contains
   procedure :: make_left => make_left_boundary_fixed_flux
   procedure :: make_right => make_right_boundary_fixed_flux
end type BoundaryFixedFlux

type(BoundaryZero), target :: boundary_zero = BoundaryZero()
type(BoundaryFirstOrder), target :: boundary_first_order = BoundaryFirstOrder()
type(BoundaryExtrap), target :: boundary_extrap = BoundaryExtrap()
type(BoundaryFixedFlux), target :: boundary_fixed_flux = BoundaryFixedFlux()


! Data for boundary conditions themselves.
type, abstract :: BoundaryCond
 contains
   procedure(apply_boundary), deferred :: apply_left
   procedure(apply_boundary), deferred :: apply_right
end type BoundaryCond

abstract interface
   function apply_boundary(self, op, array) result(output_edge)
     import :: BoundaryCond, NeighborOp, r8
     class(BoundaryCond), intent(in) :: self
     class(NeighborOp), intent(in) :: op
     real(r8), intent(in) :: array(:,:)
     real(r8) :: output_edge(size(array, 1))
   end function apply_boundary
end interface

type, extends(BoundaryCond) :: BoundaryNoData
 contains
   procedure :: apply_left => apply_left_bndry_extrap
   procedure :: apply_right => apply_right_bndry_extrap
end type BoundaryNoData

type, extends(BoundaryCond) :: BoundaryData
   real(r8), allocatable :: data_edge(:)
 contains
   procedure :: apply_left => apply_left_bndry_data
   procedure :: apply_right => apply_right_bndry_data
end type BoundaryData

type, extends(BoundaryCond) :: BoundaryFlux
   real(r8), allocatable :: delta_edge(:)
 contains
   procedure :: apply_left => apply_bndry_flux
   procedure :: apply_right => apply_bndry_flux
end type BoundaryFlux

type(BoundaryNoData), target :: boundary_no_data = BoundaryNoData()

! Constructor for BoundaryFlux; this is provided to help the user remember
! that the time/space resolution has to be accounted for in constructing
! this condition.
interface BoundaryFlux
   module procedure new_BoundaryFlux
end interface

contains

function diagonal_operator(diag) result(op)
  real(r8), intent(in) :: diag(:,:)

  type(NeighborOp) :: op

  op = NeighborOp(size(diag, 1), size(diag, 2))

  op%spr = 0._r8
  op%sub = 0._r8
  op%diag = diag
  op%lbound_term = 0._r8
  op%rbound_term = 0._r8

end function diagonal_operator

subroutine first_derivative_seed(del_p, del_m, sub, spr)
  real(r8), intent(in) :: del_p(:)
  real(r8), intent(in) :: del_m(:)
  real(r8), intent(out) :: sub(:)
  real(r8), intent(out) :: spr(:)

  real(r8) :: del_sum(size(del_p))

  del_sum = del_p + del_m

  sub = - del_p / (del_m*del_sum)
  spr =   del_m / (del_p*del_sum)

end subroutine first_derivative_seed

function first_derivative(grid_spacing, l_bndry, r_bndry) result(d)
  real(r8), intent(in) :: grid_spacing(:,:)
  class(BoundaryType), intent(in), optional :: l_bndry, r_bndry

  type(NeighborOp) :: d

  d = deriv_op_from_seed(grid_spacing, first_derivative_seed, &
       l_bndry, r_bndry)

end function first_derivative

subroutine second_derivative_seed(del_p, del_m, sub, spr)
  real(r8), intent(in) :: del_p(:)
  real(r8), intent(in) :: del_m(:)
  real(r8), intent(out) :: sub(:)
  real(r8), intent(out) :: spr(:)

  real(r8) :: del_sum(size(del_p))

  del_sum = del_p + del_m

  sub = 2._r8 / (del_m*del_sum)
  spr = 2._r8 / (del_p*del_sum)

end subroutine second_derivative_seed

function second_derivative(grid_spacing, l_bndry, r_bndry) result(d)
  real(r8), intent(in) :: grid_spacing(:,:)
  class(BoundaryType), intent(in), optional :: l_bndry, r_bndry

  type(NeighborOp) :: d

  d = deriv_op_from_seed(grid_spacing, second_derivative_seed, &
       l_bndry, r_bndry)

end function second_derivative

function deriv_op_from_seed(grid_spacing, seed, l_bndry, r_bndry) result(d)
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  class(BoundaryType), target, intent(in), optional :: l_bndry, r_bndry

  type(NeighborOp) :: d

  class(BoundaryType), pointer :: l_bndry_loc, r_bndry_loc
  real(r8) :: del_p(size(grid_spacing,1))
  real(r8) :: del_m(size(grid_spacing,1))

  integer :: k

  if (present(l_bndry)) then
     l_bndry_loc => l_bndry
  else
     l_bndry_loc => boundary_extrap
  end if

  if (present(r_bndry)) then
     r_bndry_loc => r_bndry
  else
     r_bndry_loc => boundary_extrap
  end if

  ! Number of grid points is one greater than the spacing.
  d = NeighborOp(size(grid_spacing, 1), size(grid_spacing, 2) + 1)

  ! Left boundary condition.
  call l_bndry_loc%make_left(grid_spacing, seed, &
       d%lbound_term, d%spr(:,1))

  do k = 2, d%nlev-1
     del_p = grid_spacing(:,k)
     del_m = grid_spacing(:,k-1)
     call seed(del_p, del_m, d%sub(:,k-1), d%spr(:,k))
  end do

  ! Right boundary condition.
  call r_bndry_loc%make_right(grid_spacing, seed, &
       d%sub(:,d%nlev-1), d%rbound_term)

  ! Above, we found all off-diagonals. Now get the diagonal.
  call d%deriv_diag()

end function deriv_op_from_seed

subroutine make_either_boundary_zero(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryZero) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  term1 = 0._r8
  term2 = 0._r8

end subroutine make_either_boundary_zero

subroutine make_left_boundary_1st_ord(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryFirstOrder) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! To calculate to first order, just use a really huge del_m (i.e.
  ! pretend that there's a point so far away it doesn't matter).
  del_p = grid_spacing(:,1)
  del_m = del_p * 4._r8 / epsilon(1._r8)
  call seed(del_p, del_m, term1, term2)

end subroutine make_left_boundary_1st_ord

subroutine make_right_boundary_1st_ord(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryFirstOrder) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! Use huge del_p, analogous to how left boundary works.
  del_m = grid_spacing(:,size(grid_spacing, 2))
  del_p = del_m * 4._r8 / epsilon(1._r8)
  call seed(del_p, del_m, term1, term2)

end subroutine make_right_boundary_1st_ord

subroutine make_left_boundary_extrap(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryExtrap) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! To extrapolate from the boundary, use distance from the nearest
  ! neighbor (as usual) and the second nearest neighbor (with a negative
  ! sign, since we are using two points on the same side).
  del_p = grid_spacing(:,1)
  del_m = - (grid_spacing(:,1) + grid_spacing(:,2))
  call seed(del_p, del_m, term1, term2)

end subroutine make_left_boundary_extrap

subroutine make_right_boundary_extrap(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryExtrap) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  integer :: n_space

  n_space = size(grid_spacing, 2)

  ! Same strategy as left boundary, but reversed.
  del_p = - (grid_spacing(:,n_space - 1) + grid_spacing(:,n_space))
  del_m = grid_spacing(:,n_space)
  call seed(del_p, del_m, term1, term2)

end subroutine make_right_boundary_extrap

subroutine make_left_boundary_fixed(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryFixedLayer) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! Use edge value to extend the grid.
  del_p = grid_spacing(:,1)
  del_m = self%del_edge
  call seed(del_p, del_m, term1, term2)

end subroutine make_left_boundary_fixed

subroutine make_right_boundary_fixed(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryFixedLayer) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! Use edge value to extend the grid.
  del_p = self%del_edge
  del_m = grid_spacing(:,size(grid_spacing, 2))
  call seed(del_p, del_m, term1, term2)

end subroutine make_right_boundary_fixed

subroutine make_left_boundary_fixed_flux(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryFixedFlux) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! Use edge value to extend the grid.
  del_p = grid_spacing(:,1)
  del_m = del_p
  call seed(del_p, del_m, term1, term2)
  term1 = 0._r8

end subroutine make_left_boundary_fixed_flux

subroutine make_right_boundary_fixed_flux(self, grid_spacing, seed, &
     term1, term2)
  class(BoundaryFixedFlux) :: self
  real(r8), intent(in) :: grid_spacing(:,:)
  procedure(deriv_seed) :: seed
  real(r8), intent(out) :: term1(:)
  real(r8), intent(out) :: term2(:)

  real(r8) :: del_p(size(term1)), del_m(size(term1))

  ! Use edge value to extend the grid.
  del_p = grid_spacing(:,size(grid_spacing, 2))
  del_m = del_p
  call seed(del_p, del_m, term1, term2)
  term2 = 0._r8

end subroutine make_right_boundary_fixed_flux

! Constructor for NeighborOp; this just sets the size and allocates
! arrays.
type(NeighborOp) function new_NeighborOp(ncol, nlev)

  integer, intent(in) :: ncol, nlev

  new_NeighborOp%ncol = ncol
  new_NeighborOp%nlev = nlev

  allocate(new_NeighborOp%spr(ncol,nlev-1), &
       new_NeighborOp%sub(ncol,nlev-1), &
       new_NeighborOp%diag(ncol,nlev), &
       new_NeighborOp%lbound_term(ncol), &
       new_NeighborOp%rbound_term(ncol))

end function new_NeighborOp

function apply_left_bndry_extrap(self, op, array) result(delta_edge)
  class(BoundaryNoData), intent(in) :: self
  class(NeighborOp), intent(in) :: op
  real(r8), intent(in) :: array(:,:)
  real(r8) :: delta_edge(size(array, 1))

  delta_edge = op%lbound_term*array(:,3)

end function apply_left_bndry_extrap

function apply_right_bndry_extrap(self, op, array) result(delta_edge)
  class(BoundaryNoData), intent(in) :: self
  class(NeighborOp), intent(in) :: op
  real(r8), intent(in) :: array(:,:)
  real(r8) :: delta_edge(size(array, 1))

  delta_edge = op%rbound_term*array(:,op%nlev-2)

end function apply_right_bndry_extrap

function apply_left_bndry_data(self, op, array) result(delta_edge)
  class(BoundaryData), intent(in) :: self
  class(NeighborOp), intent(in) :: op
  real(r8), intent(in) :: array(:,:)
  real(r8) :: delta_edge(size(array, 1))

  delta_edge = op%lbound_term*self%data_edge

end function apply_left_bndry_data

function apply_right_bndry_data(self, op, array) result(delta_edge)
  class(BoundaryData), intent(in) :: self
  class(NeighborOp), intent(in) :: op
  real(r8), intent(in) :: array(:,:)
  real(r8) :: delta_edge(size(array, 1))

  delta_edge = op%rbound_term*self%data_edge

end function apply_right_bndry_data

function new_BoundaryFlux(flux, dt, spacing) result(new_flux)
  real(r8), intent(in) :: flux(:)
  real(r8), intent(in) :: dt
  real(r8), intent(in) :: spacing(:)
  type(BoundaryFlux) :: new_flux

  new_flux%delta_edge = flux*dt/spacing

end function new_BoundaryFlux

function apply_bndry_flux(self, op, array) result(delta_edge)
  class(BoundaryFlux), intent(in) :: self
  class(NeighborOp), intent(in) :: op
  real(r8), intent(in) :: array(:,:)
  real(r8) :: delta_edge(size(array, 1))

  delta_edge = self%delta_edge

end function apply_bndry_flux

function apply_neighbor_to_2d(self, array, l_cond, r_cond) result(output)
  class(NeighborOp), intent(in) :: self
  real(r8), intent(in) :: array(:,:)
  class(BoundaryCond), target, intent(in), optional :: l_cond, r_cond

  real(r8) :: output(size(array, 1), size(array, 2))

  class(BoundaryCond), pointer :: l_cond_loc, r_cond_loc

  integer :: k

  if (present(l_cond)) then
     l_cond_loc => l_cond
  else
     l_cond_loc => boundary_no_data
  end if

  if (present(r_cond)) then
     r_cond_loc => r_cond
  else
     r_cond_loc => boundary_no_data
  end if

  ! Left boundary.
  output(:,1) = self%diag(:,1)*array(:,1) + &
       self%spr(:,1)*array(:,2) + &
       l_cond_loc%apply_left(self, array)

  do k = 2, self%nlev-1
     output(:,k) = &
          self%sub(:,k-1)*array(:,k-1) + &
          self%diag(:,k)*array(:,k  ) + &
          self%spr(:,k)*array(:,k+1)
  end do

  ! Right boundary.
  output(:,self%nlev) = &
       self%sub(:,self%nlev-1)*array(:,self%nlev-1) + &
       self%diag(:,self%nlev)*array(:,self%nlev) + &
       r_cond_loc%apply_right(self, array)

end function apply_neighbor_to_2d

! Fill in the diagonal for a NeighborOp for a derivative operator, where
! the off diagonal elements are already filled in.
subroutine make_neighbor_deriv_diag(self)

  class(NeighborOp), intent(inout) :: self

  ! If a derivative operator operates on a constant function, it must
  ! return 0 everywhere. To force this, make sure that all rows add to
  ! zero in the matrix.
  self%diag(:,:self%nlev-1) = - self%spr
  self%diag(:,self%nlev) = - self%rbound_term
  self%diag(:,1) = self%diag(:,1) - self%lbound_term
  self%diag(:,2:) = self%diag(:,2:) - self%sub

end subroutine make_neighbor_deriv_diag

! Sum two NeighborOp objects into a new one; this is just the addition of
! all the entries.
function sum_neighbor_ops(op1, op2) result(new_op)

  class(NeighborOp), intent(in) :: op1, op2
  type(NeighborOp) :: new_op

  ! TODO: Add assert that inputs are the same size.

  new_op = NeighborOp(op1%ncol, op1%nlev)

  new_op%spr = op1%spr + op2%spr
  new_op%sub = op1%sub + op2%sub
  new_op%diag = op1%diag + op2%diag

  new_op%lbound_term = op1%lbound_term + op2%lbound_term
  new_op%rbound_term = op1%rbound_term + op2%rbound_term

end function sum_neighbor_ops

! Multiply in a rank 1 array as if it contained the entries of a diagonal
! matrix being multiplied from the left.
subroutine diagonal_lmult_neighbor(self, diag_array)

  class(NeighborOp), intent(inout) :: self
  real(r8), intent(in) :: diag_array(:,:)

  self%spr = self%spr * diag_array(:,:self%nlev-1)
  self%sub = self%sub * diag_array(:,2:)
  self%diag = self%diag * diag_array(:,:)

  self%lbound_term = self%lbound_term * diag_array(1,1)
  self%rbound_term = self%rbound_term * diag_array(1,self%nlev)

end subroutine diagonal_lmult_neighbor

end module linear_1d_operators


Last edited by Sean Patrick Santos on Tue Apr 08, 2014 1:00 pm; edited 1 time in total
Back to top
View user's profile
cparrott



Joined: 02 May 2011
Posts: 146

PostPosted: Mon Apr 07, 2014 9:01 am    Post subject: Reply with quote

Hi Sean,

I tried to compile the code you posted here with PGI 14.1, but I got a bunch of syntax errors. Could you post the exact command line you used when you observed this problem?

Thanks in advance,

+chris
Back to top
View user's profile
Sean Patrick Santos



Joined: 15 Sep 2013
Posts: 15

PostPosted: Tue Apr 08, 2014 1:01 pm    Post subject: Reply with quote

Hmm, I'm not sure why you are getting syntax errors. Let me give the full version info and command:

Code:

> pgfortran -V

pgfortran 14.1-0 64-bit target on x86-64 Linux -tp nehalem
The Portland Group - PGI Compilers and Tools
Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
> pgfortran -c linear_1d_operators.F90
Lowering Error: array upper bound is not a symbol for datatype 176
Lowering Error: array extnt is not a symbol for datatype 176
PGF90-F-0000-Internal compiler error. Errors in Lowering       2 (linear_1d_operators.F90: 202)
PGF90/x86-64 Linux 14.1-0: compilation aborted


Edit: I just copied and pasted directly from the OP to a new file, and I still get this same internal error, so I don't think I made a transcription error when I posted. If this is still not reproducible, maybe there's some sub-version difference, or maybe x86-64 Linux is somehow different from other platforms...
Back to top
View user's profile
cparrott



Joined: 02 May 2011
Posts: 146

PostPosted: Wed Apr 09, 2014 10:11 am    Post subject: Reply with quote

Hi Sean,

Perhaps it was a cut-and-paste error on my part last time - very sorry, if so.

Anyway, I was able to reproduce the problem you reported with PGI 14.3, as well:

Code:

cparrott@ ~/UF/SPS $ pgf90 -c module_linear_1d_operators.f90
202 ub is 14
Lowering Error: array upper bound is not a symbol for datatype 176
Lowering Error: array extnt is not a symbol for datatype 176
PGF90-F-0000-Internal compiler error. Errors in Lowering       2 (module_linear_1d_operators.f90: 202)
PGF90/x86-64 Linux 14.3-0: compilation aborted


I will file a report, and follow up once I have more information.

Best regards,

+chris
Back to top
View user's profile
Sean Patrick Santos



Joined: 15 Sep 2013
Posts: 15

PostPosted: Mon Apr 14, 2014 1:23 pm    Post subject: Reply with quote

I've reduced the test case:

Code:

module test_abstract_pgi_interface

implicit none

type, abstract :: bar_t
 contains
   procedure(foo), deferred :: my_foo
end type bar_t

abstract interface
   function foo(bar, array) result(output)
     import :: bar_t
     class(bar_t), intent(in) :: bar
     integer, intent(in) :: array(:)
     integer :: output(size(array))
   end function foo
end interface

end module test_abstract_pgi_interface


This is case reproduces the lowering error. If I try to work around this, the original file encounters a second bug, which is that the compiler rejects the following valid code:

Code:

module test_pgi_procedure_iface

implicit none

abstract interface
   subroutine no_arg_sub()
   end subroutine no_arg_sub
end interface

type, abstract :: foo
 contains
   procedure(use_sub), deferred :: foo_sub
end type foo

abstract interface
   subroutine use_sub(self, sub)
     import :: no_arg_sub, foo
     class(foo) :: self
     procedure(no_arg_sub) :: sub
   end subroutine use_sub
end interface

type, extends(foo) :: bar
 contains
   procedure :: foo_sub => implement_sub
end type bar

contains

subroutine implement_sub(self, sub)
  class(bar) :: self
  procedure(no_arg_sub) :: sub

  call sub()

end subroutine implement_sub

end module test_pgi_procedure_iface


The problem seems to be that the compiler does not recognize that the "sub" argument is the same type both inside and outside the interface block.
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    PGI User Forum Forum Index -> Programming and Compiling All times are GMT - 7 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © phpBB Group