[flang-commits] [flang] 889c7c8 - [flang] Support correct continuations for compiler directives

Daniil Dudkin via flang-commits flang-commits at lists.llvm.org
Fri May 27 03:46:55 PDT 2022


Author: Daniil Dudkin
Date: 2022-05-27T13:45:37+03:00
New Revision: 889c7c8e9260932dce5367df3f7ed7ecc32dbe8e

URL: https://github.com/llvm/llvm-project/commit/889c7c8e9260932dce5367df3f7ed7ecc32dbe8e
DIFF: https://github.com/llvm/llvm-project/commit/889c7c8e9260932dce5367df3f7ed7ecc32dbe8e.diff

LOG: [flang] Support correct continuations for compiler directives

If a line is over 72 characters long, flang's preprocessor cuts it there
and continues on the next line.
For this purpose it uses the standard way of continuing line with & on each line.
However, it doesn't work with long compiler directives, like OpenMP or OpenACC ones.
The line that continues the directive also has to
contain the corresponding sentinel at the beginning.

This change implements the described functionality.
Also, some code was refactored in order to simplify and reuse existing code.

Reviewed By: klausler

Differential Revision: https://reviews.llvm.org/D126301

Added: 
    flang/test/Preprocessing/pp132.f90
    flang/test/Preprocessing/pp133.f90

Modified: 
    flang/lib/Parser/parsing.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Parser/parsing.cpp b/flang/lib/Parser/parsing.cpp
index e29d5aff2496b..6b0119008dbf4 100644
--- a/flang/lib/Parser/parsing.cpp
+++ b/flang/lib/Parser/parsing.cpp
@@ -103,7 +103,13 @@ void Parsing::EmitPreprocessedSource(
   int column{1};
   bool inDirective{false};
   bool inContinuation{false};
+  bool lineWasBlankBefore{true};
   const AllSources &allSources{allCooked().allSources()};
+  // All directives that flang support are known to have a length of 3 chars
+  constexpr int directiveNameLength{3};
+  // We need to know the current directive in order to provide correct
+  // continuation for the directive
+  std::string directive;
   for (const char &atChar : cooked().AsCharBlock()) {
     char ch{atChar};
     if (ch == '\n') {
@@ -111,15 +117,36 @@ void Parsing::EmitPreprocessedSource(
       column = 1;
       inDirective = false;
       inContinuation = false;
+      lineWasBlankBefore = true;
       ++sourceLine;
+      directive.clear();
     } else {
-      if (ch == '!') {
+      auto provenance{cooked().GetProvenanceRange(CharBlock{&atChar, 1})};
+
+      // Preserves original case of the character
+      const auto getOriginalChar{[&](char ch) {
+        if (IsLetter(ch) && provenance && provenance->size() == 1) {
+          if (const char *orig{allSources.GetSource(*provenance)}) {
+            const char upper{ToUpperCaseLetter(ch)};
+            if (*orig == upper) {
+              return upper;
+            }
+          }
+        }
+        return ch;
+      }};
+
+      if (ch == '!' && lineWasBlankBefore) {
         // Other comment markers (C, *, D) in original fixed form source
         // input card column 1 will have been deleted or normalized to !,
         // which signifies a comment (directive) in both source forms.
         inDirective = true;
       }
-      auto provenance{cooked().GetProvenanceRange(CharBlock{&atChar, 1})};
+      if (inDirective && directive.size() < directiveNameLength &&
+          IsLetter(ch)) {
+        directive += getOriginalChar(ch);
+      }
+
       std::optional<SourcePosition> position{provenance
               ? allSources.GetSourcePosition(provenance->start())
               : std::nullopt};
@@ -145,14 +172,18 @@ void Parsing::EmitPreprocessedSource(
       }
       if (column > 72) {
         // Wrap long lines in a portable fashion that works in both
-        // of the Fortran source forms.  The first free-form continuation
+        // of the Fortran source forms. The first free-form continuation
         // marker ("&") lands in column 73, which begins the card commentary
         // field of fixed form, and the second one is put in column 6,
         // where it signifies fixed form line continuation.
         // The standard Fortran fixed form column limit (72) is used
         // for output, even if the input was parsed with a nonstandard
         // column limit override option.
-        out << "&\n     &";
+        // OpenMP and OpenACC directives' continuations should have the
+        // corresponding sentinel at the next line.
+        const auto continuation{
+            inDirective ? "&\n!$" + directive + "&" : "&\n     &"s};
+        out << continuation;
         column = 7; // start of fixed form source field
         ++sourceLine;
         inContinuation = true;
@@ -169,16 +200,8 @@ void Parsing::EmitPreprocessedSource(
           out << ' ';
         }
       }
-      if (ch >= 'a' && ch <= 'z' && provenance && provenance->size() == 1) {
-        // Preserve original case
-        if (const char *orig{allSources.GetSource(*provenance)}) {
-          auto upper{static_cast<char>(ch + 'A' - 'a')};
-          if (*orig == upper) {
-            ch = upper;
-          }
-        }
-      }
-      out << ch;
+      out << getOriginalChar(ch);
+      lineWasBlankBefore = ch == ' ' && lineWasBlankBefore;
       ++column;
     }
   }

diff  --git a/flang/test/Preprocessing/pp132.f90 b/flang/test/Preprocessing/pp132.f90
new file mode 100644
index 0000000000000..418defb2d553c
--- /dev/null
+++ b/flang/test/Preprocessing/pp132.f90
@@ -0,0 +1,18 @@
+! RUN: %flang -E -fopenmp -fopenacc %s 2>&1 | FileCheck %s
+! CHECK:  !$OMP parallel default(shared) private(super_very_long_name_for_the_va&
+! CHECK:  !$OMP&riable)
+! CHECK:  !$acc data copyin(super_very_long_name_for_the_variable, another_super&
+! CHECK:  !$acc&_wordy_variable_to_test)
+! Test correct continuations in compiler directives
+subroutine foo
+  integer :: super_very_long_name_for_the_variable
+  integer :: another_super_wordy_variable_to_test
+
+  super_very_long_name_for_the_variable = 42
+  another_super_wordy_variable_to_test = super_very_long_name_for_the_variable * 2
+  !$OMP parallel default(shared) private(super_very_long_name_for_the_variable)
+  !$omp end parallel
+
+  !$acc data copyin(super_very_long_name_for_the_variable, another_super_wordy_variable_to_test)
+  !$acc end data
+end subroutine foo

diff  --git a/flang/test/Preprocessing/pp133.f90 b/flang/test/Preprocessing/pp133.f90
new file mode 100644
index 0000000000000..639bc0ad5b76b
--- /dev/null
+++ b/flang/test/Preprocessing/pp133.f90
@@ -0,0 +1,14 @@
+! RUN: %flang -E %s 2>&1 | FileCheck %s
+! CHECK: character(*), parameter :: simple_literal = "!!!!!!!!!!!!!!!!!!!!!&
+! CHECK: &!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&
+! CHECK: &!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&
+! CHECK: &!!!!!!!!!!!!!"
+! CHECK: character(*), parameter :: hollerith_literal = 166H!!!!!!!!!!!!!!!&
+! CHECK: &!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&
+! CHECK: &!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&
+! CHECK: &!!!!!!!!!!!!!!!!!!!
+! Test correct continuations in string literals
+subroutine foo
+  character(*), parameter :: simple_literal = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+  character(*), parameter :: hollerith_literal = 166H!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+end subroutine foo


        


More information about the flang-commits mailing list