Skip to content

[flang] Failed substitution with preprocessor #78797

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 Jan 19, 2024 · 12 comments · Fixed by #78868
Closed

[flang] Failed substitution with preprocessor #78797

bcornille opened this issue Jan 19, 2024 · 12 comments · Fixed by #78868
Assignees

Comments

@bcornille
Copy link

Issue:

flang does not substitute a preprocessor variable in a snake case Fortran variable. In order to get substitution some codes use continuation lines so that the preprocessor variable can be inserted in-between underscores in code. flang appears to concatenate continuation lines prior to applying the preprocessor substitutions so the substitution does not occur.

Reproducer:

main.F90

program main
  implicit none
#define LETTER b
  integer, parameter :: a_&
    &LETTER&
    &_c = 1
  write(*,*) a_b_c
end program main

compilation:

>> flang-new -c main.F90
error: Semantic errors in main.F90
./main.F90:8:14: error: No explicit type declared for 'a_b_c'
    write(*,*) a_b_c
               ^^^^^

preprocessed source:

>> flang-new -E main.F90
#line "./main.F90" 1
      program main
      implicit none
      integer, parameter :: a_LETTER_c = 1
      write(*,*) a_b_c
      end program main

GNU behavior:

>> gfortran -E main.F90
# 1 "main.F90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.F90"
program main
  implicit none
  integer, parameter :: a_&
    &b&
    &_c = 1
  write(*,*) a_b_c
end program main
@github-actions github-actions bot added the flang Flang issues not falling into any other category label Jan 19, 2024
@EugeneZelenko EugeneZelenko added flang:frontend and removed flang Flang issues not falling into any other category labels Jan 19, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 19, 2024

@llvm/issue-subscribers-flang-frontend

Author: Brian Cornille (bcornille)

### Issue: flang does not substitute a preprocessor variable in a snake case Fortran variable. In order to get substitution some codes use continuation lines so that the preprocessor variable can be inserted in-between underscores in code. flang appears to concatenate continuation lines prior to applying the preprocessor substitutions so the substitution does not occur.

Reproducer:

main.F90

program main
  implicit none
#define LETTER b
  integer, parameter :: a_&amp;
    &amp;LETTER&amp;
    &amp;_c = 1
  write(*,*) a_b_c
end program main

compilation:

&gt;&gt; flang-new -c main.F90
error: Semantic errors in main.F90
./main.F90:8:14: error: No explicit type declared for 'a_b_c'
    write(*,*) a_b_c
               ^^^^^

preprocessed source:

&gt;&gt; flang-new -E main.F90
#line "./main.F90" 1
      program main
      implicit none
      integer, parameter :: a_LETTER_c = 1
      write(*,*) a_b_c
      end program main

GNU behavior:

&gt;&gt; gfortran -E main.F90
# 1 "main.F90"
# 1 "&lt;built-in&gt;"
# 1 "&lt;command-line&gt;"
# 1 "main.F90"
program main
  implicit none
  integer, parameter :: a_&amp;
    &amp;b&amp;
    &amp;_c = 1
  write(*,*) a_b_c
end program main

@klausler
Copy link
Contributor

That's indeed how it works in f18; continuation lines are combined prior to macro substitution, so that macro references can span multiple lines.

@bcornille
Copy link
Author

So I guess due to that design decision there is no way to get macro substitution in the middle of a variable as demonstrated by the example code, correct? A macro function would probably need to be used instead to construct the composite name.

@klausler
Copy link
Contributor

Token pasting with ## works. In fixed-form code, just use spaces between the parts of the name.

@klausler
Copy link
Contributor

I'm looking into tweaking the interaction between continuation line joining and preprocessing a little to accommodate this case. In short, I may be able to allow the pp-tokens that constitute a macro reference to span multiple continuation lines, but not the individual identifier tokens themselves.

klausler added a commit to klausler/llvm-project that referenced this issue Jan 21, 2024
Some Fortran codes use line continuation as a form of token pasting;
see llvm#78797.  This works
in compilers that run a C-like preprocessor and then apply line
continuation to its output; f18 implements line continuation during
tokenization and preprocessing, but can still handle this case.

In the rare case when an identifier is split across two or more
continuation lines, this patch allows its parts to be distinct
preprocessing tokens for the purpose of macro replacemnt.  They
(or their replacement texts) can be effectively rejoined later as a
single identifier when the cooked character stream is tokenized in
parsing.

Fixes llvm#78797.
@klausler
Copy link
Contributor

#78868

@klausler klausler self-assigned this Jan 22, 2024
@klausler
Copy link
Contributor

Patch has been merged into llvm-project/main.

@bcornille
Copy link
Author

I have encountered some patterns that are not addressed by this fix.

program main
  implicit none
#define LETTER b
  integer, parameter :: a_&
    &LETTER&
    &_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&LETTER&
&(input)
  integer :: input
end subroutine test_&
&LETTER
end program main

output:

>> flang-new -E main.F90
#line "./main.F90" 1
      program main
      implicit none

      integer, parameter :: a_b_c = 1


      write(*,*) a_b_c
      contains
      subroutine test_LETTER(input)


      integer :: input
      end subroutine test_LETTER

      end program main

Please advise whether these can be accommodated or whether code changes should be considered instead.

@klausler
Copy link
Contributor

klausler commented Jan 26, 2024

#79628 (updated)

@EugeneZelenko
Copy link
Contributor

Not merged yet.

@EugeneZelenko EugeneZelenko reopened this Jan 29, 2024
@klausler
Copy link
Contributor

Fix merged.

@bcornille
Copy link
Author

Hi Peter,

Apologies, but I have one more edge case.
In this case there is a space between the token and the continuation symbol prior to the subroutine arguments.

program main
  implicit none
#define LETTER b
  integer, parameter :: a_&
    &LETTER&
    &_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&LETTER &
&(input)
  integer :: input
end subroutine test_&
&LETTER
end program main

Let me know if this additional space is for some reason problematic with respect to being valid source code and I will advise changes in the original application.

gfortran for reference:

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

  integer, parameter :: a_&
    &b&
    &_c = 1
  write(*,*) a_b_c
contains
subroutine test_&
&b &
&(input)
  integer :: input
end subroutine test_&
&b
end program main

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