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

ifx 2024.2.1 produces wrong code when using pFUnit

V-T
New Contributor I
817 Views

pFUnit is a unit testing framework for Fortran. Consider the following minimal example using this framework (two files in the same directory):

  • `m.pf`:

 

module m
   use FUnit
   type tt
      integer,allocatable::a(:),b(:)  ! works without `b`
   contains
      procedure::f
   end type
contains
   subroutine f(o)
      class(tt)o
      if(allocated(o%a))deallocate(o%a)
      allocate(o%a(1))  ! `ifx` produces code that considers this array as allocated here
   end
   @Test
   subroutine s()
      class(tt),allocatable::o  ! works with `type` instead of `class`
      o=tt()
      call o%f()  ! works with `f(o)` instead of `o%f()`
   end
end

 

  • `CMakeLists.txt`:

 

cmake_minimum_required(VERSION 3.12)
project(test Fortran)
include(CTest)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/pFUnit)
FetchContent_Declare(
        PFUNIT
        GIT_REPOSITORY "https://github.com/Goddard-Fortran-Ecosystem/pFUnit"
        GIT_TAG v4.8.0
)
FetchContent_MakeAvailable(PFUNIT)
add_pFUnit_ctest(
    funit_test
    TEST_SOURCES m.pf
    LABELS test
)

 

The test can be built and executed with the following commands (`ifx` 2024.2.1):

 

mkdir build
cd build
FC=ifx cmake ..
cmake --build .
ctest -L test -V

 

The test will fail with an error `forrtl: severe (151): allocatable array is already allocated`,  because the executable thinks that `o%a` is allocated at line 12 in `m.pf`, even though `allocated(o%a)` was `.false.` at the previous line. I think, it is a bug of `ifx`, because this error doesn't happen, when using `gfortran` instead, and it can be fixed by changing seemingly unrelated parts of code (like removing `b` from `tt` or changing `class(tt),allocatable` to `type(tt),allocatable`).

 

Unfortunately, I could not reduce the example further, since I don't know how the pFUnit code works.

Labels (2)
0 Kudos
8 Replies
Ron_Green
Moderator
691 Views

Something went wrong in the ctest step

 

 

[ 98%] Building Fortran object tests/funit-core/CMakeFiles/new_tests.x.dir/Test_TestMethod_before.F90.o

[100%] Building Fortran object tests/funit-core/CMakeFiles/new_tests.x.dir/new_tests.x_driver.F90.o

[100%] Linking Fortran executable new_tests.x

[100%] Built target new_tests.x

[100%] Built target build-tests

Constructing a list of tests

Done constructing a list of tests

Updating test list for fixtures

Added 0 tests to meet fixture requirements

Checking test dependency graph...

Checking test dependency graph end

No tests were found!!!

0 Kudos
V-T
New Contributor I
636 Views

Apparently, pFUnit uses internally an environment variable `PFUNIT_DIR`, which should be unset before starting the CMake configuration. I'm also getting `No tests were found!!!`, when `PFUNIT_DIR` is defined.

If it's not the issue, then maybe CMake or build software are causing this problem. I'm using CMake 3.20.2 and GNU Make 4.2.1 (on Rocky Linux 8.7).

0 Kudos
Ron_Green
Moderator
598 Views

I'm not exactly sure of the steps.  If you can get it to build and run the tests, can you update the step by step build and run instructions?  I had a look at the README.md and nothing struck me as an obvious fix we need.

0 Kudos
V-T
New Contributor I
567 Views

I'm able to build and run tests on my system with the commands in my first post. Alternatively, I can also use the following commands:

mkdir build
cd build
unset PFUNIT_DIR
FC=ifx cmake ..
make
ctest -L test -V

If you are unable to reproduce this behavior (and no tests are generated), then either there are some other environment variables that interfere with the process or the CMake configuration in pFUnit is system-dependent, which complicates the situation.

I should then look into the pFUnit code and reduce the example further to a single source code file. But I would need a lot more time for that...

0 Kudos
V-T
New Contributor I
463 Views

I reduced the example further. After you built all pFUnit files (with `cmake --build .`), you can create in the build directory a `a.f90` file with contents:

 

module m
   type t
      integer,allocatable::a(:),b(:)  ! works without `b`
   contains
      procedure::f
   end type
contains
   subroutine f(o)
      class(t)o
      if(allocated(o%a))deallocate(o%a)
      allocate(o%a(1))  ! `ifx` produces code that considers this array as allocated here
   end 
   subroutine s()
      class(t),allocatable::o  ! works with `type` instead of `class`
      o=t()
      call o%f()  ! works with `f(o)` instead of `o%f()`
   end 
end    
       
program main
   use FUnit,only:stub,TestSuite,TestMethod
   use m,only:s
   procedure(),pointer::i=>stub,f=>stub
   call funit_main(r,i,f)
contains
   function r()
      type(TestSuite)::r
      r=TestSuite('r')
      call r%addTest(TestMethod('s',s))                                                                                                                                                                     
   end 
end

 

It is a simplified version of a code that pFUnit generates using Python. It can then be compiled and executed (also in the build directory) with the following command (`/opt/intel/oneapi/compiler/2024.2/lib/libiomp5.so` should be replaced with the right path to this library):

 

ifx -I./pFUnit/pfunit-build/src/funit/mod -fiopenmp -c a.f90 -o a.o && ifx a.o pFUnit/pfunit-build/src/funit/libfunit.a /share/apps/intel/oneapi/compiler/2024.2/lib/libiomp5.so pFUnit/pfunit-build/extern/fArgParse/src/libfargparse.a pFUnit/pfunit-build/extern/fArgParse/extern/gFTL-shared/src/v2/libgftl-shared-v2.a && ./a.out

 

It's also a simplified version of a building command from CMake.

This executable (`a.out`) produces the error that I described in the first post.

 

0 Kudos
Ron_Green
Moderator
690 Views

same with a NAG fortran run

$ ctest -L test -V

UpdateCTestConfiguration  from :/nfs/pdx/proj/icl/devshare/rwgreen/pFUnit/pFUnit/build/DartConfiguration.tcl

Add coverage exclude regular expressions.

UpdateCTestConfiguration  from :/nfs/pdx/proj/icl/devshare/rwgreen/pFUnit/pFUnit/build/DartConfiguration.tcl

Test project /nfs/pdx/proj/icl/devshare/rwgreen/pFUnit/pFUnit/build

Run command: /usr/bin/cmake --build . --config "Release" --target "build-tests"

[  1%] Built target posix_predefined.x

[  1%] Built target generate_posix_parameters

[ 10%] Built target m4_type_includes

[ 36%] Built target gftl-shared-v2

[ 62%] Built target gftl-shared-v2-as-default

[ 65%] Built target fargparse

[ 72%] Built target funit-core

[ 77%] Built target fhamcrest

[ 86%] Built target asserts

[ 86%] Built target funit-main

[ 86%] Built target funit

[ 90%] Built target fhamcrest_tests.x

[ 90%] Built target robust

[ 90%] Built target remote.x

[ 91%] Built target robust_tests.x

[ 91%] Built target other_shared

[ 93%] Built target funit_tests

[ 93%] Built target funit_tests.x

[100%] Built target new_tests.x

[100%] Built target build-tests

Constructing a list of tests

Done constructing a list of tests

Updating test list for fixtures

Added 0 tests to meet fixture requirements

Checking test dependency graph...

Checking test dependency graph end

No tests were found!!!

0 Kudos
V-T
New Contributor I
502 Views

I believe, I reduced the code to the absolute minimum (now without pFUnit). `ifx` produces an executable with the same error as in the first post, when the following code is compiled with the `-fiopenmp` option:

module m
   type t
      integer,allocatable::a(:)
   end type
contains
   subroutine f(o)
      class(t)o
      if(allocated(o%a))deallocate(o%a)
      allocate(o%a(1))  ! `ifx` produces code that considers this array as allocated here
   end
   subroutine s()
      type(t),allocatable::o
      o=t()
      call f(o)
   end
end

module n
   type u
   end type
   type v
      class(u),allocatable::e
      procedure(i),nopass,pointer::m
   end type
   interface
      subroutine i()
      end
   end interface
contains
   function c(m)result(o)
      procedure(i)m
      type(v)o
      o%m=>m
   end
end

program p
   use m
   use n
   type(v)o
   o=c(s)
   call o%m()
end

 

0 Kudos
V-T
New Contributor I
275 Views

This issue seems to have be fixed only partially in the newest version of ifx (2025.0.0): my last minimal example doesn't cause this error, but the version with pFUnit still doesn't work.

0 Kudos
Reply