Description
Flang fails to parse its own preprocessor output:
$ flang -E -Xflang -fno-reformat ~/src/llvm-project/flang/module/ieee_arithmetic.f90 -o - | flang - -fsyntax-only
error: Could not parse -
standard input:105:3: error: expected declaration construct
elemental logical function ieee_is_finite_a2(x); real(2), intent(in) :: x; !dir$ ignore_tkr(d) x; end function ieee_is_finite_a2; elemental logical function ieee_is_finite_a3(x); real(3), intent(in) :: x; !dir$ ignore_tkr(d) x; end function ieee_is_finite_a3; elemental logical function ieee_is_finite_a4(x); real(4), intent(in) :: x; !dir$ ignore_tkr(d) x; end function ieee_is_finite_a4; elemental logical function ieee_is_finite_a8(x); real(8), intent(in) :: x; !dir$ ignore_tkr(d) x; end function ieee_is_finite_a8;
^
standard input:2:1: in the context: specification part
use __fortran_ieee_exceptions
^
standard input:1:1: in the context: module
module ieee_arithmetic
^
standard input:106:5: error: expected end of statement
end interface ieee_is_finite
^
[...]
The failing like comes from
llvm-project/flang/module/ieee_arithmetic.f90
Line 342 in a6385a8
which after preprocessing expands to
elemental logical function ieee_is_finite_a2(x); real(2), intent(in) :: x; !dir$ ignore_tkr(d) x; end function ieee_is_finite_a2;
Flang manages to parse this if the the !dir$
is within a macro, but not if expanded. The error comes from interpreting !
as a comment line, which removes everything following on the same line from the cooked character stream, including end function ieee_is_finite_a2;
, which causes the error. My initial diagnosis was that Prescanner::IsCompilerDirectiveSentinel
does not recognize !
as a potential start of a compiler directive, but this does not fix the inconcistencies:
module m
contains
! Directive inside macro on same line; works
#define MACRO(X) subroutine func1(X); real(2) :: X; !dir$ ignore_tkr(d) X; end subroutine func1;
MACRO(foo)
! Same subroutine, but after preprocessor expansion (-e -fno-reformat); syntax error
! subroutine func2(foo); real(2) :: foo; !dir$ ignore_tkr(d) foo; end subroutine func2;
! Parses with line wrap before !dir$
subroutine func3(foo); real(2) :: foo;
!dir$ ignore_tkr(d) foo; end subroutine func3;
! Parses with line wrap after !dir$, but swallows the directive
subroutine func4(foo); real(2) :: foo; !dir$ ignore_tkr(d) foo;
end subroutine func4;
end module
which results in the following parse tree (-fdebug-unparse
without func2):
MODULE m
CONTAINS
SUBROUTINE func1 (foo)
REAL(KIND=2_4) foo
!DIR$ IGNORE_TKR (d) foo
END SUBROUTINE func1
SUBROUTINE func3 (foo)
REAL(KIND=2_4) foo
!DIR$ IGNORE_TKR (d) foo
END SUBROUTINE func3
SUBROUTINE func4 (foo)
REAL(KIND=2_4) foo
END SUBROUTINE func4
END MODULE