This is an archive of the discontinued LLVM Phabricator instance.

[flang][Preprocessor] Constrain a bit more implicit continuations
ClosedPublic

Authored by rogfer01 on Aug 8 2023, 9:45 AM.

Details

Summary

D155499 fixed an issue with implicit continuations. The fixes included a nested parenthesis check during definition of a macro which is then carried over in the scanner state.

This leads to the following corner case to fail:

subroutine foo(a, d)
  implicit none
  integer :: a
  integer :: d

#define sub(x, y) foo2(x, y)
#define bar )

   ! An implicit continuation won't be considered unless
   ! the definition of "bar" above is removed/commented
   call sub(1,
     2)
end subroutine foo

The definition of bar is indeed unbalanced but it is not even used in the code, so it should not impact whether we apply implicit continuation in the expansion of sub.

This change aims at addressing this issue by removing the balance check and constraining a bit more when we consider implicit continuations: only when we see a left parenthesis after a function-like macro, not a object-like macro. In this case I think it is OK to (unconditionally) implicitly continue to the next line in search of the corresponding right parenthesis. This is, to my understanding, similar to what the C preprocessor would do according to the description in [1].

[1] https://www.spinellis.gr/blog/20060626/

Diff Detail

Event Timeline

rogfer01 created this revision.Aug 8 2023, 9:45 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptAug 8 2023, 9:45 AM
rogfer01 requested review of this revision.Aug 8 2023, 9:45 AM
rogfer01 retitled this revision from [flang][Preprocessor] Constrain a bit more intrinsic continuations to [flang][Preprocessor] Constrain a bit more implicit continuations.Aug 8 2023, 9:45 AM
klausler requested changes to this revision.Aug 8 2023, 9:48 AM

This patch would cause the original motivating test case to fail again. In the new test, call sub(1, 2 bar would fail.

This revision now requires changes to proceed.Aug 8 2023, 9:48 AM

The original testcase was not expanding a function-like macro.

When expanding a function-like macro we need to find an unexpanded ).

subroutine foo()
  implicit none

#define sub(x, y) foo2(x, y)
#define bar )

   call sub(1, 2 bar
   print *, "hello"
end subroutine foo

This will be preprocessed as

#line "./t.F90" 1
      subroutine foo()
      implicit none




      call sub(1, 2 ) print *, "hello" end subroutine foo

Which is nonsensical. I'll see if we can emit a diagnostic in this case because we didn't find any `)' when expanding a function-like macro.

Note that something odd like

subroutine foo()
  implicit none

#define sub(x, y) foo2(x, y)
#define bar )

   call sub(1, 2 bar
   ) print *, "hello"
end subroutine foo

gives a different diagnostic

error: Could not scan t.F90
./t.F90:7:9: error: Unmatched ')'
     call sub(1, 2 bar
          ^^^^^^^^^^^^
./t.F90:4:19: in a macro defined here
  #define sub(x, y) foo2(x, y)
                    ^^^^^
that expanded to:
  foo2(1,  2 ))
              ^

because we do find the ) and then we expand the arguments (including the bar).

Does this seem reasonable to you?

klausler accepted this revision.Aug 9 2023, 4:20 PM
This revision is now accepted and ready to land.Aug 9 2023, 4:20 PM