forked from OSchip/llvm-project
[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:
parent
9392f2a329
commit
65791b2d0b
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue