[flang-commits] [flang] 7d61a84 - [flang] Semantics limits on kP scale factors
V Donaldson via flang-commits
flang-commits at lists.llvm.org
Wed Apr 20 14:43:42 PDT 2022
Author: V Donaldson
Date: 2022-04-20T14:43:21-07:00
New Revision: 7d61a8419b49baed933421af70007d83633e8f30
URL: https://github.com/llvm/llvm-project/commit/7d61a8419b49baed933421af70007d83633e8f30
DIFF: https://github.com/llvm/llvm-project/commit/7d61a8419b49baed933421af70007d83633e8f30.diff
LOG: [flang] Semantics limits on kP scale factors
When known at compile time, Ew.d and Dw.d output edit descriptors
should respect limitations from the standard on the value of a
kP scale factor with respect to the digit count (d), at least for
values of k other than zero.
Added:
Modified:
flang/include/flang/Common/format.h
flang/test/Semantics/io08.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Common/format.h b/flang/include/flang/Common/format.h
index ad60cc3d3d9a0..0137da53bd090 100644
--- a/flang/include/flang/Common/format.h
+++ b/flang/include/flang/Common/format.h
@@ -125,7 +125,8 @@ template <typename CHAR = char> class FormatValidator {
void check_r(bool allowed = true);
bool check_w();
void check_m();
- bool check_d();
+ bool check_d(bool checkScaleFactor = false);
+ void check_k();
void check_e();
const CHAR *const format_; // format text
@@ -135,11 +136,13 @@ template <typename CHAR = char> class FormatValidator {
const CHAR *cursor_{}; // current location in format_
const CHAR *laCursor_{}; // lookahead cursor
- Token token_{}; // current token
TokenKind previousTokenKind_{TokenKind::None};
- int64_t integerValue_{-1}; // value of UnsignedInteger token
+ Token token_{}; // current token
Token knrToken_{}; // k, n, or r UnsignedInteger token
+ Token scaleFactorToken_{}; // most recent scale factor token P
+ int64_t integerValue_{-1}; // value of UnsignedInteger token
int64_t knrValue_{-1}; // -1 ==> not present
+ int64_t scaleFactorValue_{}; // signed k in kP
int64_t wValue_{-1};
char argString_[3]{}; // 1-2 character msg arg; usually edit descriptor name
bool formatHasErrors_{false};
@@ -491,7 +494,8 @@ template <typename CHAR> void FormatValidator<CHAR>::check_m() {
}
// Return the predicate "d value is present" to control further processing.
-template <typename CHAR> bool FormatValidator<CHAR>::check_d() {
+template <typename CHAR>
+bool FormatValidator<CHAR>::check_d(bool checkScaleFactor) {
if (token_.kind() != TokenKind::Point) {
ReportError("Expected '%s' edit descriptor '.d' value");
return false;
@@ -501,10 +505,41 @@ template <typename CHAR> bool FormatValidator<CHAR>::check_d() {
ReportError("Expected '%s' edit descriptor 'd' value after '.'");
return false;
}
+ if (checkScaleFactor) {
+ check_k();
+ }
NextToken();
return true;
}
+// Check the value of scale factor k against a field width d.
+template <typename CHAR> void FormatValidator<CHAR>::check_k() {
+ // Limit the check to D and E edit descriptors in output statements that
+ // explicitly set the scale factor.
+ if (stmt_ != IoStmtKind::Print && stmt_ != IoStmtKind::Write) {
+ return;
+ }
+ if (!scaleFactorToken_.IsSet()) {
+ return;
+ }
+ // 13.7.2.3.3p5 - The values of d and k must satisfy:
+ // −d < k <= 0; or
+ // 0 < k < d+2
+ const int64_t d{integerValue_};
+ const int64_t k{scaleFactorValue_};
+ // Exception: d = k = 0 is nonstandard, but has a reasonable interpretation.
+ if (d == 0 && k == 0) {
+ return;
+ }
+ if (k <= 0 && !(-d < k)) {
+ ReportError("Negative scale factor k (from kP) and width d in a '%s' "
+ "edit descriptor must satisfy '-d < k'");
+ } else if (k > 0 && !(k < d + 2)) {
+ ReportError("Positive scale factor k (from kP) and width d in a '%s' "
+ "edit descriptor must satisfy 'k < d+2'");
+ }
+}
+
template <typename CHAR> void FormatValidator<CHAR>::check_e() {
if (token_.kind() != TokenKind::E) {
return;
@@ -584,28 +619,32 @@ template <typename CHAR> bool FormatValidator<CHAR>::Check() {
}
break;
case TokenKind::D:
- case TokenKind::F:
+ case TokenKind::F: {
// R1307 data-edit-desc -> D w . d | F w . d
+ bool isD{token_.kind() == TokenKind::D};
hasDataEditDesc = true;
check_r();
NextToken();
if (check_w()) {
- check_d();
+ check_d(/*checkScaleFactor=*/isD);
}
break;
+ }
case TokenKind::E:
case TokenKind::EN:
case TokenKind::ES:
- case TokenKind::EX:
+ case TokenKind::EX: {
// R1307 data-edit-desc ->
// E w . d [E e] | EN w . d [E e] | ES w . d [E e] | EX w . d [E e]
+ bool isE{token_.kind() == TokenKind::E};
hasDataEditDesc = true;
check_r();
NextToken();
- if (check_w() && check_d()) {
+ if (check_w() && check_d(/*checkScaleFactor=*/isE)) {
check_e();
}
break;
+ }
case TokenKind::G:
// R1307 data-edit-desc -> G w [. d [E e]]
hasDataEditDesc = true;
@@ -695,6 +734,13 @@ template <typename CHAR> bool FormatValidator<CHAR>::Check() {
// R1313 control-edit-desc -> k P
if (knrValue_ < 0) {
ReportError("'P' edit descriptor must have a scale factor");
+ } else {
+ scaleFactorToken_ = knrToken_;
+ if (signToken.IsSet() && format_[signToken.offset()] == '-') {
+ scaleFactorValue_ = -knrValue_;
+ } else {
+ scaleFactorValue_ = knrValue_;
+ }
}
// Diagnosing C1302 may require multiple token lookahead.
// Save current cursor position to enable backup.
diff --git a/flang/test/Semantics/io08.f90 b/flang/test/Semantics/io08.f90
index b4e8d9f4b6a01..f6038b471759f 100644
--- a/flang/test/Semantics/io08.f90
+++ b/flang/test/Semantics/io08.f90
@@ -1,4 +1,7 @@
! RUN: %python %S/test_errors.py %s %flang_fc1
+ character(20), parameter :: kp_ok = "(4P,E20.5,E15.5)"
+ character(20), parameter :: kp_xx = "(4P,E20.5,E15.2)"
+
write(*,*)
write(*,'()')
write(*,'(A)')
@@ -40,6 +43,9 @@
write(*, '(' // achar( 9) // ')') ! horizontal tab
write(*, '(' // achar(11) // ')') ! vertical tab
write(*, '(' // achar(32) // ')') ! space
+ write(*, kp_ok)
+ write(*, '(-4P,E20.5,E15.5)')
+ write(*, '(D20.0)')
! C1302 warnings; no errors
write(*,'(3P7I2)')
@@ -309,4 +315,10 @@
!ERROR: Repeat specifier before '$' edit descriptor
write(*,'(7$)')
+
+ !ERROR: Positive scale factor k (from kP) and width d in a 'E' edit descriptor must satisfy 'k < d+2'
+ write(*, kp_xx)
+
+ !ERROR: Negative scale factor k (from kP) and width d in a 'E' edit descriptor must satisfy '-d < k'
+ write(*, '(-4P,E20.5,E15.2)')
end
More information about the flang-commits
mailing list