Skip to content
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

Preprocessor directives in omp_lib.h causes some OpenMP programs to fail compilation #1451

Open
bryanpkc opened this issue Sep 4, 2024 · 2 comments · May be fixed by flang-compiler/classic-flang-llvm-project#201

Comments

@bryanpkc
Copy link
Collaborator

bryanpkc commented Sep 4, 2024

The problem raised in this comment may need a downstream workaround. This issue documents the current behaviour of Classic Flang and discusses what the best solution should be.

Problem Scope

Compiling with -fopenmp does not automatically cause Classic Flang to include omp_lib.h automatically, i.e. this header file must be included explicitly to cause a problem.

While Classic Flang turns on the preprocessor automatically for files named with certain extensions (e.g. .F90, .F95), it does not check the file name extension of included files, i.e. naming an included file with .h or .H makes no difference.

There are two ways to include files in Fortran. Classic Flang supports both.

INCLUDE Line

Fortran 2018 (section 6.4) specifies the INCLUDE line, which accepts a file name and effectively replaces the line with the text in the named file. The INCLUDE line is not a preprocessor directive, and does not support preprocessor directives in the included text.

For example:

program main

include "preproc.h"

print *, A

end program main

In the above example, if preproc.h contains #ifdef and #endif directives (on lines 1 and 4, respectively), flang1 will fail, both with preprocessor enabled and without, with the following error:

$ flang preproc.f90
F90-S-0021-Label field of continuation line is not blank (./preproc.h: 1)
F90-S-0021-Label field of continuation line is not blank (./preproc.h: 4)
  0 inform,   0 warnings,   2 severes, 0 fatal for main

GFortran 11.4.0 also fails on the same program, both with preprocessor enabled and without:

$ gfortran preproc.F90
preproc.h:1:2:

    1 | #ifdef FOOBAR
      |  1
Warning: Illegal preprocessor directive
preproc.h:4:2:

    4 | #endif
      |  1
Warning: Illegal preprocessor directive

It is notable that both compilers will not respect preprocessor directives in files included with the INCLUDE line, even if the including file is being compiled with preprocessing enabled.

#include Preprocessor Directive

Both GFortran and Classic Flang offer some level of support for C preprocessor directives. For example:

program main

#include "preproc.h"

print *, A

end program main

As in the previous example, preproc.h contains #ifdef FOOBAR and #endif on lines 1 and 4, respectively.

Just like Classic Flang, GFortran 11.4.0 turns on preprocessing by default if the input file name has certain extensions (e.g. .F90, .F95). If the above example is saved as preproc.F90, GFortran compiles it successfully without any warning, and the content of preproc.h is included correctly (if -DFOOBAR is specified). If the above example is saved as preproc.f90, GFortran turns off preprocessing, and compilation fails:

$ gfortran preproc2.f90
preproc2.f90:3:2:

    3 | #include "preproc.h"
      |  1
Warning: Illegal preprocessor directive

Classic Flang's behaviour is identical. If the above example is saved as preproc.F90, Classic Flang compiles it successfully without any warning. If the above example is saved as preproc.f90, Classic Flang turns off preprocessing, and compilation fails:

$ flang preproc2.f90
F90-S-0021-Label field of continuation line is not blank (preproc2.f90: 3)
  0 inform,   0 warnings,   1 severes, 0 fatal for main

Conclusion

Classic Flang's behaviour regarding preprocessor directives is identical to GFortran's. In general, the user is responsible of turning on or off the preprocessor for each translation unit. If omp_lib.h is included explicitly using the #include directive, then the newly introduced #ifdef directives in the file will not cause a problem. A problem arises, for both Classic Flang and GFortran, only if the user's program uses the INCLUDE line for omp_lib.h.

IMHO, to maintain consistency with GFortran and avoid unnecessary work, and to avoid violating the principle of least astonishment, for now we should revert the upstream change to omp_lib.h in Classic Flang.

LLVM Flang

For brevity, LLVM Flang's behaviour is summarized in the table below. In all cases, the compilation succeeds without any warning. The INCLUDE line is apparently handled in the same way as the #include directive.

Filename Extension Inclusion Mechanism flang-new Compilation Result
.f90 INCLUDE line #ifdef and #endif in the header are ignored silently.
.f90 #include directive #ifdef and #endif in the header are ignored silently.
.F90 INCLUDE line #ifdef and #endif in the header are supported.
.F90 #include directive #ifdef and #endif in the header are supported.
@bryanpkc
Copy link
Collaborator Author

@pawosm-arm Any comment or suggestion? Do you agree with my conclusion?

@pawosm-arm
Copy link
Collaborator

to maintain consistency with GFortran and avoid unnecessary work, and to avoid violating the principle of least astonishment, for now we should revert the upstream change to omp_lib.h in Classic Flang.
@bryanpkc yes, this is what we are doing here. This is a classic-flang fork of LLVM and we do not need to make every other Fortran compiler happy, the primary goal is to make happy the classic-flang itself.

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

Successfully merging a pull request may close this issue.

2 participants