diff --git a/flang/documentation/C++style.md b/flang/documentation/C++style.md index 73ac75e9046a..ab9670940eff 100755 --- a/flang/documentation/C++style.md +++ b/flang/documentation/C++style.md @@ -124,7 +124,7 @@ last (_pace_ the standard C library conventions for `memcpy()` & al.). explicitly, it should contains either a `default:;` at its end or a `default:` label that obviously crashes. #### Classes -1. Define only POD structures with `struct`. +1. Define POD structures with `struct`. 1. Don't use `this->` in (non-static) member functions. 1. Define accessor and mutator member functions (implicitly) inline in the class, after constructors and assignments. Don't needlessly define diff --git a/flang/documentation/parsing.md b/flang/documentation/parsing.md index f10ff7657c4a..f4757e90319a 100644 --- a/flang/documentation/parsing.md +++ b/flang/documentation/parsing.md @@ -178,13 +178,15 @@ as function calls. The semantic analysis phase of the compiler performs local rewrites of the parse tree once it can be disambiguated by symbols and types. -Formally speaking, this parser is based on recursive descent with localized -backtracking. It is not generated as a table or code from a specification -of the Fortran grammar; rather, it _is_ the grammar, as declaratively -respecified in C++ constant expressions using a small collection of basic -token recognition objects and a library of "parser combinator" template -functions that compose them to form more complicated recognizers and -their correspondences to the construction of parse tree values. +Formally speaking, this parser is based on recursive descent with +localized backtracking (specifically, it will not backtrack into a +successful reduction to try its other alternatives). It is not generated +as a table or code from a specification of the Fortran grammar; rather, it +_is_ the grammar, as declaratively respecified in C++ constant expressions +using a small collection of basic token recognition objects and a library +of "parser combinator" template functions that compose them to form more +complicated recognizers and their correspondences to the construction +of parse tree values. Unparsing --------- diff --git a/flang/lib/parser/format-specification.h b/flang/lib/parser/format-specification.h index ea40df708961..3d76cf0905d9 100644 --- a/flang/lib/parser/format-specification.h +++ b/flang/lib/parser/format-specification.h @@ -91,10 +91,10 @@ struct ControlEditDesc { ControlEditDesc(ControlEditDesc &&) = default; ControlEditDesc &operator=(ControlEditDesc &&) = default; explicit ControlEditDesc(Kind k) : kind{k} {} - ControlEditDesc(Kind k, int ct) : kind{k}, count{ct} {} - ControlEditDesc(int ct, Kind k) : kind{k}, count{ct} {} + ControlEditDesc(Kind k, std::int64_t ct) : kind{k}, count{ct} {} + ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {} Kind kind; - int count{1}; // r, k, or n + std::int64_t count{1}; // r, k, or n }; // R1304 format-item -> @@ -107,10 +107,10 @@ struct FormatItem { FormatItem(FormatItem &&) = default; FormatItem &operator=(FormatItem &&) = default; template - FormatItem(std::optional &&r, A &&x) + FormatItem(std::optional &&r, A &&x) : repeatCount{std::move(r)}, u{std::move(x)} {} template explicit FormatItem(A &&x) : u{std::move(x)} {} - std::optional repeatCount; + std::optional repeatCount; std::variant> u; diff --git a/flang/lib/parser/grammar.h b/flang/lib/parser/grammar.h index 5b221cde3d25..f02fa0c287d8 100644 --- a/flang/lib/parser/grammar.h +++ b/flang/lib/parser/grammar.h @@ -159,7 +159,7 @@ template inline constexpr auto indirect(const PA &p) { // R711 digit-string -> digit [digit]... // N.B. not a token -- no space is skipped -constexpr auto digitString = DigitString{}; +constexpr DigitString digitString; // statement(p) parses Statement

for some statement type P that is the // result type of the argument parser p, while also handling labels and @@ -707,17 +707,7 @@ TYPE_PARSER(construct{}( // R710 signed-digit-string -> [sign] digit-string // N.B. Not a complete token -- no space is skipped. -static inline std::int64_t negate(std::uint64_t &&n) { - return -n; // TODO: check for overflow -} - -static inline std::int64_t castToSigned(std::uint64_t &&n) { - return n; // TODO: check for overflow -} - -constexpr auto signedDigitString = "-"_ch >> - applyFunction(negate, digitString) || - maybe("+"_ch) >> applyFunction(castToSigned, digitString); +constexpr SignedDigitString signedDigitString; // R707 signed-int-literal-constant -> [sign] int-literal-constant TYPE_PARSER(space >> sourced(construct{}( @@ -3081,11 +3071,7 @@ constexpr auto formatItems = nonemptySeparated(space >> Parser{}, maybe(","_tok)); // R1306 r -> digit-string -static inline int castU64ToInt(std::uint64_t &&n) { - return n; // TODO: check for overflow -} - -constexpr auto repeat = space >> applyFunction(castU64ToInt, digitString); +constexpr auto repeat = space >> digitString; // R1304 format-item -> // [r] data-edit-desc | control-edit-desc | char-string-edit-desc | @@ -3177,11 +3163,8 @@ TYPE_PARSER("D"_ch >> "T"_ch >> defaulted(parenthesized(nonemptyList(space >> signedDigitString))))) // R1314 k -> [sign] digit-string -static inline int castS64ToInt(std::int64_t &&n) { - return n; // TODO: check for overflow -} -constexpr auto scaleFactor = space >> - applyFunction(castS64ToInt, signedDigitString); +constexpr auto count = space >> DigitStringAsPositive{}; +constexpr auto scaleFactor = count; // R1313 control-edit-desc -> // position-edit-desc | [r] / | : | sign-edit-desc | k P | @@ -3196,8 +3179,8 @@ TYPE_PARSER(construct{}("T"_ch >> ("L"_ch >> pure(format::ControlEditDesc::Kind::TL) || "R"_ch >> pure(format::ControlEditDesc::Kind::TR) || pure(format::ControlEditDesc::Kind::T)), - repeat) || - construct{}(repeat, + count) || + construct{}(count, "X"_ch >> pure(format::ControlEditDesc::Kind::X) || "/"_ch >> pure(format::ControlEditDesc::Kind::Slash)) || construct{}( diff --git a/flang/lib/parser/token-parsers.h b/flang/lib/parser/token-parsers.h index 2e2094a7a5ed..c88fd54e21d7 100644 --- a/flang/lib/parser/token-parsers.h +++ b/flang/lib/parser/token-parsers.h @@ -457,6 +457,49 @@ constexpr struct SkipDigitString { } } skipDigitString; +struct DigitStringAsPositive { + using resultType = std::int64_t; + static std::optional Parse(ParseState *state) { + Location at{state->GetLocation()}; + std::optional x{DigitString{}.Parse(state)}; + if (!x.has_value()) { + return {}; + } + if (*x > std::numeric_limits::max()) { + state->Say(at, "overflow in positive decimal literal"_err_en_US); + } + std::int64_t value = *x; + return {value}; + } +}; + +struct SignedDigitString { + using resultType = std::int64_t; + static std::optional Parse(ParseState *state) { + std::optional sign{state->PeekAtNextChar()}; + if (!sign.has_value()) { + return {}; + } + bool negate{**sign == '-'}; + if (negate || **sign == '+') { + state->UncheckedAdvance(); + } + std::optional x{DigitString{}.Parse(state)}; + if (!x.has_value()) { + return {}; + } + std::uint64_t limit{std::numeric_limits::max()}; + if (negate) { + limit = -(limit + 1); + } + if (*x > limit) { + state->Say(*sign, "overflow in signed decimal literal"_err_en_US); + } + std::int64_t value = *x; + return {negate ? -value : value}; + } +}; + // Legacy feature: Hollerith literal constants struct HollerithLiteral { using resultType = std::string;