[flang-commits] [flang] ac77649 - [flang] Avoid spurious warnings in pedantic mode from FORMAT items

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Wed Jul 6 18:54:24 PDT 2022


Author: Peter Klausler
Date: 2022-07-06T18:54:11-07:00
New Revision: ac77649951db17f1126bde08d580ec101f0759bc

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

LOG: [flang] Avoid spurious warnings in pedantic mode from FORMAT items

In free form source, pedantic mode will elicit portability warnings
about missing spaces when a token string ends with a character that
can be in an identifier and there is no space between that last token
character and a following character that can also be part of an identifier.

This behavior doesn't really work well for the token strings that are
parsed for edit descriptors in FORMAT statements.  For example, the
'F' in FORMAT(F7.3) is followed by a digit, but obviously no space is
necessary.  Free form or not, FORMATs are their own odd little world.

This patch adds trailing blanks to these FORMAT edit descriptor token
parsers to disable the missing space check, and extends the documentation
for token string parsing to explain why this technique works.

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

Added: 
    

Modified: 
    flang/docs/ParserCombinators.md
    flang/lib/Parser/io-parsers.cpp

Removed: 
    


################################################################################
diff  --git a/flang/docs/ParserCombinators.md b/flang/docs/ParserCombinators.md
index ff94d341c1501..bb17509d16015 100644
--- a/flang/docs/ParserCombinators.md
+++ b/flang/docs/ParserCombinators.md
@@ -155,7 +155,10 @@ is built.  All of the following parsers consume characters acquired from
 * `"..."_tok` match the content of the string, skipping spaces before and
   after.  Internal spaces are optional matches.  The `_tok` suffix is
   optional when the parser appears before the combinator `>>` or after
-  the combinator `/`.
+  the combinator `/`.  If the quoted string ends in a character that
+  could appear in an identifier, a missing space will be diagnosed in
+  free form source in pedantic mode if the next character could also
+  be part of an identifier -- add a trailing blank to avoid this.
 * `"..."_sptok` is a string match in which the spaces are required in
    free form source.
 * `"..."_id` is a string match for a complete identifier (not a prefix of

diff  --git a/flang/lib/Parser/io-parsers.cpp b/flang/lib/Parser/io-parsers.cpp
index 2296d84d58f0f..c7ef96e677465 100644
--- a/flang/lib/Parser/io-parsers.cpp
+++ b/flang/lib/Parser/io-parsers.cpp
@@ -569,6 +569,11 @@ constexpr auto digits{repeat};
 constexpr auto noInt{construct<std::optional<int>>()};
 constexpr auto mandatoryDigits{construct<std::optional<int>>("." >> width)};
 
+// The extra trailing spaces in the following quoted edit descriptor token
+// parsers are intentional: they inhibit any spurious warnings about missing
+// spaces in pedantic mode that would otherwise be emitted if the edit
+// descriptor were followed by a character that could appear in an identifier.
+
 // R1307 data-edit-desc ->
 //         I w [. m] | B w [. m] | O w [. m] | Z w [. m] | F w . d |
 //         E w . d [E e] | EN w . d [E e] | ES w . d [E e] | EX w . d [E e] |
@@ -576,59 +581,60 @@ constexpr auto mandatoryDigits{construct<std::optional<int>>("." >> width)};
 //         DT [char-literal-constant] [( v-list )]
 // (part 1 of 2)
 TYPE_PARSER(construct<format::IntrinsicTypeDataEditDesc>(
-                "I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
-                    "B" >> pure(format::IntrinsicTypeDataEditDesc::Kind::B) ||
-                    "O" >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
-                    "Z" >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z),
+                "I " >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
+                    "B " >> pure(format::IntrinsicTypeDataEditDesc::Kind::B) ||
+                    "O " >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
+                    "Z " >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z),
                 mandatoryWidth, maybe("." >> digits), noInt) ||
     construct<format::IntrinsicTypeDataEditDesc>(
-        "F" >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
-            "D" >> pure(format::IntrinsicTypeDataEditDesc::Kind::D),
+        "F " >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
+            "D " >> pure(format::IntrinsicTypeDataEditDesc::Kind::D),
         mandatoryWidth, mandatoryDigits, noInt) ||
     construct<format::IntrinsicTypeDataEditDesc>(
-        "E" >> ("N" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
-                   "S" >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) ||
-                   "X" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) ||
-                   pure(format::IntrinsicTypeDataEditDesc::Kind::E)),
-        mandatoryWidth, mandatoryDigits, maybe("E" >> digits)) ||
+        "E " >> ("N " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
+                    "S " >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) ||
+                    "X " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) ||
+                    pure(format::IntrinsicTypeDataEditDesc::Kind::E)),
+        mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) ||
     construct<format::IntrinsicTypeDataEditDesc>(
-        "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G), mandatoryWidth,
-        mandatoryDigits, maybe("E" >> digits)) ||
+        "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G),
+        mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) ||
     construct<format::IntrinsicTypeDataEditDesc>(
-        "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
-            "L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
+        "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
+            "L " >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
         mandatoryWidth, noInt, noInt) ||
     construct<format::IntrinsicTypeDataEditDesc>(
-        "A" >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width),
+        "A " >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width),
         noInt, noInt) ||
     // PGI/Intel extension: omitting width (and all else that follows)
     extension<LanguageFeature::AbbreviatedEditDescriptor>(
         "nonstandard usage: abbreviated edit descriptor"_port_en_US,
         construct<format::IntrinsicTypeDataEditDesc>(
-            "I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
-                ("B"_tok / !letter /* don't occlude BN & BZ */) >>
+            "I " >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
+                ("B "_tok / !letter /* don't occlude BN & BZ */) >>
                     pure(format::IntrinsicTypeDataEditDesc::Kind::B) ||
-                "O" >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
-                "Z" >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z) ||
-                "F" >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
-                ("D"_tok / !letter /* don't occlude DT, DC, & DP */) >>
+                "O " >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
+                "Z " >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z) ||
+                "F " >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
+                ("D "_tok / !letter /* don't occlude DT, DC, & DP */) >>
                     pure(format::IntrinsicTypeDataEditDesc::Kind::D) ||
-                "E" >>
-                    ("N" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
-                        "S" >>
+                "E " >>
+                    ("N " >>
+                            pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
+                        "S " >>
                             pure(format::IntrinsicTypeDataEditDesc::Kind::ES) ||
-                        "X" >>
+                        "X " >>
                             pure(format::IntrinsicTypeDataEditDesc::Kind::EX) ||
                         pure(format::IntrinsicTypeDataEditDesc::Kind::E)) ||
-                "G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
-                "L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
+                "G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
+                "L " >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
             noInt, noInt, noInt)))
 
 // R1307 data-edit-desc (part 2 of 2)
 // R1312 v -> [sign] digit-string
 constexpr SignedDigitStringIgnoreSpaces scaleFactor;
 TYPE_PARSER(construct<format::DerivedTypeDataEditDesc>(
-    "D" >> "T"_tok >> defaulted(charLiteralConstantWithoutKind),
+    "D T" >> defaulted(charLiteralConstantWithoutKind),
     defaulted(parenthesized(nonemptyList(scaleFactor)))))
 
 // R1314 k -> [sign] digit-string
@@ -645,46 +651,46 @@ constexpr PositiveDigitStringIgnoreSpaces count;
 // R1319 round-edit-desc -> RU | RD | RZ | RN | RC | RP
 // R1320 decimal-edit-desc -> DC | DP
 TYPE_PARSER(construct<format::ControlEditDesc>(
-                "T" >> ("L" >> pure(format::ControlEditDesc::Kind::TL) ||
-                           "R" >> pure(format::ControlEditDesc::Kind::TR) ||
-                           pure(format::ControlEditDesc::Kind::T)),
+                "T L " >> pure(format::ControlEditDesc::Kind::TL) ||
+                    "T R " >> pure(format::ControlEditDesc::Kind::TR) ||
+                    "T " >> pure(format::ControlEditDesc::Kind::T),
                 count) ||
     construct<format::ControlEditDesc>(count,
-        "X" >> pure(format::ControlEditDesc::Kind::X) ||
+        "X " >> pure(format::ControlEditDesc::Kind::X) ||
             "/" >> pure(format::ControlEditDesc::Kind::Slash)) ||
     construct<format::ControlEditDesc>(
-        "X" >> pure(format::ControlEditDesc::Kind::X) ||
+        "X " >> pure(format::ControlEditDesc::Kind::X) ||
         "/" >> pure(format::ControlEditDesc::Kind::Slash)) ||
     construct<format::ControlEditDesc>(
-        scaleFactor, "P" >> pure(format::ControlEditDesc::Kind::P)) ||
+        scaleFactor, "P " >> pure(format::ControlEditDesc::Kind::P)) ||
     construct<format::ControlEditDesc>(
         ":" >> pure(format::ControlEditDesc::Kind::Colon)) ||
-    "S" >> ("S" >> construct<format::ControlEditDesc>(
-                       pure(format::ControlEditDesc::Kind::SS)) ||
-               "P" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::SP)) ||
-               construct<format::ControlEditDesc>(
-                   pure(format::ControlEditDesc::Kind::S))) ||
-    "B" >> ("N" >> construct<format::ControlEditDesc>(
-                       pure(format::ControlEditDesc::Kind::BN)) ||
-               "Z" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::BZ))) ||
-    "R" >> ("U" >> construct<format::ControlEditDesc>(
-                       pure(format::ControlEditDesc::Kind::RU)) ||
-               "D" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::RD)) ||
-               "Z" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::RZ)) ||
-               "N" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::RN)) ||
-               "C" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::RC)) ||
-               "P" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::RP))) ||
-    "D" >> ("C" >> construct<format::ControlEditDesc>(
-                       pure(format::ControlEditDesc::Kind::DC)) ||
-               "P" >> construct<format::ControlEditDesc>(
-                          pure(format::ControlEditDesc::Kind::DP))) ||
+    "S " >> ("S " >> construct<format::ControlEditDesc>(
+                         pure(format::ControlEditDesc::Kind::SS)) ||
+                "P " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::SP)) ||
+                construct<format::ControlEditDesc>(
+                    pure(format::ControlEditDesc::Kind::S))) ||
+    "B " >> ("N " >> construct<format::ControlEditDesc>(
+                         pure(format::ControlEditDesc::Kind::BN)) ||
+                "Z " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::BZ))) ||
+    "R " >> ("U " >> construct<format::ControlEditDesc>(
+                         pure(format::ControlEditDesc::Kind::RU)) ||
+                "D " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::RD)) ||
+                "Z " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::RZ)) ||
+                "N " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::RN)) ||
+                "C " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::RC)) ||
+                "P " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::RP))) ||
+    "D " >> ("C " >> construct<format::ControlEditDesc>(
+                         pure(format::ControlEditDesc::Kind::DC)) ||
+                "P " >> construct<format::ControlEditDesc>(
+                            pure(format::ControlEditDesc::Kind::DP))) ||
     extension<LanguageFeature::AdditionalFormats>(
         "nonstandard usage: $ and \\ control edit descriptors"_port_en_US,
         "$" >> construct<format::ControlEditDesc>(


        


More information about the flang-commits mailing list