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

Ifort not catching name conflict in a subroutine but caught in a program [bug?]

spg
Novice
1,156 Views

(ifort version 2021.2.0 from intel oneAPI)

[Bug?] A subroutine that defines a variable with the same name as a function from a used module compiles just fine; The error (undefined reference) is caught only when linking. The compiler behavior in this case seems to be a bug from my understanding;

If the main program defines a variable with the same name as a function from a used module, the compiler issues error #6401: The attributes of this name conflict with those made accessible by a USE statement. This is what I expect.

 

Is it a bug or the expected behavior?

 

Code listing.

========================================================

First case, subroutine uses module that defines a function, declare a variable with the same name as the function

-------------------------

cat test2.f90

 

!
!> simple module for a function
module func_mod
    !
    !
implicit none
    !
    !
contains
    !
    function func()result(res)
        integer :: res
        !
        res = 3
    end function func
    !
end module func_mod
!
!> simple module for a subroutine
module sub_mod
    use func_mod
implicit none
    !
    !
contains
    !
    subroutine sub(rr)
    use func_mod
    implicit none
        integer :: rr
        integer :: func
        !
        rr = func()
    end subroutine sub
    !
end module sub_mod


!
!> @brief test program
!<
program test
    use sub_mod
implicit none
    integer :: rr
    
    call sub( rr )
    print*, "rr =", rr
    !
end program test

 

$ifort -c test2.f90

$

 

Second case: The main program use the module that has a function, if the main program defines a variable with the same name as the function from a used module, the compiler issues an error;

--------------------------------------

cat cat test.f90

 

!
!> simple module for a function
module func_mod
    !
    !
implicit none
    !
    !
contains
    !
    function func()result(res)
        integer :: res
        !
        res = 3
    end function func
    !
end module func_mod

!
!> @brief test program
!<
program test
    use func_mod
implicit none
    integer  :: func
    !
    print*, "func =", func()
    !
end program test

 

$ifort -c test.f90

test.f90(25): error #6401: The attributes of this name conflict with those made accessible by a USE statement.   [FUNC]
   integer  :: func
----------------^
compilation aborted for test.f90 (code 1)

$

0 Kudos
1 Solution
IanH
Honored Contributor II
1,080 Views

 

 


@andrew_4619 wrote:

... Declaring local names that overide module names is allowed...

That's not the case.  That is permitted with host association, but the rules for use association are different.  F2018 14.2.2p9 - "The local identifier of an entity made accessible by a USE statement shall not appear in any other nonexecutable statement that would cause any attribute (8.5) of the entity to be specified in the scoping unit that contains the USE statement, except that it may appear in a PUBLIC or PRIVATE statement in the scoping unit of a module and it may be given the ASYNCHRONOUS or VOLATILE attribute.".

I am in two minds as to whether a conforming compiler under the standard must issue a diagnostic for this programming error, but I certainly would expect one.

The interaction between use association and host association can be tricky for both humans and compilers to navigate.  The compiler is getting confused by the otherwise pointless/redundant `use func_mod` statement (line 21 of the first example) that is in the specification part of the `sub_mod` module.  Delete that use statement and you'll get the appropriate diagnostic.

View solution in original post

0 Kudos
10 Replies
andrew_4619
Honored Contributor II
1,125 Views

In the first  example you declared an integer "func", that could be a external function, tghe absense of an external function is only known at link time. Declaring local names that overide module names is allowed.

Try this code  with the newer implicit none! 

!
!> simple module for a function
module func_mod
    !
    !
implicit none(type, external)
    !
    !
contains
    !
    function func()result(res)
        integer :: res
        !
        res = 3
    end function func
    !
end module func_mod
!
!> simple module for a subroutine
module sub_mod
    use func_mod
    implicit none(type, external)
    !
    !
contains
    !
    subroutine sub(rr)
    use func_mod
        integer :: rr
        integer :: func
        !
        rr = func()
    end subroutine sub
    !
end module sub_mod


!
!> @brief test program
!<
program test
    use sub_mod
    implicit none(type, external)
    integer :: rr
    
    call sub( rr )
    print*, "rr =", rr
    !
end program test

 

0 Kudos
spg
Novice
1,107 Views

Thank you for your explanation.

I have other questions:

1) Why does the compiler catch that conflict in the main program without <implicit none(type,external)> and not in a subroutine?

2) Why does the compiler catch it when the conflict is with a subroutine name instead of a function name? In other terms why does the compiler allows to override function names but not subroutine names, when I simply have <implicit none>

 

Thank you again.

0 Kudos
spg
Novice
1,039 Views

With a better understanding from @IanH explanations and suggestions, the question 1, does not have its place anymore.

The question 2 does not either, after a deeper look and other tests, I believe I initially got confused by something else. 

With the use statement only in the specification part of the module, or both in the specification part of the module and of the procedure, Ifort will let the programmer override any name from the used module. 

If the use statement is only in the procedure, ifort will catch the name conflict and it makes sense: that is what is happening in the main program for ifort to catch the conflict.

0 Kudos
IanH
Honored Contributor II
1,081 Views

 

 


@andrew_4619 wrote:

... Declaring local names that overide module names is allowed...

That's not the case.  That is permitted with host association, but the rules for use association are different.  F2018 14.2.2p9 - "The local identifier of an entity made accessible by a USE statement shall not appear in any other nonexecutable statement that would cause any attribute (8.5) of the entity to be specified in the scoping unit that contains the USE statement, except that it may appear in a PUBLIC or PRIVATE statement in the scoping unit of a module and it may be given the ASYNCHRONOUS or VOLATILE attribute.".

I am in two minds as to whether a conforming compiler under the standard must issue a diagnostic for this programming error, but I certainly would expect one.

The interaction between use association and host association can be tricky for both humans and compilers to navigate.  The compiler is getting confused by the otherwise pointless/redundant `use func_mod` statement (line 21 of the first example) that is in the specification part of the `sub_mod` module.  Delete that use statement and you'll get the appropriate diagnostic.

0 Kudos
spg
Novice
1,046 Views

@IanH thanks for the explanation.

Removing the `use func_mod` in the specification part of the module solves the problem., I mean makes the compiler to complain about name conflict.

That makes me better understand the comment of @andrew_4619 that "Declaring local names that overide module names is allowed". I misunderstood it in the first place as declaring local names overrides names from used modules.

 

It appears that ifort ignores the use statement in the module procedure, if the module specification already have that use statement. Shouldn't it be the reverse? meaning that the compiler ignores the module level use statement when the module procedure locally have the same use statement?

 

 

0 Kudos
andrew_4619
Honored Contributor II
1,065 Views

Yes correct as ever Ian , there are things that are wrong with the code but it is definitely true to say the compiler is not being helpful. 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,059 Views

>>...but it is definitely true to say the compiler is not being helpful.

The compiler may have a different opinion

Jim Dempsey

0 Kudos
spg
Novice
1,046 Views

@jimdempseyatthecove wrote:

>>...but it is definitely true to say the compiler is not being helpful.

The compiler may have a different opinion


I like that. It made my day, to think that the compiler may have a different opinion than I.

0 Kudos
spg
Novice
1,046 Views

I just want to put this observation as its own response to the question, as it seems to be what is going on.

It appears that ifort ignores the use statement in the module procedure, if the module specification already have that use statement. Shouldn't it be the reverse? meaning that the compiler ignores the module level use statement when the module procedure locally have the same use statement?

0 Kudos
IanH
Honored Contributor II
1,019 Views

The compiler should not ignore statements - but it should appropriately apply the rules for host and use association.  You are just seeing the consequences of a likely flaw in the compiler's logic, potentially only exposed when it is presented with erroneous Fortran source.

 

0 Kudos
Reply