Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29234 Discussions

Compiler bug: wrong type-bound procedure called

WileyOne
Novice
1,781 Views

Compiler: ifx (IFX) 2025.0.4

OS: Rocky Linux 8.9 (Green Obsidian)

 

This is a strange one. The code compiles fine but crashes at runtime; it seems to be an issue with the underlying procedure table. In short, the wrong type-bound procedure is called, eventually leading the program to crash.

 

The following is a much reduced example from our team's architecture. I expect the type-bound procedure `run` on class `component` to be called, but the example crashes on line 98. As I paired down code from our original situation, the behavior of the program varied at this location; sometimes the obviously wrong procedure would be called, other times it would enter an endless loop until a stack overflow occurred, and still others crashed immediately (like the provided example). It is this behavior that original led me to suspect a compiler bug.

 

module Component_Header
    implicit none
    private
    public :: component, componentList

    type :: component
        contains
        procedure, public :: run
    end type

    type Element
        class(component), allocatable :: object
    end type

    type componentList
        private

        type(Element), pointer :: item => null()

        contains
        final           :: final_componentList
        generic, public :: assignment(=) => copy_componentList

        procedure, public :: &
            add => add_componentList, &
            get => get_componentList

        procedure, private :: &
            copy_componentList
    end type

    contains

    subroutine run(this)
        class(component), intent(inout) :: this
        print *, 'this routine should run'
    end subroutine

    subroutine final_componentList(this)
        type(componentList) :: this

        if (associated(this%item)) deallocate(this%item)
    end subroutine

    subroutine copy_componentList(lhs,rhs)
        class(componentList), intent(out) :: lhs
        class(componentList), intent(in)  :: rhs

        call lhs%add(rhs%item%object)
    end subroutine

    subroutine add_componentList(this,something)
        class(componentList), target, intent(inout) :: this
        class(component),             intent(in)    :: something

        allocate(this%item)
        this%item%object = something
    end subroutine

    function get_componentList(this) result(something)
        class(componentList), target, intent(in) :: this
        class(component),        pointer :: something

        something => this%item%object
    end function

end module

module Container_Header
    use Component_Header
    implicit none
    private
    public :: Container

    type :: Container ! oddity #1
        type(componentList) :: components
        contains
        procedure, public :: &
            runComponents, &
            addComponent
    end type

    contains

    subroutine addComponent(this)
        class(Container), intent(inout) :: this

        call this%components%add(component())
    end subroutine

    subroutine runComponents(this)
        class(Container), intent(inout) :: this

        class(component), pointer :: comp => null()
        
        print *, 'running the container'
        comp => this%components%get()
        call comp%run() !!! this line breaks !!!
    end subroutine

end module

module Mode_Header
    use Container_Header
    implicit none
    private
    public :: mode, mode_constructor

    type :: ModeInterface ! oddity #2
    end type

    type, extends(ModeInterface) :: mode
        type(Container) :: myContainer
        contains
        procedure, public :: execute
    end type

    contains

    function mode_constructor() result(this) ! oddity #3
        type(mode) :: this

        call this%myContainer%addComponent()
    end function

    subroutine execute(this)
        class(mode), intent(inout) :: this
        print *, 'execute was called'
        call this%myContainer%runComponents()
    end subroutine

end module

program main
    use Mode_Header
    implicit none
    type(mode) :: myMode

    myMode = mode_constructor()
    call myMode%execute()
end program

 

This code is also attached as a file below. Any and all help is appreciated.

 

Additional Details

Someone might initially be tempted to think that a dangling pointer causes this crash. After all, the `component` object created on line 88 is finalized when exiting the constructor on line 139, so the new `item` pointer existing within in `myMode` is now referencing invalid memory. While it's true that the original `component` object is finalized, the class `componentList` has a defined `assignment` operator - `copy_componentList` - that performs a deep copy. Therefore, the `item` pointer within the `myMode` object references its own copy of `component`. Stepping through the program with gdb confirms that these routines behave as expected.

 

Note some of the oddities I observed when pairing down our architecture to the given example:

  1. Cutting `Container` and moving its functionality into `mode` causes the error to vanish.
  2. Extending `mode` from `ModeInterface` produces the bug but behaves as expected when `mode` is not an extension of a base class.
  3. Switching the routine `mode_constructor` from a function to a subroutine fixes the error. This is not the case, however, where we originally encountered the bug.

These are not realistic workarounds for our situation; again, this is a significant simplification from our framework. Certain aspects seems silly separated from their context. I am simply explaining why certain features were included in the bugged example.

Labels (2)
1 Solution
Ron_Green
Moderator
1,353 Views

Yes, the fix for this bug is in 2025.2.0.  I also confirmed the fix just to be sure:

$ ifx -g -O0 -traceback -what -V test.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.2.0 Build 20250605
Copyright (C) 1985-2025 Intel Corporation. All rights reserved.

 Intel(R) Fortran 25.0-1485
GNU ld version 2.35.2-17.el9

$ ./a.out
 execute was called
 running the container
 this routine should run
$ 

View solution in original post

0 Kudos
4 Replies
WileyOne
Novice
1,778 Views

Our team also encountered this bug with the following configuration:

Compiler: ifx (IFX) 2024.2.0

OS: Linux Mint 21.3 (Virginia)

0 Kudos
WileyOne
Novice
1,376 Views

As of 2025.2.0 this is now working. I will wait for confirmation from one of the admins before marking this issue as resolved.

0 Kudos
Ron_Green
Moderator
1,354 Views

Yes, the fix for this bug is in 2025.2.0.  I also confirmed the fix just to be sure:

$ ifx -g -O0 -traceback -what -V test.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.2.0 Build 20250605
Copyright (C) 1985-2025 Intel Corporation. All rights reserved.

 Intel(R) Fortran 25.0-1485
GNU ld version 2.35.2-17.el9

$ ./a.out
 execute was called
 running the container
 this routine should run
$ 
0 Kudos
WileyOne
Novice
1,149 Views

Thank you, @Ron_Green. Please pass along thanks from our team to the developers!

0 Kudos
Reply