[flang] Relax the implementation of constraint C1302. (flang-compiler/f18#805)

* Relax the implementation of constraint C1302.

When a list of format items can be unambiguously partitioned into individual items even though one or more otherwise required comma separators are omitted, generate a warning rather than an error.

Fixes flang-compiler/f18#703

Original-commit: flang-compiler/f18@79c0731137
Reviewed-on: https://github.com/flang-compiler/f18/pull/805
This commit is contained in:
vdonaldson 2019-11-05 10:11:36 -08:00 committed by GitHub
parent 9392f2a329
commit 65791b2d0b
4 changed files with 51 additions and 72 deletions

View File

@ -16,6 +16,7 @@
#define FORTRAN_COMMON_FORMAT_H_
#include "Fortran.h"
#include "enum-set.h"
#include <cstring>
// Define a FormatValidator class template to validate a format expression
@ -41,6 +42,16 @@ struct FormatMessage {
bool isError; // vs. warning
};
// This declaration is logically private to class FormatValidator.
// It is placed here to work around a clang compilation problem.
ENUM_CLASS(TokenKind, None, A, B, BN, BZ, D, DC, DP, DT, E, EN, ES, EX, F, G, I,
L, O, P, RC, RD, RN, RP, RU, RZ, S, SP, SS, T, TL, TR, X, Z, Colon, Slash,
Backslash, // nonstandard: inhibit newline on output
Dollar, // nonstandard: inhibit newline on output on terminals
Star, LParen, RParen, Comma, Point, Sign,
UnsignedInteger, // value in integerValue_
String) // char-literal-constant or Hollerith constant
template<typename CHAR = char> class FormatValidator {
public:
using Reporter = std::function<bool(const FormatMessage &)>;
@ -54,53 +65,11 @@ public:
bool Check();
private:
enum class TokenKind {
None,
A,
B,
BN,
BZ,
D,
DC,
DP,
DT,
E,
EN,
ES,
EX,
F,
G,
I,
L,
O,
P,
RC,
RD,
RN,
RP,
RU,
RZ,
S,
SP,
SS,
T,
TL,
TR,
X,
Z,
Colon,
Slash,
Backslash, // nonstandard: inhibit newline on output
Dollar, // nonstandard: inhibit newline on output on terminals
Star,
LParen,
RParen,
Comma,
Point,
Sign,
UnsignedInteger, // value in integerValue_
String, // char-literal-constant or Hollerith constant
};
common::EnumSet<TokenKind, TokenKind_enumSize> itemsWithLeadingInts_{
TokenKind::A, TokenKind::B, TokenKind::D, TokenKind::DT, TokenKind::E,
TokenKind::EN, TokenKind::ES, TokenKind::EX, TokenKind::F, TokenKind::G,
TokenKind::I, TokenKind::L, TokenKind::O, TokenKind::P, TokenKind::X,
TokenKind::Z, TokenKind::Slash, TokenKind::LParen};
struct Token {
Token &set_kind(TokenKind kind) {
@ -176,6 +145,7 @@ private:
Token knrToken_{}; // k, n, or r UnsignedInteger token
int64_t knrValue_{-1}; // -1 ==> not present
int64_t wValue_{-1};
bool previousTokenWasInt_{false};
char argString_[3]{}; // 1-2 character msg arg; usually edit descriptor name
bool formatHasErrors_{false};
bool unterminatedFormatError_{false};
@ -213,6 +183,7 @@ template<typename CHAR> void FormatValidator<CHAR>::NextToken() {
// At entry, cursor_ points before the start of the next token.
// At exit, cursor_ points to last CHAR of token_.
previousTokenWasInt_ = token_.kind() == TokenKind::UnsignedInteger;
CHAR c{NextChar()};
token_.set_kind(TokenKind::None);
token_.set_offset(cursor_ - format_);
@ -472,7 +443,7 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
Token starToken{}; // unlimited format token
bool hasDataEditDesc{false};
// Subject to error recovery exceptions, a loop iteration processes an
// Subject to error recovery exceptions, a loop iteration processes one
// edit descriptor or does list management. The loop terminates when
// - a level-0 right paren is processed (format may be valid)
// - the end of an incomplete format is reached
@ -773,7 +744,12 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
default:
// Possible first token of the next format item; token not yet processed.
if (commaRequired) {
ReportError("Expected ',' or ')' in format expression"); // C1302
const char *s{"Expected ',' or ')' in format expression"}; // C1302
if (previousTokenWasInt_ && itemsWithLeadingInts_.test(token_.kind())) {
ReportError(s);
} else {
ReportWarning(s);
}
}
}
}

View File

@ -30,6 +30,12 @@
2011 format(:2L2)
2012 format(2L2 : 2L2)
! C1302 warnings; no errors
2051 format(1X3/)
2052 format(1X003/)
2053 format(3P7I2)
2054 format(3PI2)
!ERROR: Expected ',' or ')' in format expression
2101 format(3I83Z8, 'abc')
@ -42,18 +48,6 @@
!ERROR: Expected ',' or ')' in format expression
2104 format(3I8 Z8)
!ERROR: Expected ',' or ')' in format expression
2105 format(1X3/)
!ERROR: Expected ',' or ')' in format expression
2106 format(1X003/)
!ERROR: Expected ',' or ')' in format expression
2107 format(3P7I2)
!ERROR: Expected ',' or ')' in format expression
2108 format(3PI2)
3001 format(*(I3))
3002 format(5X,*(2(A)))

View File

@ -51,6 +51,11 @@
write(*,'(\)')
write(*,'(RZ,RU,RP,RN,RD,RC,SS,SP,S,3G15.3e2)')
! C1302 warnings; no errors
write(*,'(3P7I2)')
write(*,'(5X i3)')
write(*,'(XEN)')
!ERROR: Empty format expression
write(*,"")
@ -72,12 +77,6 @@
!ERROR: 'P' edit descriptor must have a scale factor
write(*,'(P7F' // '5.2)')
!ERROR: Expected ',' or ')' in format expression
write(*,'(3P7I2)')
!ERROR: Expected ',' or ')' in format expression
write(*,'(5X i3)')
!ERROR: Unexpected integer constant
write(*,'(X,3,3L4)')
@ -186,9 +185,6 @@
!ERROR: Unexpected 'M' in format expression
write(*,'(MXY)')
!ERROR: Expected ',' or ')' in format expression
write(*,'(XEN)')
!ERROR: Unexpected 'R' in format expression
!ERROR: Unexpected 'R' in format expression
write(*,"(RR, RV)")
@ -265,9 +261,8 @@
!ERROR: Unterminated format expression
write(*,'(X')
!ERROR: Expected ',' or ')' in format expression
!ERROR: Unterminated format expression
write(*,'(XX')
write(*,'(XX') ! C1302 warning is not an error
!ERROR: Unexpected '@' in format expression
!ERROR: Unexpected '#' in format expression

View File

@ -35,4 +35,18 @@
!WARNING: Legacy 'H' edit descriptor
write(*, '(3Habc)')
!WARNING: 'X' edit descriptor must have a positive position value
!WARNING: Expected ',' or ')' in format expression
!WARNING: 'X' edit descriptor must have a positive position value
write(*,'(XX)')
!WARNING: Expected ',' or ')' in format expression
write(*,'(RZEN8.2)')
!WARNING: Expected ',' or ')' in format expression
write(*,'(3P7I2)')
!WARNING: Expected ',' or ')' in format expression
write(*,'(5X i3)')
end