I have a string type using the obvious approach of encapsulating an "character(len=:), allocatable" variable. I came upon a bug in my code, where I did something like (look at the code below):
str = str%cs(1:5)
which lead to a result with some control characters in it. Depending on the code, valgrind either show invalid memory reads, or overlapping addresses in call to memcpy. The obvious solution is to make a copy of the right hand side character sequence, deallocate the derived-type component of the left hand side and use the copy to initialise the string. Is there a way to tell the compiler that self%cs and cs might overlap in memory, so that the compiler can generate appropriate code on its own? In particular, the copying is not necessary in general, only in a few cases.
BTW, there is also a compiler bug (already reported), with the overloading of the len intrinsic. Adding an "intrinsic :: len" solves the issue, at least for ifort19.
module mod implicit none private type, public :: string character(len=:), allocatable :: cs contains procedure, public :: len => string_len procedure, public :: assign, assign_notworking ! generic, public :: assignment(=) => assign generic, public :: assignment(=) => assign_notworking end type string interface len module procedure string_len end interface len contains elemental function string_len(self) result(l) integer :: l class(string), intent(in) :: self l = len(self%cs) end function string_len elemental subroutine assign(self, cs) class(string), intent(inout) :: self character(len=*), intent(in) :: cs ! this declaration is required due to a bug in ifort intrinsic :: len character(len=len(cs)) :: cs_copy ! first make a copy as cs and self%cs might overlap cs_copy = cs deallocate(self%cs) allocate(self%cs, source = cs_copy) end subroutine assign elemental subroutine assign_notworking(self, cs) class(string), intent(inout) :: self character(len=*), intent(in) :: cs ! this is not working if cs and self%cs overlap in memory self%cs = cs end subroutine assign_notworking end module mod program assign_overlap use mod implicit none type(string) :: str str%cs = '0123456789' print *, '"'//str%cs//'"' str = str%cs(1:5) print *, '"'//str%cs//'"' end program assign_overlap