Skip to content

Commit ac77649

Browse files
committed
[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
1 parent 121798f commit ac77649

File tree

2 files changed

+71
-62
lines changed

2 files changed

+71
-62
lines changed

flang/docs/ParserCombinators.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ is built. All of the following parsers consume characters acquired from
155155
* `"..."_tok` match the content of the string, skipping spaces before and
156156
after. Internal spaces are optional matches. The `_tok` suffix is
157157
optional when the parser appears before the combinator `>>` or after
158-
the combinator `/`.
158+
the combinator `/`. If the quoted string ends in a character that
159+
could appear in an identifier, a missing space will be diagnosed in
160+
free form source in pedantic mode if the next character could also
161+
be part of an identifier -- add a trailing blank to avoid this.
159162
* `"..."_sptok` is a string match in which the spaces are required in
160163
free form source.
161164
* `"..."_id` is a string match for a complete identifier (not a prefix of

flang/lib/Parser/io-parsers.cpp

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -569,66 +569,72 @@ constexpr auto digits{repeat};
569569
constexpr auto noInt{construct<std::optional<int>>()};
570570
constexpr auto mandatoryDigits{construct<std::optional<int>>("." >> width)};
571571

572+
// The extra trailing spaces in the following quoted edit descriptor token
573+
// parsers are intentional: they inhibit any spurious warnings about missing
574+
// spaces in pedantic mode that would otherwise be emitted if the edit
575+
// descriptor were followed by a character that could appear in an identifier.
576+
572577
// R1307 data-edit-desc ->
573578
// I w [. m] | B w [. m] | O w [. m] | Z w [. m] | F w . d |
574579
// E w . d [E e] | EN w . d [E e] | ES w . d [E e] | EX w . d [E e] |
575580
// G w [. d [E e]] | L w | A [w] | D w . d |
576581
// DT [char-literal-constant] [( v-list )]
577582
// (part 1 of 2)
578583
TYPE_PARSER(construct<format::IntrinsicTypeDataEditDesc>(
579-
"I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
580-
"B" >> pure(format::IntrinsicTypeDataEditDesc::Kind::B) ||
581-
"O" >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
582-
"Z" >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z),
584+
"I " >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
585+
"B " >> pure(format::IntrinsicTypeDataEditDesc::Kind::B) ||
586+
"O " >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
587+
"Z " >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z),
583588
mandatoryWidth, maybe("." >> digits), noInt) ||
584589
construct<format::IntrinsicTypeDataEditDesc>(
585-
"F" >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
586-
"D" >> pure(format::IntrinsicTypeDataEditDesc::Kind::D),
590+
"F " >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
591+
"D " >> pure(format::IntrinsicTypeDataEditDesc::Kind::D),
587592
mandatoryWidth, mandatoryDigits, noInt) ||
588593
construct<format::IntrinsicTypeDataEditDesc>(
589-
"E" >> ("N" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
590-
"S" >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) ||
591-
"X" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) ||
592-
pure(format::IntrinsicTypeDataEditDesc::Kind::E)),
593-
mandatoryWidth, mandatoryDigits, maybe("E" >> digits)) ||
594+
"E " >> ("N " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
595+
"S " >> pure(format::IntrinsicTypeDataEditDesc::Kind::ES) ||
596+
"X " >> pure(format::IntrinsicTypeDataEditDesc::Kind::EX) ||
597+
pure(format::IntrinsicTypeDataEditDesc::Kind::E)),
598+
mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) ||
594599
construct<format::IntrinsicTypeDataEditDesc>(
595-
"G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G), mandatoryWidth,
596-
mandatoryDigits, maybe("E" >> digits)) ||
600+
"G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G),
601+
mandatoryWidth, mandatoryDigits, maybe("E " >> digits)) ||
597602
construct<format::IntrinsicTypeDataEditDesc>(
598-
"G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
599-
"L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
603+
"G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
604+
"L " >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
600605
mandatoryWidth, noInt, noInt) ||
601606
construct<format::IntrinsicTypeDataEditDesc>(
602-
"A" >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width),
607+
"A " >> pure(format::IntrinsicTypeDataEditDesc::Kind::A), maybe(width),
603608
noInt, noInt) ||
604609
// PGI/Intel extension: omitting width (and all else that follows)
605610
extension<LanguageFeature::AbbreviatedEditDescriptor>(
606611
"nonstandard usage: abbreviated edit descriptor"_port_en_US,
607612
construct<format::IntrinsicTypeDataEditDesc>(
608-
"I" >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
609-
("B"_tok / !letter /* don't occlude BN & BZ */) >>
613+
"I " >> pure(format::IntrinsicTypeDataEditDesc::Kind::I) ||
614+
("B "_tok / !letter /* don't occlude BN & BZ */) >>
610615
pure(format::IntrinsicTypeDataEditDesc::Kind::B) ||
611-
"O" >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
612-
"Z" >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z) ||
613-
"F" >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
614-
("D"_tok / !letter /* don't occlude DT, DC, & DP */) >>
616+
"O " >> pure(format::IntrinsicTypeDataEditDesc::Kind::O) ||
617+
"Z " >> pure(format::IntrinsicTypeDataEditDesc::Kind::Z) ||
618+
"F " >> pure(format::IntrinsicTypeDataEditDesc::Kind::F) ||
619+
("D "_tok / !letter /* don't occlude DT, DC, & DP */) >>
615620
pure(format::IntrinsicTypeDataEditDesc::Kind::D) ||
616-
"E" >>
617-
("N" >> pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
618-
"S" >>
621+
"E " >>
622+
("N " >>
623+
pure(format::IntrinsicTypeDataEditDesc::Kind::EN) ||
624+
"S " >>
619625
pure(format::IntrinsicTypeDataEditDesc::Kind::ES) ||
620-
"X" >>
626+
"X " >>
621627
pure(format::IntrinsicTypeDataEditDesc::Kind::EX) ||
622628
pure(format::IntrinsicTypeDataEditDesc::Kind::E)) ||
623-
"G" >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
624-
"L" >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
629+
"G " >> pure(format::IntrinsicTypeDataEditDesc::Kind::G) ||
630+
"L " >> pure(format::IntrinsicTypeDataEditDesc::Kind::L),
625631
noInt, noInt, noInt)))
626632

627633
// R1307 data-edit-desc (part 2 of 2)
628634
// R1312 v -> [sign] digit-string
629635
constexpr SignedDigitStringIgnoreSpaces scaleFactor;
630636
TYPE_PARSER(construct<format::DerivedTypeDataEditDesc>(
631-
"D" >> "T"_tok >> defaulted(charLiteralConstantWithoutKind),
637+
"D T" >> defaulted(charLiteralConstantWithoutKind),
632638
defaulted(parenthesized(nonemptyList(scaleFactor)))))
633639

634640
// R1314 k -> [sign] digit-string
@@ -645,46 +651,46 @@ constexpr PositiveDigitStringIgnoreSpaces count;
645651
// R1319 round-edit-desc -> RU | RD | RZ | RN | RC | RP
646652
// R1320 decimal-edit-desc -> DC | DP
647653
TYPE_PARSER(construct<format::ControlEditDesc>(
648-
"T" >> ("L" >> pure(format::ControlEditDesc::Kind::TL) ||
649-
"R" >> pure(format::ControlEditDesc::Kind::TR) ||
650-
pure(format::ControlEditDesc::Kind::T)),
654+
"T L " >> pure(format::ControlEditDesc::Kind::TL) ||
655+
"T R " >> pure(format::ControlEditDesc::Kind::TR) ||
656+
"T " >> pure(format::ControlEditDesc::Kind::T),
651657
count) ||
652658
construct<format::ControlEditDesc>(count,
653-
"X" >> pure(format::ControlEditDesc::Kind::X) ||
659+
"X " >> pure(format::ControlEditDesc::Kind::X) ||
654660
"/" >> pure(format::ControlEditDesc::Kind::Slash)) ||
655661
construct<format::ControlEditDesc>(
656-
"X" >> pure(format::ControlEditDesc::Kind::X) ||
662+
"X " >> pure(format::ControlEditDesc::Kind::X) ||
657663
"/" >> pure(format::ControlEditDesc::Kind::Slash)) ||
658664
construct<format::ControlEditDesc>(
659-
scaleFactor, "P" >> pure(format::ControlEditDesc::Kind::P)) ||
665+
scaleFactor, "P " >> pure(format::ControlEditDesc::Kind::P)) ||
660666
construct<format::ControlEditDesc>(
661667
":" >> pure(format::ControlEditDesc::Kind::Colon)) ||
662-
"S" >> ("S" >> construct<format::ControlEditDesc>(
663-
pure(format::ControlEditDesc::Kind::SS)) ||
664-
"P" >> construct<format::ControlEditDesc>(
665-
pure(format::ControlEditDesc::Kind::SP)) ||
666-
construct<format::ControlEditDesc>(
667-
pure(format::ControlEditDesc::Kind::S))) ||
668-
"B" >> ("N" >> construct<format::ControlEditDesc>(
669-
pure(format::ControlEditDesc::Kind::BN)) ||
670-
"Z" >> construct<format::ControlEditDesc>(
671-
pure(format::ControlEditDesc::Kind::BZ))) ||
672-
"R" >> ("U" >> construct<format::ControlEditDesc>(
673-
pure(format::ControlEditDesc::Kind::RU)) ||
674-
"D" >> construct<format::ControlEditDesc>(
675-
pure(format::ControlEditDesc::Kind::RD)) ||
676-
"Z" >> construct<format::ControlEditDesc>(
677-
pure(format::ControlEditDesc::Kind::RZ)) ||
678-
"N" >> construct<format::ControlEditDesc>(
679-
pure(format::ControlEditDesc::Kind::RN)) ||
680-
"C" >> construct<format::ControlEditDesc>(
681-
pure(format::ControlEditDesc::Kind::RC)) ||
682-
"P" >> construct<format::ControlEditDesc>(
683-
pure(format::ControlEditDesc::Kind::RP))) ||
684-
"D" >> ("C" >> construct<format::ControlEditDesc>(
685-
pure(format::ControlEditDesc::Kind::DC)) ||
686-
"P" >> construct<format::ControlEditDesc>(
687-
pure(format::ControlEditDesc::Kind::DP))) ||
668+
"S " >> ("S " >> construct<format::ControlEditDesc>(
669+
pure(format::ControlEditDesc::Kind::SS)) ||
670+
"P " >> construct<format::ControlEditDesc>(
671+
pure(format::ControlEditDesc::Kind::SP)) ||
672+
construct<format::ControlEditDesc>(
673+
pure(format::ControlEditDesc::Kind::S))) ||
674+
"B " >> ("N " >> construct<format::ControlEditDesc>(
675+
pure(format::ControlEditDesc::Kind::BN)) ||
676+
"Z " >> construct<format::ControlEditDesc>(
677+
pure(format::ControlEditDesc::Kind::BZ))) ||
678+
"R " >> ("U " >> construct<format::ControlEditDesc>(
679+
pure(format::ControlEditDesc::Kind::RU)) ||
680+
"D " >> construct<format::ControlEditDesc>(
681+
pure(format::ControlEditDesc::Kind::RD)) ||
682+
"Z " >> construct<format::ControlEditDesc>(
683+
pure(format::ControlEditDesc::Kind::RZ)) ||
684+
"N " >> construct<format::ControlEditDesc>(
685+
pure(format::ControlEditDesc::Kind::RN)) ||
686+
"C " >> construct<format::ControlEditDesc>(
687+
pure(format::ControlEditDesc::Kind::RC)) ||
688+
"P " >> construct<format::ControlEditDesc>(
689+
pure(format::ControlEditDesc::Kind::RP))) ||
690+
"D " >> ("C " >> construct<format::ControlEditDesc>(
691+
pure(format::ControlEditDesc::Kind::DC)) ||
692+
"P " >> construct<format::ControlEditDesc>(
693+
pure(format::ControlEditDesc::Kind::DP))) ||
688694
extension<LanguageFeature::AdditionalFormats>(
689695
"nonstandard usage: $ and \\ control edit descriptors"_port_en_US,
690696
"$" >> construct<format::ControlEditDesc>(

0 commit comments

Comments
 (0)