[Bug fortran/116668] New: A very strange error when trying to copy substrings from a select type generic

2024-09-10 Thread jordan4ibanez at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116668

Bug ID: 116668
   Summary: A very strange error when trying to copy substrings
from a select type generic
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: fortran
  Assignee: unassigned at gcc dot gnu.org
  Reporter: jordan4ibanez at gmail dot com
  Target Milestone: ---

This was a simple test I was doing making a threading library for Fortran on
the latest for Linux Mint 22 on gfortran 14.
I had talked to one of the devs of the LLVM fortran compiler to solve this
problem. But I still wanted to show this because it told me to report it.

I have made the mistake of not using the report function of gfortran. If you
would like more in depth review of this, here is a freeze frame of the fix I
have mentioned:
https://github.com/jordan4ibanez/Formine/tree/cbc3f7c602b9acaf84bb405f0ab7959526a8adbb

BEGIN REPORT

BEGIN TERMINAL OUTPUT

testament.f90  done.
thread_filo_queue.f90  failed.
[  5%] Compiling...
././src/bindings/thread/thread_filo_queue.f90:239:78:

  239 | new_queue_element_pointer%string(1:string_len) =
generic(1:string_len)
  |
 1
internal compiler error: Segmentation fault
0x15967a3 crash_signal
../../src/gcc/toplev.cc:319
0x79f8c244531f ???
./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0xf04d67 gfc_conv_scalarized_array_ref
../../src/gcc/fortran/trans-array.cc:3938
0xf05c36 gfc_conv_array_ref(gfc_se*, gfc_array_ref*, gfc_expr*, locus*)
../../src/gcc/fortran/trans-array.cc:4094
0xf48146 gfc_conv_variable
../../src/gcc/fortran/trans-expr.cc:3181
0xf4e918 gfc_trans_assignment_1
../../src/gcc/fortran/trans-expr.cc:12273
0xef9b27 trans_code
../../src/gcc/fortran/trans.cc:2363
0xf99038 gfc_trans_block_construct(gfc_code*)
../../src/gcc/fortran/trans-stmt.cc:2377
0xef9bf7 trans_code
../../src/gcc/fortran/trans.cc:2459
0xf99038 gfc_trans_block_construct(gfc_code*)
../../src/gcc/fortran/trans-stmt.cc:2377
0xef9bf7 trans_code
../../src/gcc/fortran/trans.cc:2459
0xf8f7e4 gfc_trans_select_type_cases
../../src/gcc/fortran/trans-stmt.cc:3020
0xf9a9ad gfc_trans_select_type(gfc_code*)
../../src/gcc/fortran/trans-stmt.cc:3729
0xef9967 trans_code
../../src/gcc/fortran/trans.cc:2479
0xf99038 gfc_trans_block_construct(gfc_code*)
../../src/gcc/fortran/trans-stmt.cc:2377
0xef9bf7 trans_code
../../src/gcc/fortran/trans.cc:2459
0xf2ef2b gfc_generate_function_code(gfc_namespace*)
../../src/gcc/fortran/trans-decl.cc:7879
0xefef41 gfc_generate_module_code(gfc_namespace*)
../../src/gcc/fortran/trans.cc:2785
0xea188d translate_all_program_units
../../src/gcc/fortran/parse.cc:7086
0xea188d gfc_parse_file()
../../src/gcc/fortran/parse.cc:7413
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See  for instructions.
 Compilation failed for object "
src_bindings_thread_thread_filo_queue.f90.o "
 stopping due to failed compilation
STOP 1
make: *** [Makefile:27: test] Error 1

END TERMINAL OUTPUT

BEGIN SOURCE CODE

  function queue_data_constructor(generic) result(new_queue_element_pointer)
implicit none

type(queue_data), pointer :: new_queue_element_pointer
class(*), intent(in), target :: generic

allocate(new_queue_element_pointer)

select type(generic)
 type is (integer(c_int))
  new_queue_element_pointer%type = QUEUE_I32
  allocate(new_queue_element_pointer%i32)
  new_queue_element_pointer%i32 = generic

 type is (integer(c_int64_t))
  new_queue_element_pointer%type = QUEUE_I64
  allocate(new_queue_element_pointer%i64)
  new_queue_element_pointer%i64 = generic

 type is (real(c_float))
  new_queue_element_pointer%type = QUEUE_F32
  allocate(new_queue_element_pointer%f32)
  new_queue_element_pointer%f32 = generic

 type is (real(c_double))
  new_queue_element_pointer%type = QUEUE_F64
  allocate(new_queue_element_pointer%f64)
  new_queue_element_pointer%f64 = generic

 type is (logical)
  new_queue_element_pointer%type = QUEUE_BOOL
  allocate(new_queue_element_pointer%bool)
  new_queue_element_pointer%bool = generic

 type is (character(len = *, kind = c_char))
  new_queue_element_pointer%type = QUEUE_STRING
  associate (string_len => len(generic))
allocate(character(len = string_len, kind = c_char) ::
new_queue_element_pointer%string)
new_queue_element_pointer%string(1:string_len) = generic(1:string_len)
  end associate

 class default
  !? We will check if this thing is a pointer.
  !! If it

[Bug fortran/116668] A very strange error when trying to copy substrings from a select type generic

2024-09-10 Thread jordan4ibanez at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116668

--- Comment #2 from Jordan  ---
(In reply to Andrew Pinski from comment #1)
> Can you provide the full source where the ICE happens including all module
> sources?
> 
> Also since you got the gfortran from your distro you should read the
> internal compiler error message:
> See  for instructions.
> 
> 
> And report this bug to them too.

This is going to be a bit lengthy, but of course I will. :)

Here are all the modules in this little ecosystem. Please keep in mind, this
version is very sloppy and has been fixed in more recent updates.

(The C code is last because it binds to it.)


FORTRAN CODE HERE:


module thread_filo_queue
  use :: thread_types
  use :: thread_mutex
  use, intrinsic :: iso_c_binding
  implicit none


  private


  public :: concurrent_linked_filo_queue
  public :: queue_data


  integer(c_int), parameter :: QUEUE_NONE = 0
  integer(c_int), parameter :: QUEUE_I32 = 1
  integer(c_int), parameter :: QUEUE_I64 = 2
  integer(c_int), parameter :: QUEUE_F32 = 3
  integer(c_int), parameter :: QUEUE_F64 = 4
  integer(c_int), parameter :: QUEUE_BOOL = 5
  integer(c_int), parameter :: QUEUE_STRING = 6
  integer(c_int), parameter :: QUEUE_GENERIC = 7



  type :: queue_data
!* Basic types.
integer(c_int), pointer :: i32 => null()
integer(c_int64_t), pointer :: i64 => null()
real(c_float), pointer :: f32 => null()
real(c_double), pointer :: f64 => null()
logical(c_bool), pointer :: bool => null()
!* String.
character(len = :, kind = c_char), pointer :: string => null()
!* Completely polymorphic.
class(*), pointer :: generic => null()
!* Designate the type of the element.
integer(c_int) :: type = QUEUE_NONE
  end type queue_data

  interface queue_data
module procedure :: queue_data_constructor
  end interface queue_data



  type :: queue_node
type(queue_node), pointer :: next => null()
type(queue_data), pointer :: data => null()
  end type queue_node


  type :: concurrent_linked_filo_queue
private
type(queue_node), pointer :: head => null()
type(queue_node), pointer :: tail => null()
type(mutex_rwlock), pointer :: mutex => null()
type(c_ptr) :: c_mutex_pointer = c_null_ptr
integer(c_int) :: items = 0
  contains
procedure :: push => concurrent_linked_filo_queue_push
procedure :: pop => concurrent_linked_filo_queue_pop
procedure :: destroy => concurrent_linked_filo_queue_destroy
procedure :: is_empty => concurrent_linked_filo_queue_is_empty
procedure :: get_size => concurrent_linked_filo_queue_get_size
  end type concurrent_linked_filo_queue


  interface concurrent_linked_filo_queue
module procedure :: constructor_concurrent_linked_filo_queue
  end interface concurrent_linked_filo_queue


contains


  function constructor_concurrent_linked_filo_queue() result(new_queue)
implicit none

type(concurrent_linked_filo_queue) :: new_queue

new_queue%mutex => thread_create_mutex_pointer()
new_queue%c_mutex_pointer = c_loc(new_queue%mutex)
  end function constructor_concurrent_linked_filo_queue


  !* Push an element into the end of a queue.
  subroutine concurrent_linked_filo_queue_push(this, generic_pointer)
implicit none

class(concurrent_linked_filo_queue), intent(inout) :: this
type(queue_data), intent(in), pointer :: generic_pointer
integer(c_int) :: status
type(queue_node), pointer :: new_node

status = thread_write_lock(this%c_mutex_pointer)
!! BEGIN SAFE OPERATION.

if (.not. associated(generic_pointer)) then
  error stop "[Thread FILO Queue] Error: Received a null pointer."
end if

allocate(new_node)
new_node%data => generic_pointer

! If the head is null, this is the new head.
if (.not. associated(this%head)) then
  this%head => new_node
end if

! If we have a tail, it now points to the new node.
! The new node then becomes the tail.
if (associated(this%tail)) then
  this%tail%next => new_node
  this%tail => new_node
else
  ! If we do not have a tail, the new node is now the tail.
  this%tail => new_node
end if

this%items = this%items + 1

!! END SAFE OPERATION.
status = thread_unlock_lock(this%c_mutex_pointer)
  end subroutine concurrent_linked_filo_queue_push


  !* Pop the first element off the queue.
  function concurrent_linked_filo_queue_pop(this, generic_pointer_option)
result(some)
implicit none

class(concurrent_linked_filo_queue), intent(inout) :: this
class(*), intent(inout), pointer :: generic_pointer_option
logical(c_bool) :: some
integer(c_int) :: status
type(queue_node), pointer :: next_pointer

status =  thread_write_lock(this%c_mutex_pointer)
!! BEGIN SAFE OPERATION.

some = .false.

generic_pointer_option => null()

! If we have a head, the output will become the head data.
! The head will now be shifted forward, and the old head will be clean