Skip to content

cpp_if not taken in account for associated method #44

@clementFoyer

Description

@clementFoyer

When trying to generate wrapper for the following C++ code, I end up with an error at link time when linking against the Fortran module.

C++ is like:

class Foo {
  public:
    void baz() {};
    void bar() {};
};

I do not want to expose the symbol bar if ENABLE_BAR is not defined. So the YAML is such as:

declarations:
  - decl: class Foo
    declarations:
      - decl: void baz()
      - decl: void bar()
        cpp_if: if defined(ENABLE_FOOBAR)

The result is such as:

    type foo
        type(SHROUD_foo_capsule) :: cxxmem
        ! splicer begin class.Foo.component_part
        ! splicer end class.Foo.component_part
    contains
        procedure :: baz => foo_baz
        procedure :: bar => foo_bar
        procedure :: get_instance => foo_get_instance
        procedure :: set_instance => foo_set_instance
        procedure :: associated => foo_associated
        ! splicer begin class.Foo.type_bound_procedure_part
        ! splicer end class.Foo.type_bound_procedure_part
    end type foo

    [... removing operators ...]

    interface

        subroutine c_foo_baz(self) &
                bind(C, name="TES_foo_baz")
            import :: SHROUD_foo_capsule
            implicit none
            type(SHROUD_foo_capsule), intent(IN) :: self
        end subroutine c_foo_baz

#ifdef ENABLE_BAR
        subroutine c_foo_bar(self) &
                bind(C, name="TES_foo_bar")
            import :: SHROUD_foo_capsule
            implicit none
            type(SHROUD_foo_capsule), intent(IN) :: self
        end subroutine c_foo_bar
#endif

        ! splicer begin class.Foo.additional_interfaces
        ! splicer end class.Foo.additional_interfaces
    end interface

contains

    subroutine foo_baz(obj)
        class(foo) :: obj
        ! splicer begin class.Foo.method.baz
        call c_foo_baz(obj%cxxmem)
        ! splicer end class.Foo.method.baz
    end subroutine foo_baz

#ifdef ENABLE_BAR
    subroutine foo_bar(obj)
        class(foo) :: obj
        ! splicer begin class.Foo.method.bar
        call c_foo_bar(obj%cxxmem)
        ! splicer end class.Foo.method.bar
    end subroutine foo_bar
#endif

    [... Removing useless function implementation ...]

end module foo_mod

In the case where ENABLE_BAR is not defined, the module will not be able to expose the foo%bar as foo_bar subroutine will not be defined, nor the c_foo_bar interface.

If I define the following FORTRAN program:

program fortran_test
    use foo_mod
    implicit none

    type(foo) :: f

    call f%baz
#ifdef ENABLE_BAR
    call f%bar
#endif
end program fortran_test

and try to link it to the module, I have the following error risen:

wrapfFoo.F:30:17:

         procedure :: bar => foo_bar
                 1
Error: 'foo_bar' must be a module procedure or an external procedure with an explicit interface at (1)

One solution would be to add a check to node.cpp_if when defining the procedure in the type definition in the wrapfFoo.f file generated, in order to add the preprocessor directives.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions