Skip to content

[flang] Preprocessor substitution in bind(C) names #96781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bcornille opened this issue Jun 26, 2024 · 10 comments · Fixed by #96987
Closed

[flang] Preprocessor substitution in bind(C) names #96781

bcornille opened this issue Jun 26, 2024 · 10 comments · Fixed by #96987
Assignees

Comments

@bcornille
Copy link

bcornille commented Jun 26, 2024

Issue:

flang does not substitute preprocessor tokens in BIND(C) names. This reproducer contains continuation lines in the same spirit as #78797. This appears to be a workaround in order to get token pasting inside character/string literals. Open to discussing whether this should be intended behavior, but it is used extensively in the a customer codebase and we'd need to find an alternative solution.

Reproducer:

main.F90

program main
  implicit none
#define TEMP_LETTER b
#define VAL c
  integer, parameter :: a_&
    &b_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&TEMP_LETTER&
&_wrapper_&
&VAL&
& (input) &
  bind(C, name="test_&
    &TEMP_LETTER&
    &_&
    &VAL&
    &_f")
  use iso_c_binding
  integer :: input
end subroutine test_&
&TEMP_LETTER&
&_wrapper_&
&VAL
end program main

preprocessor output

flang-new -E main.F90

      program main
      implicit none


      integer, parameter :: a_b_c = 1

      write(*,*) a_b_c
      contains
      subroutine test_b_wrapper_c(input) bind(C, name="test_TEMP_LETTER_&
     &VAL_f")








      use iso_c_binding
      integer :: input
      end subroutine test_b_wrapper_c



      end program main

gfortran behavior

gfortran -E main.F90

program main
  implicit none


  integer, parameter :: a_&
    &b_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&b&
&_wrapper_&
&c&
& (input) &
  bind(C, name="test_&
    &b&
    &_&
    &c&
    &_f")
  use iso_c_binding
  integer :: input
end subroutine test_&
&b&
&_wrapper_&
&c
end program main
@github-actions github-actions bot added the flang Flang issues not falling into any other category label Jun 26, 2024
@klausler
Copy link
Contributor

Why not use stringizing and //?

@klausler
Copy link
Contributor

program main
  implicit none
#define STR2(x) #x
#define STR(x) STR2(x)
#define TEMP_LETTER b
#define VAL c
  integer, parameter :: a_&
    &b_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&TEMP_LETTER&
&_wrapper_&
&VAL&
& (input) &
  bind(C, name="test_&
    &"//STR(TEMP_LETTER)//"&
    &_&
    &"//STR(VAL)//"&
    &_f")
  use iso_c_binding
  integer :: input
end subroutine test_&
&TEMP_LETTER&
&_wrapper_&
&VAL
end program main

@EugeneZelenko EugeneZelenko added flang:frontend and removed flang Flang issues not falling into any other category labels Jun 26, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 26, 2024

@llvm/issue-subscribers-flang-frontend

Author: Brian Cornille (bcornille)

### Issue: flang does not substitute preprocessor tokens in BIND(C) names. This reproducer contains continuation lines in the same spirit as #78797. This appears to be a workaround in order to get token pasting inside character/string literals. Open to discussing whether this should be intended behavior, but it is used extensively in the a customer codebase and we'd need to find an alternative solution. ### Reproducer: #### main.F90 ```Fortran program main implicit none #define TEMP_LETTER b #define VAL c integer, parameter :: a_& &b_c = 1 write(*,*) a_b_c contains subroutine test_& &TEMP_LETTER& &_wrapper_& &VAL& & (input) & bind(C, name="test_& &TEMP_LETTER& &_& &VAL& &_f") use iso_c_binding integer :: input end subroutine test_& &TEMP_LETTER& &_wrapper_& &VAL end program main ``` #### preprocessor output `flang-new -E main.F90` ```Fortran program main implicit none
  integer, parameter :: a_b_c = 1

  write(*,*) a_b_c
  contains
  subroutine test_b_wrapper_c(input) bind(C, name="test_TEMP_LETTER_&
 &VAL_f")








  use iso_c_binding
  integer :: input
  end subroutine test_b_wrapper_c



  end program main
#### gfortran behavior
`gfortran -E main.F90`

program main
implicit none

integer, parameter :: a_&
&b_c = 1
write(,) a_b_c
contains
subroutine test_&
&b&
&wrapper&
&c&
& (input) &
bind(C, name="test_&
&b&
&_&
&c&
&f")
use iso_c_binding
integer :: input
end subroutine test
&
&b&
&wrapper&
&c
end program main

</details>

@bcornille
Copy link
Author

I can bring this back to the offending codebase, but am I correct in inferring that you would prefer not to support this pattern?

@klausler
Copy link
Contributor

Preprocessors have not been replacing macros in string literals since 1989. Not going to do it here.

@bcornille
Copy link
Author

gfortran appears to fail on the provided example.

>> gfortran -E main_stringize.F90
# 1 "main_stringize.F90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main_stringize.F90"
program main
  implicit none




  integer, parameter :: a_&
    &b_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&b&
&_wrapper_&
&c&
& (input) &
  bind(C, name="test_&
    &"//STR(TEMP_LETTER)//"&
    &_&
    &"//STR(VAL)//"&
    &_f")
  use iso_c_binding
  integer :: input
end subroutine test_&
&b&
&_wrapper_&
&c
end program main

Maybe it thinks that those lines are string literals. Guess that would be a bug in gfortran.

@bcornille
Copy link
Author

Apparently the preprocessor as invoked by gfortran doesn't stringize.
https://stackoverflow.com/questions/31649691/stringify-macro-with-gnu-gfortran
This presents a challenge for migrating the given pattern.

@klausler
Copy link
Contributor

I have a solution that is portable to both gfortran and flang-new, but it's pretty ugly. I'll think about this some more.

@klausler
Copy link
Contributor

module m
  implicit none
#define TEMP_LETTER b
#define VAL c
#ifdef __GFORTRAN__
#define Q "
#define STR(x) x
#else
#define Q
#define STR2(x) #x
#define STR(x) STR2(x)
#endif
  integer, parameter :: a_&
    &b_c = 1
contains
subroutine test_&
&TEMP_LETTER&
&_wrapper_&
&VAL&
& (input) &
  bind(C, name="test_"//&
&Q&
&STR(TEMP_LETTER)&
&Q//"_"//&
&Q&
&STR(VAL)&
&Q//"_f")
  use iso_c_binding
  integer :: input
end subroutine test_&
&TEMP_LETTER&
&_wrapper_&
&VAL
end

klausler added a commit to klausler/llvm-project that referenced this issue Jun 27, 2024
…literals

To help port codes from compilers using pre-ANSI C preprocessors, which
didn't care much about context when replacing macros, support the replacement
of keyword macros in quoted character literals when (and only when) the
name of the keyword macro constitutes the entire significant portion of
a free form continuation line.  See the new test case for a motivating
example.

Fixes llvm#96781.
@klausler
Copy link
Contributor

#96987

@klausler klausler self-assigned this Jun 28, 2024
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this issue Jul 3, 2024
llvm#96987)

…literals

To help port codes from compilers using pre-ANSI C preprocessors, which
didn't care much about context when replacing macros, support the
replacement of keyword macros in quoted character literals when (and
only when) the name of the keyword macro constitutes the entire
significant portion of a free form continuation line. See the new test
case for a motivating example.

Fixes llvm#96781.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants