[flang] Reformat with latest clang-format and .clang-format

Original-commit: flang-compiler/f18@9fe84f45d7
Reviewed-on: https://github.com/flang-compiler/f18/pull/1094
This commit is contained in:
Tim Keith 2020-03-28 21:00:16 -07:00
parent 10b1addcef
commit 1f8790050b
265 changed files with 5586 additions and 4856 deletions

View File

@ -61,5 +61,5 @@ private:
LanguageFeatures warn_; LanguageFeatures warn_;
bool warnAll_{false}; bool warnAll_{false};
}; };
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_FORTRAN_FEATURES_H_ #endif // FORTRAN_COMMON_FORTRAN_FEATURES_H_

View File

@ -52,21 +52,21 @@ ENUM_CLASS(IoSpecKind, Access, Action, Advance, Asynchronous, Blank, Decimal,
Id, Iomsg, Iostat, Name, Named, Newunit, Nextrec, Nml, Number, Opened, Pad, Id, Iomsg, Iostat, Name, Named, Newunit, Nextrec, Nml, Number, Opened, Pad,
Pending, Pos, Position, Read, Readwrite, Rec, Recl, Round, Sequential, Sign, Pending, Pos, Position, Read, Readwrite, Rec, Recl, Round, Sequential, Sign,
Size, Status, Stream, Unformatted, Unit, Write, Size, Status, Stream, Unformatted, Unit, Write,
Convert, // nonstandard Convert, // nonstandard
Dispose, // nonstandard Dispose, // nonstandard
) )
// Floating-point rounding modes; these are packed into a byte to save // Floating-point rounding modes; these are packed into a byte to save
// room in the runtime's format processing context structure. // room in the runtime's format processing context structure.
enum class RoundingMode : std::uint8_t { enum class RoundingMode : std::uint8_t {
TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
ToZero, // ROUND=ZERO, RZ - truncation ToZero, // ROUND=ZERO, RZ - truncation
Down, // ROUND=DOWN, RD Down, // ROUND=DOWN, RD
Up, // ROUND=UP, RU Up, // ROUND=UP, RU
TiesAwayFromZero, // ROUND=COMPATIBLE, RC - ties round away from zero TiesAwayFromZero, // ROUND=COMPATIBLE, RC - ties round away from zero
}; };
// Fortran arrays may have up to 15 dimensions (See Fortran 2018 section 5.4.6). // Fortran arrays may have up to 15 dimensions (See Fortran 2018 section 5.4.6).
static constexpr int maxRank{15}; static constexpr int maxRank{15};
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_FORTRAN_H_ #endif // FORTRAN_COMMON_FORTRAN_H_

View File

@ -70,18 +70,18 @@ inline constexpr int BitPopulationCount(std::uint8_t x) {
return (x & 0xf) + (x >> 4); return (x & 0xf) + (x >> 4);
} }
template<typename UINT> inline constexpr bool Parity(UINT x) { template <typename UINT> inline constexpr bool Parity(UINT x) {
return BitPopulationCount(x) & 1; return BitPopulationCount(x) & 1;
} }
// "Parity is for farmers." -- Seymour R. Cray // "Parity is for farmers." -- Seymour R. Cray
template<typename UINT> inline constexpr int TrailingZeroBitCount(UINT x) { template <typename UINT> inline constexpr int TrailingZeroBitCount(UINT x) {
if ((x & 1) != 0) { if ((x & 1) != 0) {
return 0; // fast path for odd values return 0; // fast path for odd values
} else { } else {
return BitPopulationCount(static_cast<UINT>(x ^ (x - 1))) - !!x; return BitPopulationCount(static_cast<UINT>(x ^ (x - 1))) - !!x;
} }
} }
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_BIT_POPULATION_COUNT_H_ #endif // FORTRAN_COMMON_BIT_POPULATION_COUNT_H_

View File

@ -21,7 +21,7 @@
namespace Fortran::common { namespace Fortran::common {
template<int BITS> class BitSet { template <int BITS> class BitSet {
static_assert(BITS > 0 && BITS <= 64); static_assert(BITS > 0 && BITS <= 64);
static constexpr bool partialWord{BITS != 32 && BITS != 64}; static constexpr bool partialWord{BITS != 32 && BITS != 64};
using Word = std::conditional_t<(BITS > 32), std::uint64_t, std::uint32_t>; using Word = std::conditional_t<(BITS > 32), std::uint64_t, std::uint32_t>;
@ -143,5 +143,5 @@ public:
private: private:
Word bits_{0}; Word bits_{0};
}; };
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_CONSTEXPR_BITSET_H_ #endif // FORTRAN_COMMON_CONSTEXPR_BITSET_H_

View File

@ -50,12 +50,12 @@ private:
// comprise two default REAL components. // comprise two default REAL components.
int defaultIntegerKind_{4}; int defaultIntegerKind_{4};
int subscriptIntegerKind_{8}; int subscriptIntegerKind_{8};
int sizeIntegerKind_{4}; // SIZE(), UBOUND(), &c. default KIND= int sizeIntegerKind_{4}; // SIZE(), UBOUND(), &c. default KIND=
int defaultRealKind_{defaultIntegerKind_}; int defaultRealKind_{defaultIntegerKind_};
int doublePrecisionKind_{2 * defaultRealKind_}; int doublePrecisionKind_{2 * defaultRealKind_};
int quadPrecisionKind_{2 * doublePrecisionKind_}; int quadPrecisionKind_{2 * doublePrecisionKind_};
int defaultCharacterKind_{1}; int defaultCharacterKind_{1};
int defaultLogicalKind_{defaultIntegerKind_}; int defaultLogicalKind_{defaultIntegerKind_};
}; };
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_DEFAULT_KINDS_H_ #endif // FORTRAN_COMMON_DEFAULT_KINDS_H_

View File

@ -26,7 +26,7 @@
namespace Fortran::common { namespace Fortran::common {
template<typename ENUM, std::size_t BITS> class EnumSet { template <typename ENUM, std::size_t BITS> class EnumSet {
static_assert(BITS > 0); static_assert(BITS > 0);
public: public:
@ -191,7 +191,7 @@ public:
} }
} }
template<typename FUNC> void IterateOverMembers(const FUNC &f) const { template <typename FUNC> void IterateOverMembers(const FUNC &f) const {
EnumSet copy{*this}; EnumSet copy{*this};
while (auto least{copy.LeastElement()}) { while (auto least{copy.LeastElement()}) {
f(*least); f(*least);
@ -212,13 +212,13 @@ public:
private: private:
bitsetType bitset_{}; bitsetType bitset_{};
}; };
} } // namespace Fortran::common
template<typename ENUM, std::size_t values> template <typename ENUM, std::size_t values>
struct std::hash<Fortran::common::EnumSet<ENUM, values>> { struct std::hash<Fortran::common::EnumSet<ENUM, values>> {
std::size_t operator()( std::size_t operator()(
const Fortran::common::EnumSet<ENUM, values> &x) const { const Fortran::common::EnumSet<ENUM, values> &x) const {
return std::hash(x.bitset()); return std::hash(x.bitset());
} }
}; };
#endif // FORTRAN_COMMON_ENUM_SET_H_ #endif // FORTRAN_COMMON_ENUM_SET_H_

View File

@ -29,30 +29,30 @@
namespace Fortran::common { namespace Fortran::common {
struct FormatMessage { struct FormatMessage {
const char *text; // message text; may have one %s argument const char *text; // message text; may have one %s argument
const char *arg; // optional %s argument value const char *arg; // optional %s argument value
int offset; // offset to message marker int offset; // offset to message marker
int length; // length of message marker int length; // length of message marker
bool isError; // vs. warning bool isError; // vs. warning
}; };
// This declaration is logically private to class FormatValidator. // This declaration is logically private to class FormatValidator.
// It is placed here to work around a clang compilation problem. // 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, 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, 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 Backslash, // nonstandard: inhibit newline on output
Dollar, // nonstandard: inhibit newline on output on terminals Dollar, // nonstandard: inhibit newline on output on terminals
Star, LParen, RParen, Comma, Point, Sign, Star, LParen, RParen, Comma, Point, Sign,
UnsignedInteger, // value in integerValue_ UnsignedInteger, // value in integerValue_
String) // char-literal-constant or Hollerith constant String) // char-literal-constant or Hollerith constant
template<typename CHAR = char> class FormatValidator { template <typename CHAR = char> class FormatValidator {
public: public:
using Reporter = std::function<bool(const FormatMessage &)>; using Reporter = std::function<bool(const FormatMessage &)>;
FormatValidator(const CHAR *format, size_t length, Reporter reporter, FormatValidator(const CHAR *format, size_t length, Reporter reporter,
IoStmtKind stmt = IoStmtKind::None) IoStmtKind stmt = IoStmtKind::None)
: format_{format}, end_{format + length}, reporter_{reporter}, stmt_{stmt}, : format_{format}, end_{format + length}, reporter_{reporter},
cursor_{format - 1} { stmt_{stmt}, cursor_{format - 1} {
CHECK(format); CHECK(format);
} }
@ -128,54 +128,54 @@ private:
bool check_d(); bool check_d();
void check_e(); void check_e();
const CHAR *const format_; // format text const CHAR *const format_; // format text
const CHAR *const end_; // one-past-last of format_ text const CHAR *const end_; // one-past-last of format_ text
Reporter reporter_; Reporter reporter_;
IoStmtKind stmt_; IoStmtKind stmt_;
const CHAR *cursor_{}; // current location in format_ const CHAR *cursor_{}; // current location in format_
const CHAR *laCursor_{}; // lookahead cursor const CHAR *laCursor_{}; // lookahead cursor
Token token_{}; // current token Token token_{}; // current token
int64_t integerValue_{-1}; // value of UnsignedInteger token int64_t integerValue_{-1}; // value of UnsignedInteger token
Token knrToken_{}; // k, n, or r UnsignedInteger token Token knrToken_{}; // k, n, or r UnsignedInteger token
int64_t knrValue_{-1}; // -1 ==> not present int64_t knrValue_{-1}; // -1 ==> not present
int64_t wValue_{-1}; int64_t wValue_{-1};
bool previousTokenWasInt_{false}; bool previousTokenWasInt_{false};
char argString_[3]{}; // 1-2 character msg arg; usually edit descriptor name char argString_[3]{}; // 1-2 character msg arg; usually edit descriptor name
bool formatHasErrors_{false}; bool formatHasErrors_{false};
bool unterminatedFormatError_{false}; bool unterminatedFormatError_{false};
bool suppressMessageCascade_{false}; bool suppressMessageCascade_{false};
bool reporterExit_{false}; bool reporterExit_{false};
int maxNesting_{0}; // max level of nested parentheses int maxNesting_{0}; // max level of nested parentheses
}; };
template<typename CHAR> CHAR FormatValidator<CHAR>::NextChar() { template <typename CHAR> CHAR FormatValidator<CHAR>::NextChar() {
for (++cursor_; cursor_ < end_; ++cursor_) { for (++cursor_; cursor_ < end_; ++cursor_) {
if (*cursor_ != ' ') { if (*cursor_ != ' ') {
return toupper(*cursor_); return toupper(*cursor_);
} }
} }
cursor_ = end_; // don't allow cursor_ > end_ cursor_ = end_; // don't allow cursor_ > end_
return ' '; return ' ';
} }
template<typename CHAR> CHAR FormatValidator<CHAR>::LookAheadChar() { template <typename CHAR> CHAR FormatValidator<CHAR>::LookAheadChar() {
for (laCursor_ = cursor_ + 1; laCursor_ < end_; ++laCursor_) { for (laCursor_ = cursor_ + 1; laCursor_ < end_; ++laCursor_) {
if (*laCursor_ != ' ') { if (*laCursor_ != ' ') {
return toupper(*laCursor_); return toupper(*laCursor_);
} }
} }
laCursor_ = end_; // don't allow laCursor_ > end_ laCursor_ = end_; // don't allow laCursor_ > end_
return ' '; return ' ';
} }
// After a call to LookAheadChar, set token kind and advance cursor to laCursor. // After a call to LookAheadChar, set token kind and advance cursor to laCursor.
template<typename CHAR> void FormatValidator<CHAR>::Advance(TokenKind tk) { template <typename CHAR> void FormatValidator<CHAR>::Advance(TokenKind tk) {
cursor_ = laCursor_; cursor_ = laCursor_;
token_.set_kind(tk); token_.set_kind(tk);
} }
template<typename CHAR> void FormatValidator<CHAR>::NextToken() { template <typename CHAR> void FormatValidator<CHAR>::NextToken() {
// At entry, cursor_ points before the start of the next token. // At entry, cursor_ points before the start of the next token.
// At exit, cursor_ points to last CHAR of token_. // At exit, cursor_ points to last CHAR of token_.
@ -184,7 +184,7 @@ template<typename CHAR> void FormatValidator<CHAR>::NextToken() {
token_.set_kind(TokenKind::None); token_.set_kind(TokenKind::None);
token_.set_offset(cursor_ - format_); token_.set_offset(cursor_ - format_);
token_.set_length(1); token_.set_length(1);
if (c == '_' && integerValue_ >= 0) { // C1305, C1309, C1310, C1312, C1313 if (c == '_' && integerValue_ >= 0) { // C1305, C1309, C1310, C1312, C1313
ReportError("Kind parameter '_' character in format expression"); ReportError("Kind parameter '_' character in format expression");
} }
integerValue_ = -1; integerValue_ = -1;
@ -232,7 +232,7 @@ template<typename CHAR> void FormatValidator<CHAR>::NextToken() {
cursor_ = end_; cursor_ = end_;
} }
SetLength(); SetLength();
if (stmt_ == IoStmtKind::Read) { // 13.3.2p6 if (stmt_ == IoStmtKind::Read) { // 13.3.2p6
ReportError("'H' edit descriptor in READ format expression"); ReportError("'H' edit descriptor in READ format expression");
} else if (token_.kind() == TokenKind::None) { } else if (token_.kind() == TokenKind::None) {
ReportError("Unterminated 'H' edit descriptor"); ReportError("Unterminated 'H' edit descriptor");
@ -241,72 +241,154 @@ template<typename CHAR> void FormatValidator<CHAR>::NextToken() {
} }
break; break;
} }
case 'A': token_.set_kind(TokenKind::A); break; case 'A':
token_.set_kind(TokenKind::A);
break;
case 'B': case 'B':
switch (LookAheadChar()) { switch (LookAheadChar()) {
case 'N': Advance(TokenKind::BN); break; case 'N':
case 'Z': Advance(TokenKind::BZ); break; Advance(TokenKind::BN);
default: token_.set_kind(TokenKind::B); break; break;
case 'Z':
Advance(TokenKind::BZ);
break;
default:
token_.set_kind(TokenKind::B);
break;
} }
break; break;
case 'D': case 'D':
switch (LookAheadChar()) { switch (LookAheadChar()) {
case 'C': Advance(TokenKind::DC); break; case 'C':
case 'P': Advance(TokenKind::DP); break; Advance(TokenKind::DC);
case 'T': Advance(TokenKind::DT); break; break;
default: token_.set_kind(TokenKind::D); break; case 'P':
Advance(TokenKind::DP);
break;
case 'T':
Advance(TokenKind::DT);
break;
default:
token_.set_kind(TokenKind::D);
break;
} }
break; break;
case 'E': case 'E':
switch (LookAheadChar()) { switch (LookAheadChar()) {
case 'N': Advance(TokenKind::EN); break; case 'N':
case 'S': Advance(TokenKind::ES); break; Advance(TokenKind::EN);
case 'X': Advance(TokenKind::EX); break; break;
default: token_.set_kind(TokenKind::E); break; case 'S':
Advance(TokenKind::ES);
break;
case 'X':
Advance(TokenKind::EX);
break;
default:
token_.set_kind(TokenKind::E);
break;
} }
break; break;
case 'F': token_.set_kind(TokenKind::F); break; case 'F':
case 'G': token_.set_kind(TokenKind::G); break; token_.set_kind(TokenKind::F);
case 'I': token_.set_kind(TokenKind::I); break; break;
case 'L': token_.set_kind(TokenKind::L); break; case 'G':
case 'O': token_.set_kind(TokenKind::O); break; token_.set_kind(TokenKind::G);
case 'P': token_.set_kind(TokenKind::P); break; break;
case 'I':
token_.set_kind(TokenKind::I);
break;
case 'L':
token_.set_kind(TokenKind::L);
break;
case 'O':
token_.set_kind(TokenKind::O);
break;
case 'P':
token_.set_kind(TokenKind::P);
break;
case 'R': case 'R':
switch (LookAheadChar()) { switch (LookAheadChar()) {
case 'C': Advance(TokenKind::RC); break; case 'C':
case 'D': Advance(TokenKind::RD); break; Advance(TokenKind::RC);
case 'N': Advance(TokenKind::RN); break; break;
case 'P': Advance(TokenKind::RP); break; case 'D':
case 'U': Advance(TokenKind::RU); break; Advance(TokenKind::RD);
case 'Z': Advance(TokenKind::RZ); break; break;
default: token_.set_kind(TokenKind::None); break; case 'N':
Advance(TokenKind::RN);
break;
case 'P':
Advance(TokenKind::RP);
break;
case 'U':
Advance(TokenKind::RU);
break;
case 'Z':
Advance(TokenKind::RZ);
break;
default:
token_.set_kind(TokenKind::None);
break;
} }
break; break;
case 'S': case 'S':
switch (LookAheadChar()) { switch (LookAheadChar()) {
case 'P': Advance(TokenKind::SP); break; case 'P':
case 'S': Advance(TokenKind::SS); break; Advance(TokenKind::SP);
default: token_.set_kind(TokenKind::S); break; break;
case 'S':
Advance(TokenKind::SS);
break;
default:
token_.set_kind(TokenKind::S);
break;
} }
break; break;
case 'T': case 'T':
switch (LookAheadChar()) { switch (LookAheadChar()) {
case 'L': Advance(TokenKind::TL); break; case 'L':
case 'R': Advance(TokenKind::TR); break; Advance(TokenKind::TL);
default: token_.set_kind(TokenKind::T); break; break;
case 'R':
Advance(TokenKind::TR);
break;
default:
token_.set_kind(TokenKind::T);
break;
} }
break; break;
case 'X': token_.set_kind(TokenKind::X); break; case 'X':
case 'Z': token_.set_kind(TokenKind::Z); break; token_.set_kind(TokenKind::X);
break;
case 'Z':
token_.set_kind(TokenKind::Z);
break;
case '-': case '-':
case '+': token_.set_kind(TokenKind::Sign); break; case '+':
case '/': token_.set_kind(TokenKind::Slash); break; token_.set_kind(TokenKind::Sign);
case '(': token_.set_kind(TokenKind::LParen); break; break;
case ')': token_.set_kind(TokenKind::RParen); break; case '/':
case '.': token_.set_kind(TokenKind::Point); break; token_.set_kind(TokenKind::Slash);
case ':': token_.set_kind(TokenKind::Colon); break; break;
case '\\': token_.set_kind(TokenKind::Backslash); break; case '(':
case '$': token_.set_kind(TokenKind::Dollar); break; token_.set_kind(TokenKind::LParen);
break;
case ')':
token_.set_kind(TokenKind::RParen);
break;
case '.':
token_.set_kind(TokenKind::Point);
break;
case ':':
token_.set_kind(TokenKind::Colon);
break;
case '\\':
token_.set_kind(TokenKind::Backslash);
break;
case '$':
token_.set_kind(TokenKind::Dollar);
break;
case '*': case '*':
token_.set_kind(LookAheadChar() == '(' ? TokenKind::Star : TokenKind::None); token_.set_kind(LookAheadChar() == '(' ? TokenKind::Star : TokenKind::None);
break; break;
@ -334,7 +416,7 @@ template<typename CHAR> void FormatValidator<CHAR>::NextToken() {
} }
} }
SetLength(); SetLength();
if (stmt_ == IoStmtKind::Read) { // 13.3.2p6 if (stmt_ == IoStmtKind::Read) { // 13.3.2p6
ReportError("String edit descriptor in READ format expression"); ReportError("String edit descriptor in READ format expression");
} else if (token_.kind() != TokenKind::String) { } else if (token_.kind() != TokenKind::String) {
ReportError("Unterminated string"); ReportError("Unterminated string");
@ -353,34 +435,34 @@ template<typename CHAR> void FormatValidator<CHAR>::NextToken() {
SetLength(); SetLength();
} }
template<typename CHAR> void FormatValidator<CHAR>::check_r(bool allowed) { template <typename CHAR> void FormatValidator<CHAR>::check_r(bool allowed) {
if (!allowed && knrValue_ >= 0) { if (!allowed && knrValue_ >= 0) {
ReportError("Repeat specifier before '%s' edit descriptor", knrToken_); ReportError("Repeat specifier before '%s' edit descriptor", knrToken_);
} else if (knrValue_ == 0) { } else if (knrValue_ == 0) {
ReportError("'%s' edit descriptor repeat specifier must be positive", ReportError("'%s' edit descriptor repeat specifier must be positive",
knrToken_); // C1304 knrToken_); // C1304
} }
} }
// Return the predicate "w value is present" to control further processing. // Return the predicate "w value is present" to control further processing.
template<typename CHAR> bool FormatValidator<CHAR>::check_w() { template <typename CHAR> bool FormatValidator<CHAR>::check_w() {
if (token_.kind() == TokenKind::UnsignedInteger) { if (token_.kind() == TokenKind::UnsignedInteger) {
wValue_ = integerValue_; wValue_ = integerValue_;
if (wValue_ == 0 && if (wValue_ == 0 &&
(*argString_ == 'A' || *argString_ == 'L' || (*argString_ == 'A' || *argString_ == 'L' ||
stmt_ == IoStmtKind::Read)) { // C1306, 13.7.2.1p6 stmt_ == IoStmtKind::Read)) { // C1306, 13.7.2.1p6
ReportError("'%s' edit descriptor 'w' value must be positive"); ReportError("'%s' edit descriptor 'w' value must be positive");
} }
NextToken(); NextToken();
return true; return true;
} }
if (*argString_ != 'A') { if (*argString_ != 'A') {
ReportWarning("Expected '%s' edit descriptor 'w' value"); // C1306 ReportWarning("Expected '%s' edit descriptor 'w' value"); // C1306
} }
return false; return false;
} }
template<typename CHAR> void FormatValidator<CHAR>::check_m() { template <typename CHAR> void FormatValidator<CHAR>::check_m() {
if (token_.kind() != TokenKind::Point) { if (token_.kind() != TokenKind::Point) {
return; return;
} }
@ -390,14 +472,14 @@ template<typename CHAR> void FormatValidator<CHAR>::check_m() {
return; return;
} }
if ((stmt_ == IoStmtKind::Print || stmt_ == IoStmtKind::Write) && if ((stmt_ == IoStmtKind::Print || stmt_ == IoStmtKind::Write) &&
wValue_ > 0 && integerValue_ > wValue_) { // 13.7.2.2p5, 13.7.2.4p6 wValue_ > 0 && integerValue_ > wValue_) { // 13.7.2.2p5, 13.7.2.4p6
ReportError("'%s' edit descriptor 'm' value is greater than 'w' value"); ReportError("'%s' edit descriptor 'm' value is greater than 'w' value");
} }
NextToken(); NextToken();
} }
// Return the predicate "d value is present" to control further processing. // 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() {
if (token_.kind() != TokenKind::Point) { if (token_.kind() != TokenKind::Point) {
ReportError("Expected '%s' edit descriptor '.d' value"); ReportError("Expected '%s' edit descriptor '.d' value");
return false; return false;
@ -411,7 +493,7 @@ template<typename CHAR> bool FormatValidator<CHAR>::check_d() {
return true; return true;
} }
template<typename CHAR> void FormatValidator<CHAR>::check_e() { template <typename CHAR> void FormatValidator<CHAR>::check_e() {
if (token_.kind() != TokenKind::E) { if (token_.kind() != TokenKind::E) {
return; return;
} }
@ -423,7 +505,7 @@ template<typename CHAR> void FormatValidator<CHAR>::check_e() {
NextToken(); NextToken();
} }
template<typename CHAR> bool FormatValidator<CHAR>::Check() { template <typename CHAR> bool FormatValidator<CHAR>::Check() {
if (!*format_) { if (!*format_) {
ReportError("Empty format expression"); ReportError("Empty format expression");
return formatHasErrors_; return formatHasErrors_;
@ -435,8 +517,8 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
} }
NextToken(); NextToken();
int nestLevel{0}; // Outer level ()s are at level 0. int nestLevel{0}; // Outer level ()s are at level 0.
Token starToken{}; // unlimited format token Token starToken{}; // unlimited format token
bool hasDataEditDesc{false}; bool hasDataEditDesc{false};
// Subject to error recovery exceptions, a loop iteration processes one // Subject to error recovery exceptions, a loop iteration processes one
@ -446,7 +528,7 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
// - the error reporter requests termination (error threshold reached) // - the error reporter requests termination (error threshold reached)
while (!reporterExit_) { while (!reporterExit_) {
Token signToken{}; Token signToken{};
knrValue_ = -1; // -1 ==> not present knrValue_ = -1; // -1 ==> not present
wValue_ = -1; wValue_ = -1;
bool commaRequired{true}; bool commaRequired{true};
@ -519,12 +601,12 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
NextToken(); NextToken();
if (check_w()) { if (check_w()) {
if (wValue_ > 0) { if (wValue_ > 0) {
if (check_d()) { // C1307 if (check_d()) { // C1307
check_e(); check_e();
} }
} else if (token_.kind() == TokenKind::Point && check_d() && } else if (token_.kind() == TokenKind::Point && check_d() &&
token_.kind() == TokenKind::E) { token_.kind() == TokenKind::E) {
ReportError("Unexpected 'e' in 'G0' edit descriptor"); // C1308 ReportError("Unexpected 'e' in 'G0' edit descriptor"); // C1308
NextToken(); NextToken();
if (token_.kind() == TokenKind::UnsignedInteger) { if (token_.kind() == TokenKind::UnsignedInteger) {
NextToken(); NextToken();
@ -616,7 +698,9 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
case TokenKind::ES: case TokenKind::ES:
case TokenKind::EX: case TokenKind::EX:
case TokenKind::F: case TokenKind::F:
case TokenKind::G: commaRequired = false; break; case TokenKind::G:
commaRequired = false;
break;
default:; default:;
} }
cursor_ = saveCursor; cursor_ = saveCursor;
@ -629,14 +713,14 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
// R1315 position-edit-desc -> T n | TL n | TR n // R1315 position-edit-desc -> T n | TL n | TR n
check_r(false); check_r(false);
NextToken(); NextToken();
if (integerValue_ <= 0) { // C1311 if (integerValue_ <= 0) { // C1311
ReportError("'%s' edit descriptor must have a positive position value"); ReportError("'%s' edit descriptor must have a positive position value");
} }
NextToken(); NextToken();
break; break;
case TokenKind::X: case TokenKind::X:
// R1315 position-edit-desc -> n X // R1315 position-edit-desc -> n X
if (knrValue_ == 0) { // C1311 if (knrValue_ == 0) { // C1311
ReportError("'X' edit descriptor must have a positive position value", ReportError("'X' edit descriptor must have a positive position value",
knrToken_); knrToken_);
} else if (knrValue_ < 0) { } else if (knrValue_ < 0) {
@ -695,11 +779,11 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
do { do {
if (nestLevel == 0) { if (nestLevel == 0) {
// Any characters after level-0 ) are ignored. // Any characters after level-0 ) are ignored.
return formatHasErrors_; // normal exit (may have messages) return formatHasErrors_; // normal exit (may have messages)
} }
if (nestLevel == 1 && starToken.IsSet() && !hasDataEditDesc) { if (nestLevel == 1 && starToken.IsSet() && !hasDataEditDesc) {
SetLength(starToken); SetLength(starToken);
ReportError( // C1303 ReportError( // C1303
"Unlimited format item list must contain a data edit descriptor", "Unlimited format item list must contain a data edit descriptor",
starToken); starToken);
} }
@ -718,31 +802,33 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
break; break;
} }
[[fallthrough]]; [[fallthrough]];
default: ReportError("Unexpected '%s' in format expression"); NextToken(); default:
ReportError("Unexpected '%s' in format expression");
NextToken();
} }
// Process comma separator and exit an incomplete format. // Process comma separator and exit an incomplete format.
switch (token_.kind()) { switch (token_.kind()) {
case TokenKind::Colon: // Comma not required; token not yet processed. case TokenKind::Colon: // Comma not required; token not yet processed.
case TokenKind::Slash: // Comma not required; token not yet processed. case TokenKind::Slash: // Comma not required; token not yet processed.
case TokenKind::RParen: // Comma not allowed; token not yet processed. case TokenKind::RParen: // Comma not allowed; token not yet processed.
suppressMessageCascade_ = false; suppressMessageCascade_ = false;
break; break;
case TokenKind::LParen: // Comma not allowed; token already processed. case TokenKind::LParen: // Comma not allowed; token already processed.
case TokenKind::Comma: // Normal comma case; move past token. case TokenKind::Comma: // Normal comma case; move past token.
suppressMessageCascade_ = false; suppressMessageCascade_ = false;
NextToken(); NextToken();
break; break;
case TokenKind::Sign: // Error; main switch has a better message. case TokenKind::Sign: // Error; main switch has a better message.
case TokenKind::None: // Error; token not yet processed. case TokenKind::None: // Error; token not yet processed.
if (cursor_ >= end_) { if (cursor_ >= end_) {
return formatHasErrors_; // incomplete format error exit return formatHasErrors_; // incomplete format error exit
} }
break; break;
default: default:
// Possible first token of the next format item; token not yet processed. // Possible first token of the next format item; token not yet processed.
if (commaRequired) { if (commaRequired) {
const char *s{"Expected ',' or ')' in format expression"}; // C1302 const char *s{"Expected ',' or ')' in format expression"}; // C1302
if (previousTokenWasInt_ && itemsWithLeadingInts_.test(token_.kind())) { if (previousTokenWasInt_ && itemsWithLeadingInts_.test(token_.kind())) {
ReportError(s); ReportError(s);
} else { } else {
@ -752,8 +838,8 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
} }
} }
return formatHasErrors_; // error reporter (message threshold) exit return formatHasErrors_; // error reporter (message threshold) exit
} }
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_FORMAT_H_ #endif // FORTRAN_COMMON_FORMAT_H_

View File

@ -34,11 +34,11 @@
#if __GNUC__ == 7 #if __GNUC__ == 7
// Avoid a deduction bug in GNU 7.x headers by forcing the answer. // Avoid a deduction bug in GNU 7.x headers by forcing the answer.
namespace std { namespace std {
template<typename A> template <typename A>
struct is_trivially_copy_constructible<list<A>> : false_type {}; struct is_trivially_copy_constructible<list<A>> : false_type {};
template<typename A> template <typename A>
struct is_trivially_copy_constructible<optional<list<A>>> : false_type {}; struct is_trivially_copy_constructible<optional<list<A>>> : false_type {};
} } // namespace std
#endif #endif
// enable "this is a std::string"s with the 's' suffix // enable "this is a std::string"s with the 's' suffix
@ -54,11 +54,11 @@ namespace Fortran::common {
// ... // ...
// [&](const auto &catchAll) { ... }}, variantObject); // [&](const auto &catchAll) { ... }}, variantObject);
template<typename... LAMBDAS> struct visitors : LAMBDAS... { template <typename... LAMBDAS> struct visitors : LAMBDAS... {
using LAMBDAS::operator()...; using LAMBDAS::operator()...;
}; };
template<typename... LAMBDAS> visitors(LAMBDAS... x)->visitors<LAMBDAS...>; template <typename... LAMBDAS> visitors(LAMBDAS... x) -> visitors<LAMBDAS...>;
// Calls std::fprintf(stderr, ...), then abort(). // Calls std::fprintf(stderr, ...), then abort().
[[noreturn]] void die(const char *, ...); [[noreturn]] void die(const char *, ...);
@ -93,11 +93,11 @@ template<typename... LAMBDAS> visitors(LAMBDAS... x)->visitors<LAMBDAS...>;
// in template specialization definitions. // in template specialization definitions.
#define CLASS_TRAIT(T) \ #define CLASS_TRAIT(T) \
namespace class_trait_ns_##T { \ namespace class_trait_ns_##T { \
template<typename A> std::true_type test(typename A::T *); \ template <typename A> std::true_type test(typename A::T *); \
template<typename A> std::false_type test(...); \ template <typename A> std::false_type test(...); \
template<typename A> \ template <typename A> \
constexpr bool has_trait{decltype(test<A>(nullptr))::value}; \ constexpr bool has_trait{decltype(test<A>(nullptr))::value}; \
template<typename A> constexpr bool trait_value() { \ template <typename A> constexpr bool trait_value() { \
if constexpr (has_trait<A>) { \ if constexpr (has_trait<A>) { \
using U = typename A::T; \ using U = typename A::T; \
return U::value; \ return U::value; \
@ -106,7 +106,7 @@ template<typename... LAMBDAS> visitors(LAMBDAS... x)->visitors<LAMBDAS...>;
} \ } \
} \ } \
} \ } \
template<typename A> constexpr bool T{class_trait_ns_##T::trait_value<A>()}; template <typename A> constexpr bool T{class_trait_ns_##T::trait_value<A>()};
#if !defined ATTRIBUTE_UNUSED && (__clang__ || __GNUC__) #if !defined ATTRIBUTE_UNUSED && (__clang__ || __GNUC__)
#define ATTRIBUTE_UNUSED __attribute__((unused)) #define ATTRIBUTE_UNUSED __attribute__((unused))
@ -119,7 +119,7 @@ template<typename... LAMBDAS> visitors(LAMBDAS... x)->visitors<LAMBDAS...>;
std::string EnumIndexToString(int index, const char *names); std::string EnumIndexToString(int index, const char *names);
template<typename A> struct ListItemCount { template <typename A> struct ListItemCount {
constexpr ListItemCount(std::initializer_list<A> list) : value{list.size()} {} constexpr ListItemCount(std::initializer_list<A> list) : value{list.size()} {}
const std::size_t value; const std::size_t value;
}; };
@ -138,7 +138,7 @@ template<typename A> struct ListItemCount {
// Check that a pointer is non-null and dereference it // Check that a pointer is non-null and dereference it
#define DEREF(p) Fortran::common::Deref(p, __FILE__, __LINE__) #define DEREF(p) Fortran::common::Deref(p, __FILE__, __LINE__)
template<typename T> constexpr T &Deref(T *p, const char *file, int line) { template <typename T> constexpr T &Deref(T *p, const char *file, int line) {
if (!p) { if (!p) {
Fortran::common::die("nullptr dereference at %s(%d)", file, line); Fortran::common::die("nullptr dereference at %s(%d)", file, line);
} }
@ -146,7 +146,7 @@ template<typename T> constexpr T &Deref(T *p, const char *file, int line) {
} }
// Given a const reference to a value, return a copy of the value. // Given a const reference to a value, return a copy of the value.
template<typename A> A Clone(const A &x) { return x; } template <typename A> A Clone(const A &x) { return x; }
// C++ does a weird and dangerous thing when deducing template type parameters // C++ does a weird and dangerous thing when deducing template type parameters
// from function arguments: lvalue references are allowed to match rvalue // from function arguments: lvalue references are allowed to match rvalue
@ -159,8 +159,8 @@ template<typename A> A Clone(const A &x) { return x; }
// or, for constructors, // or, for constructors,
// template<typename A, typename = common::NoLvalue<A>> int foo(A &&); // template<typename A, typename = common::NoLvalue<A>> int foo(A &&);
// This works with parameter packs too. // This works with parameter packs too.
template<typename A, typename... B> template <typename A, typename... B>
using IfNoLvalue = std::enable_if_t<(... && !std::is_lvalue_reference_v<B>), A>; using IfNoLvalue = std::enable_if_t<(... && !std::is_lvalue_reference_v<B>), A>;
template<typename... RVREF> using NoLvalue = IfNoLvalue<void, RVREF...>; template <typename... RVREF> using NoLvalue = IfNoLvalue<void, RVREF...>;
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_IDIOMS_H_ #endif // FORTRAN_COMMON_IDIOMS_H_

View File

@ -28,7 +28,7 @@
namespace Fortran::common { namespace Fortran::common {
// The default case does not support (deep) copy construction or assignment. // The default case does not support (deep) copy construction or assignment.
template<typename A, bool COPY = false> class Indirection { template <typename A, bool COPY = false> class Indirection {
public: public:
using element_type = A; using element_type = A;
Indirection() = delete; Indirection() = delete;
@ -59,7 +59,7 @@ public:
bool operator==(const A &that) const { return *p_ == that; } bool operator==(const A &that) const { return *p_ == that; }
bool operator==(const Indirection &that) const { return *p_ == *that.p_; } bool operator==(const Indirection &that) const { return *p_ == *that.p_; }
template<typename... ARGS> template <typename... ARGS>
static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&... args) { static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&... args) {
return {new A(std::move(args)...)}; return {new A(std::move(args)...)};
} }
@ -69,7 +69,7 @@ private:
}; };
// Variant with copy construction and assignment // Variant with copy construction and assignment
template<typename A> class Indirection<A, true> { template <typename A> class Indirection<A, true> {
public: public:
using element_type = A; using element_type = A;
@ -111,7 +111,7 @@ public:
bool operator==(const A &that) const { return *p_ == that; } bool operator==(const A &that) const { return *p_ == that; }
bool operator==(const Indirection &that) const { return *p_ == *that.p_; } bool operator==(const Indirection &that) const { return *p_ == *that.p_; }
template<typename... ARGS> template <typename... ARGS>
static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&... args) { static common::IfNoLvalue<Indirection, ARGS...> Make(ARGS &&... args) {
return {new A(std::move(args)...)}; return {new A(std::move(args)...)};
} }
@ -120,7 +120,7 @@ private:
A *p_{nullptr}; A *p_{nullptr};
}; };
template<typename A> using CopyableIndirection = Indirection<A, true>; template <typename A> using CopyableIndirection = Indirection<A, true>;
// For use with std::unique_ptr<> when declaring owning pointers to // For use with std::unique_ptr<> when declaring owning pointers to
// forward-referenced types, here's a minimal custom deleter that avoids // forward-referenced types, here's a minimal custom deleter that avoids
@ -129,13 +129,13 @@ template<typename A> using CopyableIndirection = Indirection<A, true>;
// type is visible. Be advised, std::unique_ptr<> does not have copy // type is visible. Be advised, std::unique_ptr<> does not have copy
// semantics; if you need ownership, copy semantics, and nullability, // semantics; if you need ownership, copy semantics, and nullability,
// std::optional<CopyableIndirection<>> works. // std::optional<CopyableIndirection<>> works.
template<typename A> class Deleter { template <typename A> class Deleter {
public: public:
void operator()(A *) const; void operator()(A *) const;
}; };
} } // namespace Fortran::common
#define DEFINE_DELETER(A) \ #define DEFINE_DELETER(A) \
template<> void Fortran::common::Deleter<A>::operator()(A *p) const { \ template <> void Fortran::common::Deleter<A>::operator()(A *p) const { \
delete p; \ delete p; \
} }
#endif // FORTRAN_COMMON_INDIRECTION_H_ #endif // FORTRAN_COMMON_INDIRECTION_H_

View File

@ -19,13 +19,13 @@
namespace Fortran::common { namespace Fortran::common {
template<typename A> class Interval { template <typename A> class Interval {
public: public:
using type = A; using type = A;
constexpr Interval() {} constexpr Interval() {}
constexpr Interval(const A &s, std::size_t n = 1) : start_{s}, size_{n} {} constexpr Interval(const A &s, std::size_t n = 1) : start_{s}, size_{n} {}
constexpr Interval(A &&s, std::size_t n = 1) constexpr Interval(A &&s, std::size_t n = 1)
: start_{std::move(s)}, size_{n} {} : start_{std::move(s)}, size_{n} {}
constexpr Interval(const Interval &) = default; constexpr Interval(const Interval &) = default;
constexpr Interval(Interval &&) = default; constexpr Interval(Interval &&) = default;
constexpr Interval &operator=(const Interval &) = default; constexpr Interval &operator=(const Interval &) = default;
@ -111,5 +111,5 @@ private:
A start_; A start_;
std::size_t size_{0}; std::size_t size_{0};
}; };
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_INTERVAL_H_ #endif // FORTRAN_COMMON_INTERVAL_H_

View File

@ -40,7 +40,7 @@ static constexpr std::uint8_t mapping[64]{63, 0, 58, 1, 59, 47, 53, 2, 60, 39,
48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43,
14, 22, 4, 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 14, 22, 4, 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5}; 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5};
} } // namespace
inline constexpr int LeadingZeroBitCount(std::uint64_t x) { inline constexpr int LeadingZeroBitCount(std::uint64_t x) {
if (x == 0) { if (x == 0) {
@ -53,13 +53,13 @@ inline constexpr int LeadingZeroBitCount(std::uint64_t x) {
x |= x >> 16; x |= x >> 16;
x |= x >> 32; x |= x >> 32;
// All of the bits below the uppermost set bit are now also set. // All of the bits below the uppermost set bit are now also set.
x -= x >> 1; // All of the bits below the uppermost are now clear. x -= x >> 1; // All of the bits below the uppermost are now clear.
// x now has exactly one bit set, so it is a power of two, so // x now has exactly one bit set, so it is a power of two, so
// multiplication by x is equivalent to a left shift by its // multiplication by x is equivalent to a left shift by its
// base-2 logarithm. We calculate that unknown base-2 logarithm // base-2 logarithm. We calculate that unknown base-2 logarithm
// by shifting the deBruijn sequence and mapping the framed value. // by shifting the deBruijn sequence and mapping the framed value.
int base2Log{mapping[(x * deBruijn) >> 58]}; int base2Log{mapping[(x * deBruijn) >> 58]};
return 63 - base2Log; // convert to leading zero count return 63 - base2Log; // convert to leading zero count
} }
} }
@ -89,8 +89,8 @@ inline constexpr int LeadingZeroBitCount(std::uint8_t x) {
return eightBitLeadingZeroBitCount[x]; return eightBitLeadingZeroBitCount[x];
} }
template<typename A> inline constexpr int BitsNeededFor(A x) { template <typename A> inline constexpr int BitsNeededFor(A x) {
return 8 * sizeof x - LeadingZeroBitCount(x); return 8 * sizeof x - LeadingZeroBitCount(x);
} }
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_LEADING_ZERO_BIT_COUNT_H_ #endif // FORTRAN_COMMON_LEADING_ZERO_BIT_COUNT_H_

View File

@ -20,14 +20,22 @@ namespace Fortran::common {
// Total representation size in bits for each type // Total representation size in bits for each type
static constexpr int BitsForBinaryPrecision(int binaryPrecision) { static constexpr int BitsForBinaryPrecision(int binaryPrecision) {
switch (binaryPrecision) { switch (binaryPrecision) {
case 8: return 16; // IEEE single (truncated): 1+8+7 case 8:
case 11: return 16; // IEEE half precision: 1+5+10 return 16; // IEEE single (truncated): 1+8+7
case 24: return 32; // IEEE single precision: 1+8+23 case 11:
case 53: return 64; // IEEE double precision: 1+11+52 return 16; // IEEE half precision: 1+5+10
case 64: return 80; // x87 extended precision: 1+15+64 case 24:
case 106: return 128; // "double-double": 2*(1+11+52) return 32; // IEEE single precision: 1+8+23
case 113: return 128; // IEEE quad precision: 1+15+112 case 53:
default: return -1; return 64; // IEEE double precision: 1+11+52
case 64:
return 80; // x87 extended precision: 1+15+64
case 106:
return 128; // "double-double": 2*(1+11+52)
case 113:
return 128; // IEEE quad precision: 1+15+112
default:
return -1;
} }
} }
@ -37,18 +45,26 @@ static constexpr int BitsForBinaryPrecision(int binaryPrecision) {
// exactly with FORMAT(E0.22981). // exactly with FORMAT(E0.22981).
static constexpr int MaxDecimalConversionDigits(int binaryPrecision) { static constexpr int MaxDecimalConversionDigits(int binaryPrecision) {
switch (binaryPrecision) { switch (binaryPrecision) {
case 8: return 93; case 8:
case 11: return 17; return 93;
case 24: return 105; case 11:
case 53: return 751; return 17;
case 64: return 11495; case 24:
case 106: return 2 * 751; return 105;
case 113: return 11530; case 53:
default: return -1; return 751;
case 64:
return 11495;
case 106:
return 2 * 751;
case 113:
return 11530;
default:
return -1;
} }
} }
template<int BINARY_PRECISION> class RealDetails { template <int BINARY_PRECISION> class RealDetails {
private: private:
// Converts bit widths to whole decimal digits // Converts bit widths to whole decimal digits
static constexpr int LogBaseTwoToLogBaseTen(int logb2) { static constexpr int LogBaseTwoToLogBaseTen(int logb2) {
@ -82,5 +98,5 @@ public:
static_assert(exponentBits <= 15); static_assert(exponentBits <= 15);
}; };
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_REAL_H_ #endif // FORTRAN_COMMON_REAL_H_

View File

@ -16,7 +16,7 @@
namespace Fortran::common { namespace Fortran::common {
// A base class for reference-counted objects. Must be public. // A base class for reference-counted objects. Must be public.
template<typename A> class ReferenceCounted { template <typename A> class ReferenceCounted {
public: public:
ReferenceCounted() {} ReferenceCounted() {}
void TakeReference() { ++references_; } void TakeReference() { ++references_; }
@ -31,7 +31,7 @@ private:
}; };
// A reference to a reference-counted object. // A reference to a reference-counted object.
template<typename A> class CountedReference { template <typename A> class CountedReference {
public: public:
using type = A; using type = A;
CountedReference() {} CountedReference() {}
@ -72,5 +72,5 @@ private:
type *p_{nullptr}; type *p_{nullptr};
}; };
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_REFERENCE_COUNTED_H_ #endif // FORTRAN_COMMON_REFERENCE_COUNTED_H_

View File

@ -15,7 +15,7 @@
#define FORTRAN_COMMON_REFERENCE_H_ #define FORTRAN_COMMON_REFERENCE_H_
#include <type_traits> #include <type_traits>
namespace Fortran::common { namespace Fortran::common {
template<typename A> class Reference { template <typename A> class Reference {
public: public:
using type = A; using type = A;
Reference(type &x) : p_{&x} {} Reference(type &x) : p_{&x} {}
@ -35,8 +35,8 @@ public:
// creation of a temporary copy in cases like: // creation of a temporary copy in cases like:
// Reference<type> ref; // Reference<type> ref;
// const Type &x{ref}; // creates ref to temp copy! // const Type &x{ref}; // creates ref to temp copy!
operator std::conditional_t<std::is_const_v<type>, type &, void>() const operator std::conditional_t<std::is_const_v<type>, type &, void>()
noexcept { const noexcept {
if constexpr (std::is_const_v<type>) { if constexpr (std::is_const_v<type>) {
return *p_; return *p_;
} }
@ -56,8 +56,8 @@ public:
bool operator!=(const Reference &that) const { return !(*this == that); } bool operator!=(const Reference &that) const { return !(*this == that); }
private: private:
type *p_; // never null type *p_; // never null
}; };
template<typename A> Reference(A &)->Reference<A>; template <typename A> Reference(A &) -> Reference<A>;
} } // namespace Fortran::common
#endif #endif

View File

@ -20,7 +20,7 @@
#define FORTRAN_COMMON_RESTORER_H_ #define FORTRAN_COMMON_RESTORER_H_
#include "idioms.h" #include "idioms.h"
namespace Fortran::common { namespace Fortran::common {
template<typename A> class Restorer { template <typename A> class Restorer {
public: public:
explicit Restorer(A &p) : p_{p}, original_{std::move(p)} {} explicit Restorer(A &p) : p_{p}, original_{std::move(p)} {}
~Restorer() { p_ = std::move(original_); } ~Restorer() { p_ = std::move(original_); }
@ -30,17 +30,17 @@ private:
A original_; A original_;
}; };
template<typename A, typename B> template <typename A, typename B>
common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, B &&from) { common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, B &&from) {
Restorer<A> result{to}; Restorer<A> result{to};
to = std::move(from); to = std::move(from);
return result; return result;
} }
template<typename A, typename B> template <typename A, typename B>
common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, const B &from) { common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, const B &from) {
Restorer<A> result{to}; Restorer<A> result{to};
to = from; to = from;
return result; return result;
} }
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_RESTORER_H_ #endif // FORTRAN_COMMON_RESTORER_H_

View File

@ -26,7 +26,7 @@ namespace Fortran::common {
// index of the first type T in the list for which PREDICATE<T>::value() is // index of the first type T in the list for which PREDICATE<T>::value() is
// true is returned, or -1 if the predicate is false for every type in the list. // true is returned, or -1 if the predicate is false for every type in the list.
// This is a compile-time operation; see SearchTypes below for a run-time form. // This is a compile-time operation; see SearchTypes below for a run-time form.
template<int N, template<typename> class PREDICATE, typename TUPLE> template <int N, template <typename> class PREDICATE, typename TUPLE>
struct SearchTypeListHelper { struct SearchTypeListHelper {
static constexpr int value() { static constexpr int value() {
if constexpr (N >= std::tuple_size_v<TUPLE>) { if constexpr (N >= std::tuple_size_v<TUPLE>) {
@ -39,41 +39,41 @@ struct SearchTypeListHelper {
} }
}; };
template<template<typename> class PREDICATE, typename... TYPES> template <template <typename> class PREDICATE, typename... TYPES>
constexpr int SearchTypeList{ constexpr int SearchTypeList{
SearchTypeListHelper<0, PREDICATE, std::tuple<TYPES...>>::value()}; SearchTypeListHelper<0, PREDICATE, std::tuple<TYPES...>>::value()};
// TypeIndex<A, TYPES...> scans a list of types for simple type equality. // TypeIndex<A, TYPES...> scans a list of types for simple type equality.
// The zero-based index of A in the list is returned, or -1 if A is not present. // The zero-based index of A in the list is returned, or -1 if A is not present.
template<typename A> struct MatchType { template <typename A> struct MatchType {
template<typename B> struct Match { template <typename B> struct Match {
static constexpr bool value() { static constexpr bool value() {
return std::is_same_v<std::decay_t<A>, std::decay_t<B>>; return std::is_same_v<std::decay_t<A>, std::decay_t<B>>;
} }
}; };
}; };
template<typename A, typename... TYPES> template <typename A, typename... TYPES>
constexpr int TypeIndex{SearchTypeList<MatchType<A>::template Match, TYPES...>}; constexpr int TypeIndex{SearchTypeList<MatchType<A>::template Match, TYPES...>};
// IsTypeInList<A, TYPES...> is a simple presence predicate. // IsTypeInList<A, TYPES...> is a simple presence predicate.
template<typename A, typename... TYPES> template <typename A, typename... TYPES>
constexpr bool IsTypeInList{TypeIndex<A, TYPES...> >= 0}; constexpr bool IsTypeInList{TypeIndex<A, TYPES...> >= 0};
// OverMembers extracts the list of types that constitute the alternatives // OverMembers extracts the list of types that constitute the alternatives
// of a std::variant or elements of a std::tuple and passes that list as // of a std::variant or elements of a std::tuple and passes that list as
// parameter types to a given variadic template. // parameter types to a given variadic template.
template<template<typename...> class, typename> struct OverMembersHelper; template <template <typename...> class, typename> struct OverMembersHelper;
template<template<typename...> class T, typename... Ts> template <template <typename...> class T, typename... Ts>
struct OverMembersHelper<T, std::variant<Ts...>> { struct OverMembersHelper<T, std::variant<Ts...>> {
using type = T<Ts...>; using type = T<Ts...>;
}; };
template<template<typename...> class T, typename... Ts> template <template <typename...> class T, typename... Ts>
struct OverMembersHelper<T, std::tuple<Ts...>> { struct OverMembersHelper<T, std::tuple<Ts...>> {
using type = T<Ts...>; using type = T<Ts...>;
}; };
template<template<typename...> class T, typename TUPLEorVARIANT> template <template <typename...> class T, typename TUPLEorVARIANT>
using OverMembers = using OverMembers =
typename OverMembersHelper<T, std::decay_t<TUPLEorVARIANT>>::type; typename OverMembersHelper<T, std::decay_t<TUPLEorVARIANT>>::type;
@ -82,23 +82,23 @@ using OverMembers =
// The zero-based index of the first type T among the alternatives for which // The zero-based index of the first type T among the alternatives for which
// PREDICATE<T>::value() is true is returned, or -1 when the predicate is false // PREDICATE<T>::value() is true is returned, or -1 when the predicate is false
// for every type in the set. // for every type in the set.
template<template<typename> class PREDICATE> struct SearchMembersHelper { template <template <typename> class PREDICATE> struct SearchMembersHelper {
template<typename... Ts> struct Scanner { template <typename... Ts> struct Scanner {
static constexpr int value() { return SearchTypeList<PREDICATE, Ts...>; } static constexpr int value() { return SearchTypeList<PREDICATE, Ts...>; }
}; };
}; };
template<template<typename> class PREDICATE, typename TUPLEorVARIANT> template <template <typename> class PREDICATE, typename TUPLEorVARIANT>
constexpr int SearchMembers{ constexpr int SearchMembers{
OverMembers<SearchMembersHelper<PREDICATE>::template Scanner, OverMembers<SearchMembersHelper<PREDICATE>::template Scanner,
TUPLEorVARIANT>::value()}; TUPLEorVARIANT>::value()};
template<typename A, typename TUPLEorVARIANT> template <typename A, typename TUPLEorVARIANT>
constexpr bool HasMember{ constexpr bool HasMember{
SearchMembers<MatchType<A>::template Match, TUPLEorVARIANT> >= 0}; SearchMembers<MatchType<A>::template Match, TUPLEorVARIANT> >= 0};
// std::optional<std::optional<A>> -> std::optional<A> // std::optional<std::optional<A>> -> std::optional<A>
template<typename A> template <typename A>
std::optional<A> JoinOptional(std::optional<std::optional<A>> &&x) { std::optional<A> JoinOptional(std::optional<std::optional<A>> &&x) {
if (x) { if (x) {
return std::move(*x); return std::move(*x);
@ -107,7 +107,7 @@ std::optional<A> JoinOptional(std::optional<std::optional<A>> &&x) {
} }
// Convert an std::optional to an ordinary pointer // Convert an std::optional to an ordinary pointer
template<typename A> const A *GetPtrFromOptional(const std::optional<A> &x) { template <typename A> const A *GetPtrFromOptional(const std::optional<A> &x) {
if (x) { if (x) {
return &*x; return &*x;
} else { } else {
@ -117,13 +117,13 @@ template<typename A> const A *GetPtrFromOptional(const std::optional<A> &x) {
// Copy a value from one variant type to another. The types allowed in the // Copy a value from one variant type to another. The types allowed in the
// source variant must all be allowed in the destination variant type. // source variant must all be allowed in the destination variant type.
template<typename TOV, typename FROMV> TOV CopyVariant(const FROMV &u) { template <typename TOV, typename FROMV> TOV CopyVariant(const FROMV &u) {
return std::visit([](const auto &x) -> TOV { return {x}; }, u); return std::visit([](const auto &x) -> TOV { return {x}; }, u);
} }
// Move a value from one variant type to another. The types allowed in the // Move a value from one variant type to another. The types allowed in the
// source variant must all be allowed in the destination variant type. // source variant must all be allowed in the destination variant type.
template<typename TOV, typename FROMV> template <typename TOV, typename FROMV>
common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) { common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) {
return std::visit( return std::visit(
[](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u)); [](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u));
@ -134,26 +134,26 @@ common::IfNoLvalue<TOV, FROMV> MoveVariant(FROMV &&u) {
// types. E.g., // types. E.g.,
// CombineTuples<std::tuple<char, int>, std::tuple<float, double>> // CombineTuples<std::tuple<char, int>, std::tuple<float, double>>
// is std::tuple<char, int, float, double>. // is std::tuple<char, int, float, double>.
template<typename... TUPLES> struct CombineTuplesHelper { template <typename... TUPLES> struct CombineTuplesHelper {
static decltype(auto) f(TUPLES *... a) { static decltype(auto) f(TUPLES *... a) {
return std::tuple_cat(std::move(*a)...); return std::tuple_cat(std::move(*a)...);
} }
using type = decltype(f(static_cast<TUPLES *>(nullptr)...)); using type = decltype(f(static_cast<TUPLES *>(nullptr)...));
}; };
template<typename... TUPLES> template <typename... TUPLES>
using CombineTuples = typename CombineTuplesHelper<TUPLES...>::type; using CombineTuples = typename CombineTuplesHelper<TUPLES...>::type;
// CombineVariants takes a list of std::variant<> instantiations and constructs // CombineVariants takes a list of std::variant<> instantiations and constructs
// a new instantiation that holds all of their alternatives, which must be // a new instantiation that holds all of their alternatives, which must be
// pairwise distinct. // pairwise distinct.
template<typename> struct VariantToTupleHelper; template <typename> struct VariantToTupleHelper;
template<typename... Ts> struct VariantToTupleHelper<std::variant<Ts...>> { template <typename... Ts> struct VariantToTupleHelper<std::variant<Ts...>> {
using type = std::tuple<Ts...>; using type = std::tuple<Ts...>;
}; };
template<typename VARIANT> template <typename VARIANT>
using VariantToTuple = typename VariantToTupleHelper<VARIANT>::type; using VariantToTuple = typename VariantToTupleHelper<VARIANT>::type;
template<typename A, typename... REST> struct AreTypesDistinctHelper { template <typename A, typename... REST> struct AreTypesDistinctHelper {
static constexpr bool value() { static constexpr bool value() {
if constexpr (sizeof...(REST) > 0) { if constexpr (sizeof...(REST) > 0) {
// extra () for clang-format // extra () for clang-format
@ -163,10 +163,10 @@ template<typename A, typename... REST> struct AreTypesDistinctHelper {
return true; return true;
} }
}; };
template<typename... Ts> template <typename... Ts>
constexpr bool AreTypesDistinct{AreTypesDistinctHelper<Ts...>::value()}; constexpr bool AreTypesDistinct{AreTypesDistinctHelper<Ts...>::value()};
template<typename A, typename... Ts> struct AreSameTypeHelper { template <typename A, typename... Ts> struct AreSameTypeHelper {
using type = A; using type = A;
static constexpr bool value() { static constexpr bool value() {
if constexpr (sizeof...(Ts) == 0) { if constexpr (sizeof...(Ts) == 0) {
@ -178,53 +178,53 @@ template<typename A, typename... Ts> struct AreSameTypeHelper {
} }
}; };
template<typename... Ts> template <typename... Ts>
constexpr bool AreSameType{AreSameTypeHelper<Ts...>::value()}; constexpr bool AreSameType{AreSameTypeHelper<Ts...>::value()};
template<typename> struct TupleToVariantHelper; template <typename> struct TupleToVariantHelper;
template<typename... Ts> struct TupleToVariantHelper<std::tuple<Ts...>> { template <typename... Ts> struct TupleToVariantHelper<std::tuple<Ts...>> {
static_assert(AreTypesDistinct<Ts...>, static_assert(AreTypesDistinct<Ts...>,
"TupleToVariant: types are not pairwise distinct"); "TupleToVariant: types are not pairwise distinct");
using type = std::variant<Ts...>; using type = std::variant<Ts...>;
}; };
template<typename TUPLE> template <typename TUPLE>
using TupleToVariant = typename TupleToVariantHelper<TUPLE>::type; using TupleToVariant = typename TupleToVariantHelper<TUPLE>::type;
template<typename... VARIANTS> struct CombineVariantsHelper { template <typename... VARIANTS> struct CombineVariantsHelper {
using type = TupleToVariant<CombineTuples<VariantToTuple<VARIANTS>...>>; using type = TupleToVariant<CombineTuples<VariantToTuple<VARIANTS>...>>;
}; };
template<typename... VARIANTS> template <typename... VARIANTS>
using CombineVariants = typename CombineVariantsHelper<VARIANTS...>::type; using CombineVariants = typename CombineVariantsHelper<VARIANTS...>::type;
// SquashVariantOfVariants: given a std::variant whose alternatives are // SquashVariantOfVariants: given a std::variant whose alternatives are
// all std::variant instantiations, form a new union over their alternatives. // all std::variant instantiations, form a new union over their alternatives.
template<typename VARIANT> template <typename VARIANT>
using SquashVariantOfVariants = OverMembers<CombineVariants, VARIANT>; using SquashVariantOfVariants = OverMembers<CombineVariants, VARIANT>;
// Given a type function, MapTemplate applies it to each of the types // Given a type function, MapTemplate applies it to each of the types
// in a tuple or variant, and collect the results in a given variadic // in a tuple or variant, and collect the results in a given variadic
// template (typically a std::variant). // template (typically a std::variant).
template<template<typename> class, template<typename...> class, typename...> template <template <typename> class, template <typename...> class, typename...>
struct MapTemplateHelper; struct MapTemplateHelper;
template<template<typename> class F, template<typename...> class PACKAGE, template <template <typename> class F, template <typename...> class PACKAGE,
typename... Ts> typename... Ts>
struct MapTemplateHelper<F, PACKAGE, std::tuple<Ts...>> { struct MapTemplateHelper<F, PACKAGE, std::tuple<Ts...>> {
using type = PACKAGE<F<Ts>...>; using type = PACKAGE<F<Ts>...>;
}; };
template<template<typename> class F, template<typename...> class PACKAGE, template <template <typename> class F, template <typename...> class PACKAGE,
typename... Ts> typename... Ts>
struct MapTemplateHelper<F, PACKAGE, std::variant<Ts...>> { struct MapTemplateHelper<F, PACKAGE, std::variant<Ts...>> {
using type = PACKAGE<F<Ts>...>; using type = PACKAGE<F<Ts>...>;
}; };
template<template<typename> class F, typename TUPLEorVARIANT, template <template <typename> class F, typename TUPLEorVARIANT,
template<typename...> class PACKAGE = std::variant> template <typename...> class PACKAGE = std::variant>
using MapTemplate = using MapTemplate =
typename MapTemplateHelper<F, PACKAGE, TUPLEorVARIANT>::type; typename MapTemplateHelper<F, PACKAGE, TUPLEorVARIANT>::type;
// std::tuple<std::optional<>...> -> std::optional<std::tuple<...>> // std::tuple<std::optional<>...> -> std::optional<std::tuple<...>>
// i.e., inverts a tuple of optional values into an optional tuple that has // i.e., inverts a tuple of optional values into an optional tuple that has
// a value only if all of the original elements were present. // a value only if all of the original elements were present.
template<typename... A, std::size_t... J> template <typename... A, std::size_t... J>
std::optional<std::tuple<A...>> AllElementsPresentHelper( std::optional<std::tuple<A...>> AllElementsPresentHelper(
std::tuple<std::optional<A>...> &&t, std::index_sequence<J...>) { std::tuple<std::optional<A>...> &&t, std::index_sequence<J...>) {
bool present[]{std::get<J>(t).has_value()...}; bool present[]{std::get<J>(t).has_value()...};
@ -236,7 +236,7 @@ std::optional<std::tuple<A...>> AllElementsPresentHelper(
return {std::make_tuple(*std::get<J>(t)...)}; return {std::make_tuple(*std::get<J>(t)...)};
} }
template<typename... A> template <typename... A>
std::optional<std::tuple<A...>> AllElementsPresent( std::optional<std::tuple<A...>> AllElementsPresent(
std::tuple<std::optional<A>...> &&t) { std::tuple<std::optional<A>...> &&t) {
return AllElementsPresentHelper( return AllElementsPresentHelper(
@ -246,7 +246,7 @@ std::optional<std::tuple<A...>> AllElementsPresent(
// std::vector<std::optional<A>> -> std::optional<std::vector<A>> // std::vector<std::optional<A>> -> std::optional<std::vector<A>>
// i.e., inverts a vector of optional values into an optional vector that // i.e., inverts a vector of optional values into an optional vector that
// will have a value only when all of the original elements are present. // will have a value only when all of the original elements are present.
template<typename A> template <typename A>
std::optional<std::vector<A>> AllElementsPresent( std::optional<std::vector<A>> AllElementsPresent(
std::vector<std::optional<A>> &&v) { std::vector<std::optional<A>> &&v) {
for (const auto &maybeA : v) { for (const auto &maybeA : v) {
@ -264,7 +264,7 @@ std::optional<std::vector<A>> AllElementsPresent(
// (std::optional<>...) -> std::optional<std::tuple<...>> // (std::optional<>...) -> std::optional<std::tuple<...>>
// i.e., given some number of optional values, return a optional tuple of // i.e., given some number of optional values, return a optional tuple of
// those values that is present only of all of the values were so. // those values that is present only of all of the values were so.
template<typename... A> template <typename... A>
std::optional<std::tuple<A...>> AllPresent(std::optional<A> &&... x) { std::optional<std::tuple<A...>> AllPresent(std::optional<A> &&... x) {
return AllElementsPresent(std::make_tuple(std::move(x)...)); return AllElementsPresent(std::make_tuple(std::move(x)...));
} }
@ -274,7 +274,7 @@ std::optional<std::tuple<A...>> AllPresent(std::optional<A> &&... x) {
// N.B. If the function returns std::optional, MapOptional will return // N.B. If the function returns std::optional, MapOptional will return
// std::optional<std::optional<...>> and you will probably want to // std::optional<std::optional<...>> and you will probably want to
// run it through JoinOptional to "squash" it. // run it through JoinOptional to "squash" it.
template<typename R, typename... A> template <typename R, typename... A>
std::optional<R> MapOptional( std::optional<R> MapOptional(
std::function<R(A &&...)> &&f, std::optional<A> &&... x) { std::function<R(A &&...)> &&f, std::optional<A> &&... x) {
if (auto args{AllPresent(std::move(x)...)}) { if (auto args{AllPresent(std::move(x)...)}) {
@ -282,7 +282,7 @@ std::optional<R> MapOptional(
} }
return std::nullopt; return std::nullopt;
} }
template<typename R, typename... A> template <typename R, typename... A>
std::optional<R> MapOptional(R (*f)(A &&...), std::optional<A> &&... x) { std::optional<R> MapOptional(R (*f)(A &&...), std::optional<A> &&... x) {
return MapOptional(std::function<R(A && ...)>{f}, std::move(x)...); return MapOptional(std::function<R(A && ...)>{f}, std::move(x)...);
} }
@ -297,7 +297,7 @@ std::optional<R> MapOptional(R (*f)(A &&...), std::optional<A> &&... x) {
// and invoke VISITOR::Test<T>() on each until it returns a value that // and invoke VISITOR::Test<T>() on each until it returns a value that
// casts to true. If no invocation of Test succeeds, SearchTypes will // casts to true. If no invocation of Test succeeds, SearchTypes will
// return a default value. // return a default value.
template<std::size_t J, typename VISITOR> template <std::size_t J, typename VISITOR>
common::IfNoLvalue<typename VISITOR::Result, VISITOR> SearchTypesHelper( common::IfNoLvalue<typename VISITOR::Result, VISITOR> SearchTypesHelper(
VISITOR &&visitor, typename VISITOR::Result &&defaultResult) { VISITOR &&visitor, typename VISITOR::Result &&defaultResult) {
using Tuple = typename VISITOR::Types; using Tuple = typename VISITOR::Types;
@ -312,12 +312,12 @@ common::IfNoLvalue<typename VISITOR::Result, VISITOR> SearchTypesHelper(
} }
} }
template<typename VISITOR> template <typename VISITOR>
common::IfNoLvalue<typename VISITOR::Result, VISITOR> SearchTypes( common::IfNoLvalue<typename VISITOR::Result, VISITOR> SearchTypes(
VISITOR &&visitor, VISITOR &&visitor,
typename VISITOR::Result defaultResult = typename VISITOR::Result{}) { typename VISITOR::Result defaultResult = typename VISITOR::Result{}) {
return SearchTypesHelper<0, VISITOR>( return SearchTypesHelper<0, VISITOR>(
std::move(visitor), std::move(defaultResult)); std::move(visitor), std::move(defaultResult));
} }
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_TEMPLATE_H_ #endif // FORTRAN_COMMON_TEMPLATE_H_

View File

@ -13,7 +13,7 @@
#define FORTRAN_COMMON_UINT128_H_ #define FORTRAN_COMMON_UINT128_H_
#ifndef AVOID_NATIVE_UINT128_T #ifndef AVOID_NATIVE_UINT128_T
#define AVOID_NATIVE_UINT128_T 1 // always use this code for now for testing #define AVOID_NATIVE_UINT128_T 1 // always use this code for now for testing
#endif #endif
#include "leading-zero-bit-count.h" #include "leading-zero-bit-count.h"
@ -31,14 +31,14 @@ public:
constexpr UnsignedInt128(unsigned long n) : low_{n} {} constexpr UnsignedInt128(unsigned long n) : low_{n} {}
constexpr UnsignedInt128(unsigned long long n) : low_{n} {} constexpr UnsignedInt128(unsigned long long n) : low_{n} {}
constexpr UnsignedInt128(int n) constexpr UnsignedInt128(int n)
: low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>( : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
n < 0)} {} n < 0)} {}
constexpr UnsignedInt128(long n) constexpr UnsignedInt128(long n)
: low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>( : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
n < 0)} {} n < 0)} {}
constexpr UnsignedInt128(long long n) constexpr UnsignedInt128(long long n)
: low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>( : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
n < 0)} {} n < 0)} {}
constexpr UnsignedInt128(const UnsignedInt128 &) = default; constexpr UnsignedInt128(const UnsignedInt128 &) = default;
constexpr UnsignedInt128(UnsignedInt128 &&) = default; constexpr UnsignedInt128(UnsignedInt128 &&) = default;
constexpr UnsignedInt128 &operator=(const UnsignedInt128 &) = default; constexpr UnsignedInt128 &operator=(const UnsignedInt128 &) = default;
@ -241,7 +241,7 @@ public:
private: private:
constexpr UnsignedInt128(std::uint64_t hi, std::uint64_t lo) constexpr UnsignedInt128(std::uint64_t hi, std::uint64_t lo)
: low_{lo}, high_{hi} {} : low_{lo}, high_{hi} {}
constexpr int LeadingZeroes() const { constexpr int LeadingZeroes() const {
if (high_ == 0) { if (high_ == 0) {
return 64 + LeadingZeroBitCount(low_); return 64 + LeadingZeroBitCount(low_);
@ -261,14 +261,14 @@ using uint128_t = __uint128_t;
using uint128_t = UnsignedInt128; using uint128_t = UnsignedInt128;
#endif #endif
template<int BITS> struct HostUnsignedIntTypeHelper { template <int BITS> struct HostUnsignedIntTypeHelper {
using type = std::conditional_t<(BITS <= 8), std::uint8_t, using type = std::conditional_t<(BITS <= 8), std::uint8_t,
std::conditional_t<(BITS <= 16), std::uint16_t, std::conditional_t<(BITS <= 16), std::uint16_t,
std::conditional_t<(BITS <= 32), std::uint32_t, std::conditional_t<(BITS <= 32), std::uint32_t,
std::conditional_t<(BITS <= 64), std::uint64_t, uint128_t>>>>; std::conditional_t<(BITS <= 64), std::uint64_t, uint128_t>>>>;
}; };
template<int BITS> template <int BITS>
using HostUnsignedIntType = typename HostUnsignedIntTypeHelper<BITS>::type; using HostUnsignedIntType = typename HostUnsignedIntTypeHelper<BITS>::type;
} } // namespace Fortran::common
#endif #endif

View File

@ -22,7 +22,7 @@
namespace Fortran::common { namespace Fortran::common {
template<typename UINT> class FixedPointReciprocal { template <typename UINT> class FixedPointReciprocal {
public: public:
using type = UINT; using type = UINT;
@ -36,7 +36,7 @@ public:
static constexpr FixedPointReciprocal For(type n) { static constexpr FixedPointReciprocal For(type n) {
if (n == 0) { if (n == 0) {
return {0, 0}; return {0, 0};
} else if ((n & (n - 1)) == 0) { // n is a power of two } else if ((n & (n - 1)) == 0) { // n is a power of two
return {TrailingZeroBitCount(n), 1}; return {TrailingZeroBitCount(n), 1};
} else { } else {
int shift{bits - 1 + BitsNeededFor(n)}; int shift{bits - 1 + BitsNeededFor(n)};
@ -60,7 +60,7 @@ static_assert(FixedPointReciprocal<std::uint32_t>::For(5).Divide(2000000000u) ==
static_assert(FixedPointReciprocal<std::uint64_t>::For(10).Divide( static_assert(FixedPointReciprocal<std::uint64_t>::For(10).Divide(
10000000000000000u) == 1000000000000000u); 10000000000000000u) == 1000000000000000u);
template<typename UINT, std::uint64_t DENOM> template <typename UINT, std::uint64_t DENOM>
inline constexpr UINT DivideUnsignedBy(UINT n) { inline constexpr UINT DivideUnsignedBy(UINT n) {
if constexpr (std::is_same_v<UINT, uint128_t>) { if constexpr (std::is_same_v<UINT, uint128_t>) {
return n / static_cast<UINT>(DENOM); return n / static_cast<UINT>(DENOM);
@ -73,5 +73,5 @@ inline constexpr UINT DivideUnsignedBy(UINT n) {
return recip.Divide(n); return recip.Divide(n);
} }
} }
} } // namespace Fortran::common
#endif #endif

View File

@ -37,7 +37,7 @@
namespace Fortran::common { namespace Fortran::common {
// Utility: Produces "const A" if B is const and A is not already so. // Utility: Produces "const A" if B is const and A is not already so.
template<typename A, typename B> template <typename A, typename B>
using Constify = std::conditional_t<std::is_const_v<B> && !std::is_const_v<A>, using Constify = std::conditional_t<std::is_const_v<B> && !std::is_const_v<A>,
std::add_const_t<A>, A>; std::add_const_t<A>, A>;
@ -46,7 +46,7 @@ using Constify = std::conditional_t<std::is_const_v<B> && !std::is_const_v<A>,
struct UnwrapperHelper { struct UnwrapperHelper {
// Base case // Base case
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(B &x) -> Constify<A, B> * { static auto Unwrap(B &x) -> Constify<A, B> * {
if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) { if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) {
return &x; return &x;
@ -56,7 +56,7 @@ struct UnwrapperHelper {
} }
// Implementations of specializations // Implementations of specializations
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(B *p) -> Constify<A, B> * { static auto Unwrap(B *p) -> Constify<A, B> * {
if (p) { if (p) {
return Unwrap<A>(*p); return Unwrap<A>(*p);
@ -65,7 +65,7 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(const std::unique_ptr<B> &p) -> Constify<A, B> * { static auto Unwrap(const std::unique_ptr<B> &p) -> Constify<A, B> * {
if (p.get()) { if (p.get()) {
return Unwrap<A>(*p); return Unwrap<A>(*p);
@ -74,7 +74,7 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(const std::shared_ptr<B> &p) -> Constify<A, B> * { static auto Unwrap(const std::shared_ptr<B> &p) -> Constify<A, B> * {
if (p.get()) { if (p.get()) {
return Unwrap<A>(*p); return Unwrap<A>(*p);
@ -83,7 +83,7 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(std::optional<B> &x) -> Constify<A, B> * { static auto Unwrap(std::optional<B> &x) -> Constify<A, B> * {
if (x) { if (x) {
return Unwrap<A>(*x); return Unwrap<A>(*x);
@ -92,7 +92,7 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(const std::optional<B> &x) -> Constify<A, B> * { static auto Unwrap(const std::optional<B> &x) -> Constify<A, B> * {
if (x) { if (x) {
return Unwrap<A>(*x); return Unwrap<A>(*x);
@ -101,7 +101,7 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename... Bs> template <typename A, typename... Bs>
static A *Unwrap(std::variant<Bs...> &u) { static A *Unwrap(std::variant<Bs...> &u) {
return std::visit( return std::visit(
[](auto &x) -> A * { [](auto &x) -> A * {
@ -115,23 +115,23 @@ struct UnwrapperHelper {
u); u);
} }
template<typename A, typename... Bs> template <typename A, typename... Bs>
static auto Unwrap(const std::variant<Bs...> &u) -> std::add_const_t<A> * { static auto Unwrap(const std::variant<Bs...> &u) -> std::add_const_t<A> * {
return std::visit( return std::visit(
[](const auto &x) -> std::add_const_t<A> * { return Unwrap<A>(x); }, u); [](const auto &x) -> std::add_const_t<A> * { return Unwrap<A>(x); }, u);
} }
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(const Reference<B> &ref) -> Constify<A, B> * { static auto Unwrap(const Reference<B> &ref) -> Constify<A, B> * {
return Unwrap<A>(*ref); return Unwrap<A>(*ref);
} }
template<typename A, typename B, bool COPY> template <typename A, typename B, bool COPY>
static auto Unwrap(const Indirection<B, COPY> &p) -> Constify<A, B> * { static auto Unwrap(const Indirection<B, COPY> &p) -> Constify<A, B> * {
return Unwrap<A>(*p); return Unwrap<A>(*p);
} }
template<typename A, typename B> template <typename A, typename B>
static auto Unwrap(const CountedReference<B> &p) -> Constify<A, B> * { static auto Unwrap(const CountedReference<B> &p) -> Constify<A, B> * {
if (p.get()) { if (p.get()) {
return Unwrap<A>(*p); return Unwrap<A>(*p);
@ -141,17 +141,17 @@ struct UnwrapperHelper {
} }
}; };
template<typename A, typename B> auto Unwrap(B &x) -> Constify<A, B> * { template <typename A, typename B> auto Unwrap(B &x) -> Constify<A, B> * {
return UnwrapperHelper::Unwrap<A>(x); return UnwrapperHelper::Unwrap<A>(x);
} }
// Returns a copy of a wrapped value, if present, otherwise a vacant optional. // Returns a copy of a wrapped value, if present, otherwise a vacant optional.
template<typename A, typename B> std::optional<A> UnwrapCopy(const B &x) { template <typename A, typename B> std::optional<A> UnwrapCopy(const B &x) {
if (const A * p{Unwrap<A>(x)}) { if (const A * p{Unwrap<A>(x)}) {
return std::make_optional<A>(*p); return std::make_optional<A>(*p);
} else { } else {
return std::nullopt; return std::nullopt;
} }
} }
} } // namespace Fortran::common
#endif // FORTRAN_COMMON_UNWRAP_H_ #endif // FORTRAN_COMMON_UNWRAP_H_

View File

@ -21,9 +21,9 @@
namespace Fortran::decimal { namespace Fortran::decimal {
template<int BINARY_PRECISION> template <int BINARY_PRECISION>
struct BinaryFloatingPointNumber struct BinaryFloatingPointNumber
: public common::RealDetails<BINARY_PRECISION> { : public common::RealDetails<BINARY_PRECISION> {
using Details = common::RealDetails<BINARY_PRECISION>; using Details = common::RealDetails<BINARY_PRECISION>;
using Details::bits; using Details::bits;
@ -40,7 +40,7 @@ struct BinaryFloatingPointNumber
static_assert(CHAR_BIT * sizeof(RawType) >= bits); static_assert(CHAR_BIT * sizeof(RawType) >= bits);
static constexpr RawType significandMask{(RawType{1} << significandBits) - 1}; static constexpr RawType significandMask{(RawType{1} << significandBits) - 1};
constexpr BinaryFloatingPointNumber() {} // zero constexpr BinaryFloatingPointNumber() {} // zero
constexpr BinaryFloatingPointNumber( constexpr BinaryFloatingPointNumber(
const BinaryFloatingPointNumber &that) = default; const BinaryFloatingPointNumber &that) = default;
constexpr BinaryFloatingPointNumber( constexpr BinaryFloatingPointNumber(
@ -50,7 +50,7 @@ struct BinaryFloatingPointNumber
constexpr BinaryFloatingPointNumber &operator=( constexpr BinaryFloatingPointNumber &operator=(
BinaryFloatingPointNumber &&that) = default; BinaryFloatingPointNumber &&that) = default;
template<typename A> explicit constexpr BinaryFloatingPointNumber(A x) { template <typename A> explicit constexpr BinaryFloatingPointNumber(A x) {
static_assert(sizeof raw <= sizeof x); static_assert(sizeof raw <= sizeof x);
std::memcpy(reinterpret_cast<void *>(&raw), std::memcpy(reinterpret_cast<void *>(&raw),
reinterpret_cast<const void *>(&x), sizeof raw); reinterpret_cast<const void *>(&x), sizeof raw);
@ -92,5 +92,5 @@ struct BinaryFloatingPointNumber
RawType raw{0}; RawType raw{0};
}; };
} } // namespace Fortran::decimal
#endif #endif

View File

@ -72,7 +72,7 @@ enum DecimalConversionFlags {
#define EXTRA_DECIMAL_CONVERSION_SPACE (1 + 1 + 16 - 1) #define EXTRA_DECIMAL_CONVERSION_SPACE (1 + 1 + 16 - 1)
#ifdef __cplusplus #ifdef __cplusplus
template<int PREC> template <int PREC>
ConversionToDecimalResult ConvertToDecimal(char *, size_t, ConversionToDecimalResult ConvertToDecimal(char *, size_t,
DecimalConversionFlags, int digits, enum FortranRounding rounding, DecimalConversionFlags, int digits, enum FortranRounding rounding,
BinaryFloatingPointNumber<PREC> x); BinaryFloatingPointNumber<PREC> x);
@ -96,12 +96,12 @@ extern template ConversionToDecimalResult ConvertToDecimal<113>(char *, size_t,
enum DecimalConversionFlags, int, enum FortranRounding, enum DecimalConversionFlags, int, enum FortranRounding,
BinaryFloatingPointNumber<113>); BinaryFloatingPointNumber<113>);
template<int PREC> struct ConversionToBinaryResult { template <int PREC> struct ConversionToBinaryResult {
BinaryFloatingPointNumber<PREC> binary; BinaryFloatingPointNumber<PREC> binary;
enum ConversionResultFlags flags { Exact }; enum ConversionResultFlags flags { Exact };
}; };
template<int PREC> template <int PREC>
ConversionToBinaryResult<PREC> ConvertToBinary( ConversionToBinaryResult<PREC> ConvertToBinary(
const char *&, enum FortranRounding = RoundNearest); const char *&, enum FortranRounding = RoundNearest);
@ -117,7 +117,7 @@ extern template ConversionToBinaryResult<64> ConvertToBinary<64>(
const char *&, enum FortranRounding = RoundNearest); const char *&, enum FortranRounding = RoundNearest);
extern template ConversionToBinaryResult<113> ConvertToBinary<113>( extern template ConversionToBinaryResult<113> ConvertToBinary<113>(
const char *&, enum FortranRounding = RoundNearest); const char *&, enum FortranRounding = RoundNearest);
} // namespace Fortran::decimal } // namespace Fortran::decimal
extern "C" { extern "C" {
#define NS(x) Fortran::decimal::x #define NS(x) Fortran::decimal::x
#else /* C++ */ #else /* C++ */
@ -146,6 +146,6 @@ enum NS(ConversionResultFlags) ConvertDecimalToLongDouble(
#endif #endif
#undef NS #undef NS
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif
#endif #endif

View File

@ -33,11 +33,11 @@ class Symbol;
namespace Fortran::evaluate { namespace Fortran::evaluate {
class Component; class Component;
class IntrinsicProcTable; class IntrinsicProcTable;
} } // namespace Fortran::evaluate
namespace Fortran::evaluate::characteristics { namespace Fortran::evaluate::characteristics {
struct DummyArgument; struct DummyArgument;
struct Procedure; struct Procedure;
} } // namespace Fortran::evaluate::characteristics
extern template class Fortran::common::Indirection<Fortran::evaluate::Component, extern template class Fortran::common::Indirection<Fortran::evaluate::Component,
true>; true>;
@ -133,7 +133,7 @@ private:
// in the parse tree. // in the parse tree.
std::variant<common::CopyableIndirection<Expr<SomeType>>, AssumedType> u_; std::variant<common::CopyableIndirection<Expr<SomeType>>, AssumedType> u_;
std::optional<parser::CharBlock> keyword_; std::optional<parser::CharBlock> keyword_;
bool isAlternateReturn_{false}; // whether expr is a "*label" number bool isAlternateReturn_{false}; // whether expr is a "*label" number
bool isPassedObject_{false}; bool isPassedObject_{false};
common::Intent dummyIntent_{common::Intent::Default}; common::Intent dummyIntent_{common::Intent::Default};
}; };
@ -152,7 +152,7 @@ struct SpecificIntrinsic {
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
IntrinsicProcedure name; IntrinsicProcedure name;
bool isRestrictedSpecific{false}; // if true, can only call it, not pass it bool isRestrictedSpecific{false}; // if true, can only call it, not pass it
common::CopyableIndirection<characteristics::Procedure> characteristics; common::CopyableIndirection<characteristics::Procedure> characteristics;
}; };
@ -164,7 +164,7 @@ struct ProcedureDesignator {
// Exactly one of these will return a non-null pointer. // Exactly one of these will return a non-null pointer.
const SpecificIntrinsic *GetSpecificIntrinsic() const; const SpecificIntrinsic *GetSpecificIntrinsic() const;
const Symbol *GetSymbol() const; // symbol or component symbol const Symbol *GetSymbol() const; // symbol or component symbol
// For references to NOPASS components and bindings only. // For references to NOPASS components and bindings only.
// References to PASS components and bindings are represented // References to PASS components and bindings are represented
@ -191,7 +191,7 @@ class ProcedureRef {
public: public:
CLASS_BOILERPLATE(ProcedureRef) CLASS_BOILERPLATE(ProcedureRef)
ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a) ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a)
: proc_{std::move(p)}, arguments_(std::move(a)) {} : proc_{std::move(p)}, arguments_(std::move(a)) {}
~ProcedureRef(); ~ProcedureRef();
ProcedureDesignator &proc() { return proc_; } ProcedureDesignator &proc() { return proc_; }
@ -210,18 +210,18 @@ protected:
ActualArguments arguments_; ActualArguments arguments_;
}; };
template<typename A> class FunctionRef : public ProcedureRef { template <typename A> class FunctionRef : public ProcedureRef {
public: public:
using Result = A; using Result = A;
CLASS_BOILERPLATE(FunctionRef) CLASS_BOILERPLATE(FunctionRef)
explicit FunctionRef(ProcedureRef &&pr) : ProcedureRef{std::move(pr)} {} explicit FunctionRef(ProcedureRef &&pr) : ProcedureRef{std::move(pr)} {}
FunctionRef(ProcedureDesignator &&p, ActualArguments &&a) FunctionRef(ProcedureDesignator &&p, ActualArguments &&a)
: ProcedureRef{std::move(p), std::move(a)} {} : ProcedureRef{std::move(p), std::move(a)} {}
std::optional<DynamicType> GetType() const { return proc_.GetType(); } std::optional<DynamicType> GetType() const { return proc_.GetType(); }
std::optional<Constant<Result>> Fold(FoldingContext &); // for intrinsics std::optional<Constant<Result>> Fold(FoldingContext &); // for intrinsics
}; };
FOR_EACH_SPECIFIC_TYPE(extern template class FunctionRef, ) FOR_EACH_SPECIFIC_TYPE(extern template class FunctionRef, )
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_CALL_H_ #endif // FORTRAN_EVALUATE_CALL_H_

View File

@ -91,7 +91,7 @@ public:
static std::optional<TypeAndShape> Characterize( static std::optional<TypeAndShape> Characterize(
const semantics::DeclTypeSpec &); const semantics::DeclTypeSpec &);
template<typename A> template <typename A>
static std::optional<TypeAndShape> Characterize( static std::optional<TypeAndShape> Characterize(
const A &x, FoldingContext &context) { const A &x, FoldingContext &context) {
if (const auto *symbol{UnwrapWholeSymbolDataRef(x)}) { if (const auto *symbol{UnwrapWholeSymbolDataRef(x)}) {
@ -197,9 +197,9 @@ struct AlternateReturn {
struct DummyArgument { struct DummyArgument {
DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(DummyArgument) DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(DummyArgument)
DummyArgument(std::string &&name, DummyDataObject &&x) DummyArgument(std::string &&name, DummyDataObject &&x)
: name{std::move(name)}, u{std::move(x)} {} : name{std::move(name)}, u{std::move(x)} {}
DummyArgument(std::string &&name, DummyProcedure &&x) DummyArgument(std::string &&name, DummyProcedure &&x)
: name{std::move(name)}, u{std::move(x)} {} : name{std::move(name)}, u{std::move(x)} {}
explicit DummyArgument(AlternateReturn &&x) : u{std::move(x)} {} explicit DummyArgument(AlternateReturn &&x) : u{std::move(x)} {}
~DummyArgument(); ~DummyArgument();
bool operator==(const DummyArgument &) const; bool operator==(const DummyArgument &) const;
@ -215,7 +215,7 @@ struct DummyArgument {
// name and pass are not characteristics and so does not participate in // name and pass are not characteristics and so does not participate in
// operator== but are needed to determine if procedures are distinguishable // operator== but are needed to determine if procedures are distinguishable
std::string name; std::string name;
bool pass{false}; // is this the PASS argument of its procedure bool pass{false}; // is this the PASS argument of its procedure
std::variant<DummyDataObject, DummyProcedure, AlternateReturn> u; std::variant<DummyDataObject, DummyProcedure, AlternateReturn> u;
}; };
@ -262,7 +262,7 @@ struct Procedure {
Attr, Pure, Elemental, BindC, ImplicitInterface, NullPointer, Subroutine) Attr, Pure, Elemental, BindC, ImplicitInterface, NullPointer, Subroutine)
using Attrs = common::EnumSet<Attr, Attr_enumSize>; using Attrs = common::EnumSet<Attr, Attr_enumSize>;
Procedure(FunctionResult &&, DummyArguments &&, Attrs); Procedure(FunctionResult &&, DummyArguments &&, Attrs);
Procedure(DummyArguments &&, Attrs); // for subroutines and NULL() Procedure(DummyArguments &&, Attrs); // for subroutines and NULL()
DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure) DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure)
~Procedure(); ~Procedure();
bool operator==(const Procedure &) const; bool operator==(const Procedure &) const;
@ -301,5 +301,5 @@ private:
Procedure() {} Procedure() {}
}; };
} } // namespace Fortran::evaluate::characteristics
#endif // FORTRAN_EVALUATE_CHARACTERISTICS_H_ #endif // FORTRAN_EVALUATE_CHARACTERISTICS_H_

View File

@ -28,7 +28,7 @@ class IntrinsicProcTable;
// Predicate: true when an expression is a constant expression (in the // Predicate: true when an expression is a constant expression (in the
// strict sense of the Fortran standard); it may not (yet) be a hard // strict sense of the Fortran standard); it may not (yet) be a hard
// constant value. // constant value.
template<typename A> bool IsConstantExpr(const A &); template <typename A> bool IsConstantExpr(const A &);
extern template bool IsConstantExpr(const Expr<SomeType> &); extern template bool IsConstantExpr(const Expr<SomeType> &);
extern template bool IsConstantExpr(const Expr<SomeInteger> &); extern template bool IsConstantExpr(const Expr<SomeInteger> &);
extern template bool IsConstantExpr(const Expr<SubscriptInteger> &); extern template bool IsConstantExpr(const Expr<SubscriptInteger> &);
@ -40,7 +40,7 @@ bool IsInitialDataTarget(const Expr<SomeType> &, parser::ContextualMessages &);
// Check whether an expression is a specification expression // Check whether an expression is a specification expression
// (10.1.11(2), C1010). Constant expressions are always valid // (10.1.11(2), C1010). Constant expressions are always valid
// specification expressions. // specification expressions.
template<typename A> template <typename A>
void CheckSpecificationExpr( void CheckSpecificationExpr(
const A &, parser::ContextualMessages &, const semantics::Scope &); const A &, parser::ContextualMessages &, const semantics::Scope &);
extern template void CheckSpecificationExpr(const Expr<SomeType> &x, extern template void CheckSpecificationExpr(const Expr<SomeType> &x,
@ -60,10 +60,10 @@ extern template void CheckSpecificationExpr(
parser::ContextualMessages &, const semantics::Scope &); parser::ContextualMessages &, const semantics::Scope &);
// Simple contiguity (9.5.4) // Simple contiguity (9.5.4)
template<typename A> template <typename A>
bool IsSimplyContiguous(const A &, const IntrinsicProcTable &); bool IsSimplyContiguous(const A &, const IntrinsicProcTable &);
extern template bool IsSimplyContiguous( extern template bool IsSimplyContiguous(
const Expr<SomeType> &, const IntrinsicProcTable &); const Expr<SomeType> &, const IntrinsicProcTable &);
} } // namespace Fortran::evaluate
#endif #endif

View File

@ -35,7 +35,8 @@ using common::RelationalOperator;
ENUM_CLASS(Ordering, Less, Equal, Greater) ENUM_CLASS(Ordering, Less, Equal, Greater)
ENUM_CLASS(Relation, Less, Equal, Greater, Unordered) ENUM_CLASS(Relation, Less, Equal, Greater, Unordered)
template<typename A> static constexpr Ordering Compare(const A &x, const A &y) { template <typename A>
static constexpr Ordering Compare(const A &x, const A &y) {
if (x < y) { if (x < y) {
return Ordering::Less; return Ordering::Less;
} else if (x > y) { } else if (x > y) {
@ -87,17 +88,21 @@ static constexpr bool Satisfies(RelationalOperator op, Ordering order) {
return op == RelationalOperator::NE || op == RelationalOperator::GE || return op == RelationalOperator::NE || op == RelationalOperator::GE ||
op == RelationalOperator::GT; op == RelationalOperator::GT;
} }
return false; // silence g++ warning return false; // silence g++ warning
} }
static constexpr bool Satisfies(RelationalOperator op, Relation relation) { static constexpr bool Satisfies(RelationalOperator op, Relation relation) {
switch (relation) { switch (relation) {
case Relation::Less: return Satisfies(op, Ordering::Less); case Relation::Less:
case Relation::Equal: return Satisfies(op, Ordering::Equal); return Satisfies(op, Ordering::Less);
case Relation::Greater: return Satisfies(op, Ordering::Greater); case Relation::Equal:
case Relation::Unordered: return false; return Satisfies(op, Ordering::Equal);
case Relation::Greater:
return Satisfies(op, Ordering::Greater);
case Relation::Unordered:
return false;
} }
return false; // silence g++ warning return false; // silence g++ warning
} }
ENUM_CLASS( ENUM_CLASS(
@ -105,7 +110,7 @@ ENUM_CLASS(
using RealFlags = common::EnumSet<RealFlag, RealFlag_enumSize>; using RealFlags = common::EnumSet<RealFlag, RealFlag_enumSize>;
template<typename A> struct ValueWithRealFlags { template <typename A> struct ValueWithRealFlags {
A AccumulateFlags(RealFlags &f) { A AccumulateFlags(RealFlags &f) {
f |= flags; f |= flags;
return value; return value;
@ -139,20 +144,20 @@ constexpr bool isHostLittleEndian{true};
// HostUnsignedInt<BITS> finds the smallest native unsigned integer type // HostUnsignedInt<BITS> finds the smallest native unsigned integer type
// whose size is >= BITS. // whose size is >= BITS.
template<bool LE8, bool LE16, bool LE32, bool LE64> struct SmallestUInt {}; template <bool LE8, bool LE16, bool LE32, bool LE64> struct SmallestUInt {};
template<> struct SmallestUInt<true, true, true, true> { template <> struct SmallestUInt<true, true, true, true> {
using type = std::uint8_t; using type = std::uint8_t;
}; };
template<> struct SmallestUInt<false, true, true, true> { template <> struct SmallestUInt<false, true, true, true> {
using type = std::uint16_t; using type = std::uint16_t;
}; };
template<> struct SmallestUInt<false, false, true, true> { template <> struct SmallestUInt<false, false, true, true> {
using type = std::uint32_t; using type = std::uint32_t;
}; };
template<> struct SmallestUInt<false, false, false, true> { template <> struct SmallestUInt<false, false, false, true> {
using type = std::uint64_t; using type = std::uint64_t;
}; };
template<int BITS> template <int BITS>
using HostUnsignedInt = using HostUnsignedInt =
typename SmallestUInt<BITS <= 8, BITS <= 16, BITS <= 32, BITS <= 64>::type; typename SmallestUInt<BITS <= 8, BITS <= 16, BITS <= 32, BITS <= 64>::type;
@ -188,8 +193,8 @@ using HostUnsignedInt =
DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(t) DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(t)
#define UNION_CONSTRUCTORS(t) \ #define UNION_CONSTRUCTORS(t) \
template<typename _A> explicit t(const _A &x) : u{x} {} \ template <typename _A> explicit t(const _A &x) : u{x} {} \
template<typename _A, typename = common::NoLvalue<_A>> \ template <typename _A, typename = common::NoLvalue<_A>> \
explicit t(_A &&x) : u(std::move(x)) {} explicit t(_A &&x) : u(std::move(x)) {}
#define EVALUATE_UNION_CLASS_BOILERPLATE(t) \ #define EVALUATE_UNION_CLASS_BOILERPLATE(t) \
@ -199,29 +204,29 @@ using HostUnsignedInt =
// Forward definition of Expr<> so that it can be indirectly used in its own // Forward definition of Expr<> so that it can be indirectly used in its own
// definition // definition
template<typename A> class Expr; template <typename A> class Expr;
class FoldingContext { class FoldingContext {
public: public:
FoldingContext( FoldingContext(
const common::IntrinsicTypeDefaultKinds &d, const IntrinsicProcTable &t) const common::IntrinsicTypeDefaultKinds &d, const IntrinsicProcTable &t)
: defaults_{d}, intrinsics_{t} {} : defaults_{d}, intrinsics_{t} {}
FoldingContext(const parser::ContextualMessages &m, FoldingContext(const parser::ContextualMessages &m,
const common::IntrinsicTypeDefaultKinds &d, const IntrinsicProcTable &t, const common::IntrinsicTypeDefaultKinds &d, const IntrinsicProcTable &t,
Rounding round = defaultRounding, bool flush = false) Rounding round = defaultRounding, bool flush = false)
: messages_{m}, defaults_{d}, intrinsics_{t}, rounding_{round}, : messages_{m}, defaults_{d}, intrinsics_{t}, rounding_{round},
flushSubnormalsToZero_{flush} {} flushSubnormalsToZero_{flush} {}
FoldingContext(const FoldingContext &that) FoldingContext(const FoldingContext &that)
: messages_{that.messages_}, defaults_{that.defaults_}, : messages_{that.messages_}, defaults_{that.defaults_},
intrinsics_{that.intrinsics_}, rounding_{that.rounding_}, intrinsics_{that.intrinsics_}, rounding_{that.rounding_},
flushSubnormalsToZero_{that.flushSubnormalsToZero_}, flushSubnormalsToZero_{that.flushSubnormalsToZero_},
pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_} {} pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_} {}
FoldingContext( FoldingContext(
const FoldingContext &that, const parser::ContextualMessages &m) const FoldingContext &that, const parser::ContextualMessages &m)
: messages_{m}, defaults_{that.defaults_}, : messages_{m}, defaults_{that.defaults_},
intrinsics_{that.intrinsics_}, rounding_{that.rounding_}, intrinsics_{that.intrinsics_}, rounding_{that.rounding_},
flushSubnormalsToZero_{that.flushSubnormalsToZero_}, flushSubnormalsToZero_{that.flushSubnormalsToZero_},
pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_} {} pdtInstance_{that.pdtInstance_}, impliedDos_{that.impliedDos_} {}
parser::ContextualMessages &messages() { return messages_; } parser::ContextualMessages &messages() { return messages_; }
const parser::ContextualMessages &messages() const { return messages_; } const parser::ContextualMessages &messages() const { return messages_; }
@ -263,5 +268,5 @@ private:
}; };
void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op); void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op);
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_COMMON_H_ #endif // FORTRAN_EVALUATE_COMMON_H_

View File

@ -19,12 +19,12 @@ class raw_ostream;
namespace Fortran::evaluate::value { namespace Fortran::evaluate::value {
template<typename REAL_TYPE> class Complex { template <typename REAL_TYPE> class Complex {
public: public:
using Part = REAL_TYPE; using Part = REAL_TYPE;
static constexpr int bits{2 * Part::bits}; static constexpr int bits{2 * Part::bits};
constexpr Complex() {} // (+0.0, +0.0) constexpr Complex() {} // (+0.0, +0.0)
constexpr Complex(const Complex &) = default; constexpr Complex(const Complex &) = default;
constexpr Complex(const Part &r, const Part &i) : re_{r}, im_{i} {} constexpr Complex(const Part &r, const Part &i) : re_{r}, im_{i} {}
explicit constexpr Complex(const Part &r) : re_{r} {} explicit constexpr Complex(const Part &r) : re_{r} {}
@ -59,7 +59,7 @@ public:
return re_.IsSignalingNaN() || im_.IsSignalingNaN(); return re_.IsSignalingNaN() || im_.IsSignalingNaN();
} }
template<typename INT> template <typename INT>
static ValueWithRealFlags<Complex> FromInteger( static ValueWithRealFlags<Complex> FromInteger(
const INT &n, Rounding rounding = defaultRounding) { const INT &n, Rounding rounding = defaultRounding) {
ValueWithRealFlags<Complex> result; ValueWithRealFlags<Complex> result;
@ -101,5 +101,5 @@ extern template class Complex<Real<Integer<32>, 24>>;
extern template class Complex<Real<Integer<64>, 53>>; extern template class Complex<Real<Integer<64>, 53>>;
extern template class Complex<Real<Integer<80>, 64>>; extern template class Complex<Real<Integer<80>, 64>>;
extern template class Complex<Real<Integer<128>, 113>>; extern template class Complex<Real<Integer<128>, 113>>;
} } // namespace Fortran::evaluate::value
#endif // FORTRAN_EVALUATE_COMPLEX_H_ #endif // FORTRAN_EVALUATE_COMPLEX_H_

View File

@ -37,7 +37,7 @@ using SymbolRef = common::Reference<const Symbol>;
// constants, use a generic expression like Expr<SomeInteger> & // constants, use a generic expression like Expr<SomeInteger> &
// Expr<SomeType>) to wrap the appropriate instantiation of Constant<>. // Expr<SomeType>) to wrap the appropriate instantiation of Constant<>.
template<typename> class Constant; template <typename> class Constant;
// When describing shapes of constants or specifying 1-based subscript // When describing shapes of constants or specifying 1-based subscript
// values as indices into constants, use a vector of integers. // values as indices into constants, use a vector of integers.
@ -87,7 +87,7 @@ private:
// Constant<> is specialized for Character kinds and SomeDerived. // Constant<> is specialized for Character kinds and SomeDerived.
// The non-Character intrinsic types, and SomeDerived, share enough // The non-Character intrinsic types, and SomeDerived, share enough
// common behavior that they use this common base class. // common behavior that they use this common base class.
template<typename RESULT, typename ELEMENT = Scalar<RESULT>> template <typename RESULT, typename ELEMENT = Scalar<RESULT>>
class ConstantBase : public ConstantBounds { class ConstantBase : public ConstantBounds {
static_assert(RESULT::category != TypeCategory::Character); static_assert(RESULT::category != TypeCategory::Character);
@ -95,11 +95,11 @@ public:
using Result = RESULT; using Result = RESULT;
using Element = ELEMENT; using Element = ELEMENT;
template<typename A> template <typename A>
ConstantBase(const A &x, Result res = Result{}) : result_{res}, values_{x} {} ConstantBase(const A &x, Result res = Result{}) : result_{res}, values_{x} {}
template<typename A, typename = common::NoLvalue<A>> template <typename A, typename = common::NoLvalue<A>>
ConstantBase(A &&x, Result res = Result{}) ConstantBase(A &&x, Result res = Result{})
: result_{res}, values_{std::move(x)} {} : result_{res}, values_{std::move(x)} {}
ConstantBase( ConstantBase(
std::vector<Element> &&, ConstantSubscripts &&, Result = Result{}); std::vector<Element> &&, ConstantSubscripts &&, Result = Result{});
@ -124,7 +124,7 @@ protected:
std::vector<Element> values_; std::vector<Element> values_;
}; };
template<typename T> class Constant : public ConstantBase<T> { template <typename T> class Constant : public ConstantBase<T> {
public: public:
using Result = T; using Result = T;
using Base = ConstantBase<T>; using Base = ConstantBase<T>;
@ -149,7 +149,7 @@ public:
ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder); ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder);
}; };
template<int KIND> template <int KIND>
class Constant<Type<TypeCategory::Character, KIND>> : public ConstantBounds { class Constant<Type<TypeCategory::Character, KIND>> : public ConstantBounds {
public: public:
using Result = Type<TypeCategory::Character, KIND>; using Result = Type<TypeCategory::Character, KIND>;
@ -189,7 +189,7 @@ public:
ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder); ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder);
private: private:
Scalar<Result> values_; // one contiguous string Scalar<Result> values_; // one contiguous string
ConstantSubscript length_; ConstantSubscript length_;
ConstantSubscripts shape_; ConstantSubscripts shape_;
ConstantSubscripts lbounds_; ConstantSubscripts lbounds_;
@ -199,9 +199,9 @@ class StructureConstructor;
using StructureConstructorValues = using StructureConstructorValues =
std::map<SymbolRef, common::CopyableIndirection<Expr<SomeType>>>; std::map<SymbolRef, common::CopyableIndirection<Expr<SomeType>>>;
template<> template <>
class Constant<SomeDerived> class Constant<SomeDerived>
: public ConstantBase<SomeDerived, StructureConstructorValues> { : public ConstantBase<SomeDerived, StructureConstructorValues> {
public: public:
using Result = SomeDerived; using Result = SomeDerived;
using Element = StructureConstructorValues; using Element = StructureConstructorValues;
@ -231,5 +231,5 @@ FOR_EACH_INTRINSIC_KIND(extern template class Constant, )
FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase, ) \ FOR_EACH_LENGTHLESS_INTRINSIC_KIND(template class ConstantBase, ) \
template class ConstantBase<SomeDerived, StructureConstructorValues>; \ template class ConstantBase<SomeDerived, StructureConstructorValues>; \
FOR_EACH_INTRINSIC_KIND(template class Constant, ) FOR_EACH_INTRINSIC_KIND(template class Constant, )
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_CONSTANT_H_ #endif // FORTRAN_EVALUATE_CONSTANT_H_

View File

@ -60,10 +60,10 @@ using common::RelationalOperator;
// represented with an instance of some class containing a Result typedef that // represented with an instance of some class containing a Result typedef that
// maps to some instantiation of Type<CATEGORY, KIND>, SomeKind<CATEGORY>, // maps to some instantiation of Type<CATEGORY, KIND>, SomeKind<CATEGORY>,
// or SomeType. (Exception: BOZ literal constants in generic Expr<SomeType>.) // or SomeType. (Exception: BOZ literal constants in generic Expr<SomeType>.)
template<typename A> using ResultType = typename std::decay_t<A>::Result; template <typename A> using ResultType = typename std::decay_t<A>::Result;
// Common Expr<> behaviors: every Expr<T> derives from ExpressionBase<T>. // Common Expr<> behaviors: every Expr<T> derives from ExpressionBase<T>.
template<typename RESULT> class ExpressionBase { template <typename RESULT> class ExpressionBase {
public: public:
using Result = RESULT; using Result = RESULT;
@ -78,13 +78,13 @@ private:
#endif #endif
public: public:
template<typename A> Derived &operator=(const A &x) { template <typename A> Derived &operator=(const A &x) {
Derived &d{derived()}; Derived &d{derived()};
d.u = x; d.u = x;
return d; return d;
} }
template<typename A> common::IfNoLvalue<Derived &, A> operator=(A &&x) { template <typename A> common::IfNoLvalue<Derived &, A> operator=(A &&x) {
Derived &d{derived()}; Derived &d{derived()};
d.u = std::move(x); d.u = std::move(x);
return d; return d;
@ -106,7 +106,7 @@ public:
// struct Add : public Operation<Add, ...>. Uses of instances of Operation<>, // struct Add : public Operation<Add, ...>. Uses of instances of Operation<>,
// including its own member functions, can access each specific class derived // including its own member functions, can access each specific class derived
// from it via its derived() member function with compile-time type safety. // from it via its derived() member function with compile-time type safety.
template<typename DERIVED, typename RESULT, typename... OPERANDS> template <typename DERIVED, typename RESULT, typename... OPERANDS>
class Operation { class Operation {
// The extra final member is a dummy that allows a safe unused reference // The extra final member is a dummy that allows a safe unused reference
// to element 1 to arise indirectly in the definition of "right()" below // to element 1 to arise indirectly in the definition of "right()" below
@ -118,7 +118,7 @@ public:
using Result = RESULT; using Result = RESULT;
static_assert(IsSpecificIntrinsicType<Result>); static_assert(IsSpecificIntrinsicType<Result>);
static constexpr std::size_t operands{sizeof...(OPERANDS)}; static constexpr std::size_t operands{sizeof...(OPERANDS)};
template<int J> using Operand = std::tuple_element_t<J, OperandTypes>; template <int J> using Operand = std::tuple_element_t<J, OperandTypes>;
// Unary operations wrap a single Expr with a CopyableIndirection. // Unary operations wrap a single Expr with a CopyableIndirection.
// Binary operations wrap a tuple of CopyableIndirections to Exprs. // Binary operations wrap a tuple of CopyableIndirections to Exprs.
@ -140,7 +140,7 @@ public:
// which must be spelled like "this->template operand<0>()" when // which must be spelled like "this->template operand<0>()" when
// inherited in a derived class template. There are convenience aliases // inherited in a derived class template. There are convenience aliases
// left() and right() that are not templates. // left() and right() that are not templates.
template<int J> Expr<Operand<J>> &operand() { template <int J> Expr<Operand<J>> &operand() {
if constexpr (operands == 1) { if constexpr (operands == 1) {
static_assert(J == 0); static_assert(J == 0);
return operand_.value(); return operand_.value();
@ -148,7 +148,7 @@ public:
return std::get<J>(operand_).value(); return std::get<J>(operand_).value();
} }
} }
template<int J> const Expr<Operand<J>> &operand() const { template <int J> const Expr<Operand<J>> &operand() const {
if constexpr (operands == 1) { if constexpr (operands == 1) {
static_assert(J == 0); static_assert(J == 0);
return operand_.value(); return operand_.value();
@ -198,7 +198,7 @@ private:
// Conversions to specific types from expressions of known category and // Conversions to specific types from expressions of known category and
// dynamic kind. // dynamic kind.
template<typename TO, TypeCategory FROMCAT = TO::category> template <typename TO, TypeCategory FROMCAT = TO::category>
struct Convert : public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> { struct Convert : public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> {
// Fortran doesn't have conversions between kinds of CHARACTER apart from // Fortran doesn't have conversions between kinds of CHARACTER apart from
// assignments, and in those the data must be convertible to/from 7-bit ASCII. // assignments, and in those the data must be convertible to/from 7-bit ASCII.
@ -218,7 +218,7 @@ struct Convert : public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> {
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
}; };
template<typename A> template <typename A>
struct Parentheses : public Operation<Parentheses<A>, A, A> { struct Parentheses : public Operation<Parentheses<A>, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
@ -226,30 +226,30 @@ struct Parentheses : public Operation<Parentheses<A>, A, A> {
using Base::Base; using Base::Base;
}; };
template<typename A> struct Negate : public Operation<Negate<A>, A, A> { template <typename A> struct Negate : public Operation<Negate<A>, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Negate, A, A>; using Base = Operation<Negate, A, A>;
using Base::Base; using Base::Base;
}; };
template<int KIND> template <int KIND>
struct ComplexComponent struct ComplexComponent
: public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>, : public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>,
Type<TypeCategory::Complex, KIND>> { Type<TypeCategory::Complex, KIND>> {
using Result = Type<TypeCategory::Real, KIND>; using Result = Type<TypeCategory::Real, KIND>;
using Operand = Type<TypeCategory::Complex, KIND>; using Operand = Type<TypeCategory::Complex, KIND>;
using Base = Operation<ComplexComponent, Result, Operand>; using Base = Operation<ComplexComponent, Result, Operand>;
CLASS_BOILERPLATE(ComplexComponent) CLASS_BOILERPLATE(ComplexComponent)
ComplexComponent(bool isImaginary, const Expr<Operand> &x) ComplexComponent(bool isImaginary, const Expr<Operand> &x)
: Base{x}, isImaginaryPart{isImaginary} {} : Base{x}, isImaginaryPart{isImaginary} {}
ComplexComponent(bool isImaginary, Expr<Operand> &&x) ComplexComponent(bool isImaginary, Expr<Operand> &&x)
: Base{std::move(x)}, isImaginaryPart{isImaginary} {} : Base{std::move(x)}, isImaginaryPart{isImaginary} {}
bool isImaginaryPart{true}; bool isImaginaryPart{true};
}; };
template<int KIND> template <int KIND>
struct Not : public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>, struct Not : public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>,
Type<TypeCategory::Logical, KIND>> { Type<TypeCategory::Logical, KIND>> {
using Result = Type<TypeCategory::Logical, KIND>; using Result = Type<TypeCategory::Logical, KIND>;
@ -262,10 +262,10 @@ struct Not : public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>,
// have explicit syntax for changing them. Expressions represent // have explicit syntax for changing them. Expressions represent
// changes of length (e.g., for assignments and structure constructors) // changes of length (e.g., for assignments and structure constructors)
// with this operation. // with this operation.
template<int KIND> template <int KIND>
struct SetLength struct SetLength
: public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>, : public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>,
Type<TypeCategory::Character, KIND>, SubscriptInteger> { Type<TypeCategory::Character, KIND>, SubscriptInteger> {
using Result = Type<TypeCategory::Character, KIND>; using Result = Type<TypeCategory::Character, KIND>;
using CharacterOperand = Result; using CharacterOperand = Result;
using LengthOperand = SubscriptInteger; using LengthOperand = SubscriptInteger;
@ -275,42 +275,42 @@ struct SetLength
// Binary operations // Binary operations
template<typename A> struct Add : public Operation<Add<A>, A, A, A> { template <typename A> struct Add : public Operation<Add<A>, A, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Add, A, A, A>; using Base = Operation<Add, A, A, A>;
using Base::Base; using Base::Base;
}; };
template<typename A> struct Subtract : public Operation<Subtract<A>, A, A, A> { template <typename A> struct Subtract : public Operation<Subtract<A>, A, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Subtract, A, A, A>; using Base = Operation<Subtract, A, A, A>;
using Base::Base; using Base::Base;
}; };
template<typename A> struct Multiply : public Operation<Multiply<A>, A, A, A> { template <typename A> struct Multiply : public Operation<Multiply<A>, A, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Multiply, A, A, A>; using Base = Operation<Multiply, A, A, A>;
using Base::Base; using Base::Base;
}; };
template<typename A> struct Divide : public Operation<Divide<A>, A, A, A> { template <typename A> struct Divide : public Operation<Divide<A>, A, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Divide, A, A, A>; using Base = Operation<Divide, A, A, A>;
using Base::Base; using Base::Base;
}; };
template<typename A> struct Power : public Operation<Power<A>, A, A, A> { template <typename A> struct Power : public Operation<Power<A>, A, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Power, A, A, A>; using Base = Operation<Power, A, A, A>;
using Base::Base; using Base::Base;
}; };
template<typename A> template <typename A>
struct RealToIntPower : public Operation<RealToIntPower<A>, A, A, SomeInteger> { struct RealToIntPower : public Operation<RealToIntPower<A>, A, A, SomeInteger> {
using Base = Operation<RealToIntPower, A, A, SomeInteger>; using Base = Operation<RealToIntPower, A, A, SomeInteger>;
using Result = A; using Result = A;
@ -319,74 +319,75 @@ struct RealToIntPower : public Operation<RealToIntPower<A>, A, A, SomeInteger> {
using Base::Base; using Base::Base;
}; };
template<typename A> struct Extremum : public Operation<Extremum<A>, A, A, A> { template <typename A> struct Extremum : public Operation<Extremum<A>, A, A, A> {
using Result = A; using Result = A;
using Operand = A; using Operand = A;
using Base = Operation<Extremum, A, A, A>; using Base = Operation<Extremum, A, A, A>;
CLASS_BOILERPLATE(Extremum) CLASS_BOILERPLATE(Extremum)
Extremum(Ordering ord, const Expr<Operand> &x, const Expr<Operand> &y) Extremum(Ordering ord, const Expr<Operand> &x, const Expr<Operand> &y)
: Base{x, y}, ordering{ord} {} : Base{x, y}, ordering{ord} {}
Extremum(Ordering ord, Expr<Operand> &&x, Expr<Operand> &&y) Extremum(Ordering ord, Expr<Operand> &&x, Expr<Operand> &&y)
: Base{std::move(x), std::move(y)}, ordering{ord} {} : Base{std::move(x), std::move(y)}, ordering{ord} {}
Ordering ordering{Ordering::Greater}; Ordering ordering{Ordering::Greater};
}; };
template<int KIND> template <int KIND>
struct ComplexConstructor struct ComplexConstructor
: public Operation<ComplexConstructor<KIND>, : public Operation<ComplexConstructor<KIND>,
Type<TypeCategory::Complex, KIND>, Type<TypeCategory::Real, KIND>, Type<TypeCategory::Complex, KIND>, Type<TypeCategory::Real, KIND>,
Type<TypeCategory::Real, KIND>> { Type<TypeCategory::Real, KIND>> {
using Result = Type<TypeCategory::Complex, KIND>; using Result = Type<TypeCategory::Complex, KIND>;
using Operand = Type<TypeCategory::Real, KIND>; using Operand = Type<TypeCategory::Real, KIND>;
using Base = Operation<ComplexConstructor, Result, Operand, Operand>; using Base = Operation<ComplexConstructor, Result, Operand, Operand>;
using Base::Base; using Base::Base;
}; };
template<int KIND> template <int KIND>
struct Concat struct Concat
: public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>, : public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>,
Type<TypeCategory::Character, KIND>, Type<TypeCategory::Character, KIND>,
Type<TypeCategory::Character, KIND>> { Type<TypeCategory::Character, KIND>> {
using Result = Type<TypeCategory::Character, KIND>; using Result = Type<TypeCategory::Character, KIND>;
using Operand = Result; using Operand = Result;
using Base = Operation<Concat, Result, Operand, Operand>; using Base = Operation<Concat, Result, Operand, Operand>;
using Base::Base; using Base::Base;
}; };
template<int KIND> template <int KIND>
struct LogicalOperation struct LogicalOperation
: public Operation<LogicalOperation<KIND>, Type<TypeCategory::Logical, KIND>, : public Operation<LogicalOperation<KIND>,
Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>> { Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>,
Type<TypeCategory::Logical, KIND>> {
using Result = Type<TypeCategory::Logical, KIND>; using Result = Type<TypeCategory::Logical, KIND>;
using Operand = Result; using Operand = Result;
using Base = Operation<LogicalOperation, Result, Operand, Operand>; using Base = Operation<LogicalOperation, Result, Operand, Operand>;
CLASS_BOILERPLATE(LogicalOperation) CLASS_BOILERPLATE(LogicalOperation)
LogicalOperation( LogicalOperation(
LogicalOperator opr, const Expr<Operand> &x, const Expr<Operand> &y) LogicalOperator opr, const Expr<Operand> &x, const Expr<Operand> &y)
: Base{x, y}, logicalOperator{opr} {} : Base{x, y}, logicalOperator{opr} {}
LogicalOperation(LogicalOperator opr, Expr<Operand> &&x, Expr<Operand> &&y) LogicalOperation(LogicalOperator opr, Expr<Operand> &&x, Expr<Operand> &&y)
: Base{std::move(x), std::move(y)}, logicalOperator{opr} {} : Base{std::move(x), std::move(y)}, logicalOperator{opr} {}
LogicalOperator logicalOperator; LogicalOperator logicalOperator;
}; };
// Array constructors // Array constructors
template<typename RESULT> class ArrayConstructorValues; template <typename RESULT> class ArrayConstructorValues;
struct ImpliedDoIndex { struct ImpliedDoIndex {
using Result = SubscriptInteger; using Result = SubscriptInteger;
bool operator==(const ImpliedDoIndex &) const; bool operator==(const ImpliedDoIndex &) const;
static constexpr int Rank() { return 0; } static constexpr int Rank() { return 0; }
parser::CharBlock name; // nested implied DOs must use distinct names parser::CharBlock name; // nested implied DOs must use distinct names
}; };
template<typename RESULT> class ImpliedDo { template <typename RESULT> class ImpliedDo {
public: public:
using Result = RESULT; using Result = RESULT;
using Index = ResultType<ImpliedDoIndex>; using Index = ResultType<ImpliedDoIndex>;
ImpliedDo(parser::CharBlock name, Expr<Index> &&lower, Expr<Index> &&upper, ImpliedDo(parser::CharBlock name, Expr<Index> &&lower, Expr<Index> &&upper,
Expr<Index> &&stride, ArrayConstructorValues<Result> &&values) Expr<Index> &&stride, ArrayConstructorValues<Result> &&values)
: name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)}, : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
stride_{std::move(stride)}, values_{std::move(values)} {} stride_{std::move(stride)}, values_{std::move(values)} {}
DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo) DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo)
bool operator==(const ImpliedDo &) const; bool operator==(const ImpliedDo &) const;
parser::CharBlock name() const { return name_; } parser::CharBlock name() const { return name_; }
@ -407,13 +408,13 @@ private:
common::CopyableIndirection<ArrayConstructorValues<Result>> values_; common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
}; };
template<typename RESULT> struct ArrayConstructorValue { template <typename RESULT> struct ArrayConstructorValue {
using Result = RESULT; using Result = RESULT;
EVALUATE_UNION_CLASS_BOILERPLATE(ArrayConstructorValue) EVALUATE_UNION_CLASS_BOILERPLATE(ArrayConstructorValue)
std::variant<Expr<Result>, ImpliedDo<Result>> u; std::variant<Expr<Result>, ImpliedDo<Result>> u;
}; };
template<typename RESULT> class ArrayConstructorValues { template <typename RESULT> class ArrayConstructorValues {
public: public:
using Result = RESULT; using Result = RESULT;
using Values = std::vector<ArrayConstructorValue<Result>>; using Values = std::vector<ArrayConstructorValue<Result>>;
@ -422,7 +423,7 @@ public:
bool operator==(const ArrayConstructorValues &) const; bool operator==(const ArrayConstructorValues &) const;
static constexpr int Rank() { return 1; } static constexpr int Rank() { return 1; }
template<typename A> common::NoLvalue<A> Push(A &&x) { template <typename A> common::NoLvalue<A> Push(A &&x) {
values_.emplace_back(std::move(x)); values_.emplace_back(std::move(x));
} }
@ -439,31 +440,31 @@ protected:
// and derived types, since they must carry additional type information, // and derived types, since they must carry additional type information,
// but that an empty ArrayConstructor can be constructed for any type // but that an empty ArrayConstructor can be constructed for any type
// given an expression from which such type information may be gleaned. // given an expression from which such type information may be gleaned.
template<typename RESULT> template <typename RESULT>
class ArrayConstructor : public ArrayConstructorValues<RESULT> { class ArrayConstructor : public ArrayConstructorValues<RESULT> {
public: public:
using Result = RESULT; using Result = RESULT;
using Base = ArrayConstructorValues<Result>; using Base = ArrayConstructorValues<Result>;
DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor) DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {} explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
template<typename T> explicit ArrayConstructor(const Expr<T> &) {} template <typename T> explicit ArrayConstructor(const Expr<T> &) {}
static constexpr Result result() { return Result{}; } static constexpr Result result() { return Result{}; }
static constexpr DynamicType GetType() { return Result::GetType(); } static constexpr DynamicType GetType() { return Result::GetType(); }
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
}; };
template<int KIND> template <int KIND>
class ArrayConstructor<Type<TypeCategory::Character, KIND>> class ArrayConstructor<Type<TypeCategory::Character, KIND>>
: public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> { : public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> {
public: public:
using Result = Type<TypeCategory::Character, KIND>; using Result = Type<TypeCategory::Character, KIND>;
using Base = ArrayConstructorValues<Result>; using Base = ArrayConstructorValues<Result>;
CLASS_BOILERPLATE(ArrayConstructor) CLASS_BOILERPLATE(ArrayConstructor)
ArrayConstructor(Expr<SubscriptInteger> &&len, Base &&v) ArrayConstructor(Expr<SubscriptInteger> &&len, Base &&v)
: Base{std::move(v)}, length_{std::move(len)} {} : Base{std::move(v)}, length_{std::move(len)} {}
template<typename A> template <typename A>
explicit ArrayConstructor(const A &prototype) explicit ArrayConstructor(const A &prototype)
: length_{prototype.LEN().value()} {} : length_{prototype.LEN().value()} {}
bool operator==(const ArrayConstructor &) const; bool operator==(const ArrayConstructor &) const;
static constexpr Result result() { return Result{}; } static constexpr Result result() { return Result{}; }
static constexpr DynamicType GetType() { return Result::GetType(); } static constexpr DynamicType GetType() { return Result::GetType(); }
@ -474,19 +475,19 @@ private:
common::CopyableIndirection<Expr<SubscriptInteger>> length_; common::CopyableIndirection<Expr<SubscriptInteger>> length_;
}; };
template<> template <>
class ArrayConstructor<SomeDerived> class ArrayConstructor<SomeDerived>
: public ArrayConstructorValues<SomeDerived> { : public ArrayConstructorValues<SomeDerived> {
public: public:
using Result = SomeDerived; using Result = SomeDerived;
using Base = ArrayConstructorValues<Result>; using Base = ArrayConstructorValues<Result>;
CLASS_BOILERPLATE(ArrayConstructor) CLASS_BOILERPLATE(ArrayConstructor)
ArrayConstructor(const semantics::DerivedTypeSpec &spec, Base &&v) ArrayConstructor(const semantics::DerivedTypeSpec &spec, Base &&v)
: Base{std::move(v)}, result_{spec} {} : Base{std::move(v)}, result_{spec} {}
template<typename A> template <typename A>
explicit ArrayConstructor(const A &prototype) explicit ArrayConstructor(const A &prototype)
: result_{prototype.GetType().value().GetDerivedTypeSpec()} {} : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
bool operator==(const ArrayConstructor &) const; bool operator==(const ArrayConstructor &) const;
constexpr Result result() const { return result_; } constexpr Result result() const { return result_; }
@ -499,9 +500,9 @@ private:
// Expression representations for each type category. // Expression representations for each type category.
template<int KIND> template <int KIND>
class Expr<Type<TypeCategory::Integer, KIND>> class Expr<Type<TypeCategory::Integer, KIND>>
: public ExpressionBase<Type<TypeCategory::Integer, KIND>> { : public ExpressionBase<Type<TypeCategory::Integer, KIND>> {
public: public:
using Result = Type<TypeCategory::Integer, KIND>; using Result = Type<TypeCategory::Integer, KIND>;
@ -527,9 +528,9 @@ public:
u; u;
}; };
template<int KIND> template <int KIND>
class Expr<Type<TypeCategory::Real, KIND>> class Expr<Type<TypeCategory::Real, KIND>>
: public ExpressionBase<Type<TypeCategory::Real, KIND>> { : public ExpressionBase<Type<TypeCategory::Real, KIND>> {
public: public:
using Result = Type<TypeCategory::Real, KIND>; using Result = Type<TypeCategory::Real, KIND>;
@ -552,9 +553,9 @@ public:
common::CombineVariants<Operations, Conversions, Others> u; common::CombineVariants<Operations, Conversions, Others> u;
}; };
template<int KIND> template <int KIND>
class Expr<Type<TypeCategory::Complex, KIND>> class Expr<Type<TypeCategory::Complex, KIND>>
: public ExpressionBase<Type<TypeCategory::Complex, KIND>> { : public ExpressionBase<Type<TypeCategory::Complex, KIND>> {
public: public:
using Result = Type<TypeCategory::Complex, KIND>; using Result = Type<TypeCategory::Complex, KIND>;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr) EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
@ -576,9 +577,9 @@ FOR_EACH_INTEGER_KIND(extern template class Expr, )
FOR_EACH_REAL_KIND(extern template class Expr, ) FOR_EACH_REAL_KIND(extern template class Expr, )
FOR_EACH_COMPLEX_KIND(extern template class Expr, ) FOR_EACH_COMPLEX_KIND(extern template class Expr, )
template<int KIND> template <int KIND>
class Expr<Type<TypeCategory::Character, KIND>> class Expr<Type<TypeCategory::Character, KIND>>
: public ExpressionBase<Type<TypeCategory::Character, KIND>> { : public ExpressionBase<Type<TypeCategory::Character, KIND>> {
public: public:
using Result = Type<TypeCategory::Character, KIND>; using Result = Type<TypeCategory::Character, KIND>;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr) EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
@ -603,7 +604,7 @@ FOR_EACH_CHARACTER_KIND(extern template class Expr, )
// addition operator. Character relations must have the same kind. // addition operator. Character relations must have the same kind.
// There are no relations between LOGICAL values. // There are no relations between LOGICAL values.
template<typename T> template <typename T>
struct Relational : public Operation<Relational<T>, LogicalResult, T, T> { struct Relational : public Operation<Relational<T>, LogicalResult, T, T> {
using Result = LogicalResult; using Result = LogicalResult;
using Base = Operation<Relational, LogicalResult, T, T>; using Base = Operation<Relational, LogicalResult, T, T>;
@ -614,13 +615,13 @@ struct Relational : public Operation<Relational<T>, LogicalResult, T, T> {
CLASS_BOILERPLATE(Relational) CLASS_BOILERPLATE(Relational)
Relational( Relational(
RelationalOperator r, const Expr<Operand> &a, const Expr<Operand> &b) RelationalOperator r, const Expr<Operand> &a, const Expr<Operand> &b)
: Base{a, b}, opr{r} {} : Base{a, b}, opr{r} {}
Relational(RelationalOperator r, Expr<Operand> &&a, Expr<Operand> &&b) Relational(RelationalOperator r, Expr<Operand> &&a, Expr<Operand> &&b)
: Base{std::move(a), std::move(b)}, opr{r} {} : Base{std::move(a), std::move(b)}, opr{r} {}
RelationalOperator opr; RelationalOperator opr;
}; };
template<> class Relational<SomeType> { template <> class Relational<SomeType> {
// COMPLEX data are compared piecewise. // COMPLEX data are compared piecewise.
using DirectlyComparableTypes = using DirectlyComparableTypes =
common::CombineTuples<IntegerTypes, RealTypes, CharacterTypes>; common::CombineTuples<IntegerTypes, RealTypes, CharacterTypes>;
@ -645,9 +646,9 @@ extern template struct Relational<SomeType>;
// do not include Relational<> operations as possibilities, // do not include Relational<> operations as possibilities,
// since the results of Relationals are always LogicalResult // since the results of Relationals are always LogicalResult
// (kind=1). // (kind=1).
template<int KIND> template <int KIND>
class Expr<Type<TypeCategory::Logical, KIND>> class Expr<Type<TypeCategory::Logical, KIND>>
: public ExpressionBase<Type<TypeCategory::Logical, KIND>> { : public ExpressionBase<Type<TypeCategory::Logical, KIND>> {
public: public:
using Result = Type<TypeCategory::Logical, KIND>; using Result = Type<TypeCategory::Logical, KIND>;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr) EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
@ -688,7 +689,7 @@ public:
using Result = SomeDerived; using Result = SomeDerived;
explicit StructureConstructor(const semantics::DerivedTypeSpec &spec) explicit StructureConstructor(const semantics::DerivedTypeSpec &spec)
: result_{spec} {} : result_{spec} {}
StructureConstructor( StructureConstructor(
const semantics::DerivedTypeSpec &, const StructureConstructorValues &); const semantics::DerivedTypeSpec &, const StructureConstructorValues &);
StructureConstructor( StructureConstructor(
@ -713,7 +714,7 @@ public:
return values_.end(); return values_.end();
} }
const Expr<SomeType> *Find(const Symbol &) const; // can return null const Expr<SomeType> *Find(const Symbol &) const; // can return null
StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&); StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&);
int Rank() const { return 0; } int Rank() const { return 0; }
@ -726,7 +727,7 @@ private:
}; };
// An expression whose result has a derived type. // An expression whose result has a derived type.
template<> class Expr<SomeDerived> : public ExpressionBase<SomeDerived> { template <> class Expr<SomeDerived> : public ExpressionBase<SomeDerived> {
public: public:
using Result = SomeDerived; using Result = SomeDerived;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr) EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
@ -738,7 +739,7 @@ public:
// A polymorphic expression of known intrinsic type category, but dynamic // A polymorphic expression of known intrinsic type category, but dynamic
// kind, represented as a discriminated union over Expr<Type<CAT, K>> // kind, represented as a discriminated union over Expr<Type<CAT, K>>
// for each supported kind K in the category. // for each supported kind K in the category.
template<TypeCategory CAT> template <TypeCategory CAT>
class Expr<SomeKind<CAT>> : public ExpressionBase<SomeKind<CAT>> { class Expr<SomeKind<CAT>> : public ExpressionBase<SomeKind<CAT>> {
public: public:
using Result = SomeKind<CAT>; using Result = SomeKind<CAT>;
@ -747,7 +748,7 @@ public:
common::MapTemplate<Expr, CategoryTypes<CAT>> u; common::MapTemplate<Expr, CategoryTypes<CAT>> u;
}; };
template<> class Expr<SomeCharacter> : public ExpressionBase<SomeCharacter> { template <> class Expr<SomeCharacter> : public ExpressionBase<SomeCharacter> {
public: public:
using Result = SomeCharacter; using Result = SomeCharacter;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr) EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
@ -780,7 +781,7 @@ using TypelessExpression = std::variant<BOZLiteralConstant, NullPointer,
// A completely generic expression, polymorphic across all of the intrinsic type // A completely generic expression, polymorphic across all of the intrinsic type
// categories and each of their kinds. // categories and each of their kinds.
template<> class Expr<SomeType> : public ExpressionBase<SomeType> { template <> class Expr<SomeType> : public ExpressionBase<SomeType> {
public: public:
using Result = SomeType; using Result = SomeType;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr) EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
@ -790,20 +791,20 @@ public:
// its destructor is externalized to reduce redundant default instances. // its destructor is externalized to reduce redundant default instances.
~Expr(); ~Expr();
template<TypeCategory CAT, int KIND> template <TypeCategory CAT, int KIND>
explicit Expr(const Expr<Type<CAT, KIND>> &x) : u{Expr<SomeKind<CAT>>{x}} {} explicit Expr(const Expr<Type<CAT, KIND>> &x) : u{Expr<SomeKind<CAT>>{x}} {}
template<TypeCategory CAT, int KIND> template <TypeCategory CAT, int KIND>
explicit Expr(Expr<Type<CAT, KIND>> &&x) explicit Expr(Expr<Type<CAT, KIND>> &&x)
: u{Expr<SomeKind<CAT>>{std::move(x)}} {} : u{Expr<SomeKind<CAT>>{std::move(x)}} {}
template<TypeCategory CAT, int KIND> template <TypeCategory CAT, int KIND>
Expr &operator=(const Expr<Type<CAT, KIND>> &x) { Expr &operator=(const Expr<Type<CAT, KIND>> &x) {
u = Expr<SomeKind<CAT>>{x}; u = Expr<SomeKind<CAT>>{x};
return *this; return *this;
} }
template<TypeCategory CAT, int KIND> template <TypeCategory CAT, int KIND>
Expr &operator=(Expr<Type<CAT, KIND>> &&x) { Expr &operator=(Expr<Type<CAT, KIND>> &&x) {
u = Expr<SomeKind<CAT>>{std::move(x)}; u = Expr<SomeKind<CAT>>{std::move(x)};
return *this; return *this;
@ -820,7 +821,7 @@ public:
class Assignment { class Assignment {
public: public:
Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs) Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs)
: lhs(std::move(lhs)), rhs(std::move(rhs)) {} : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
struct Intrinsic {}; struct Intrinsic {};
using BoundsSpec = std::vector<Expr<SubscriptInteger>>; using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
@ -838,9 +839,9 @@ public:
struct GenericExprWrapper { struct GenericExprWrapper {
GenericExprWrapper() {} GenericExprWrapper() {}
explicit GenericExprWrapper(std::optional<Expr<SomeType>> &&x) explicit GenericExprWrapper(std::optional<Expr<SomeType>> &&x)
: v{std::move(x)} {} : v{std::move(x)} {}
~GenericExprWrapper(); ~GenericExprWrapper();
std::optional<Expr<SomeType>> v; // vacant if error std::optional<Expr<SomeType>> v; // vacant if error
}; };
// Like GenericExprWrapper but for analyzed assignments // Like GenericExprWrapper but for analyzed assignments
@ -848,7 +849,7 @@ struct GenericAssignmentWrapper {
GenericAssignmentWrapper() {} GenericAssignmentWrapper() {}
explicit GenericAssignmentWrapper(Assignment &&x) : v{std::move(x)} {} explicit GenericAssignmentWrapper(Assignment &&x) : v{std::move(x)} {}
~GenericAssignmentWrapper(); ~GenericAssignmentWrapper();
std::optional<Assignment> v; // vacant if error std::optional<Assignment> v; // vacant if error
}; };
FOR_EACH_CATEGORY_TYPE(extern template class Expr, ) FOR_EACH_CATEGORY_TYPE(extern template class Expr, )
@ -867,5 +868,5 @@ FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructor, )
FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \ FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \ FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, )
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_EXPRESSION_H_ #endif // FORTRAN_EVALUATE_EXPRESSION_H_

View File

@ -28,11 +28,11 @@ using namespace Fortran::parser::literals;
// be able to extract it. // be able to extract it.
// Note the rvalue reference argument: the rewrites are performed in place // Note the rvalue reference argument: the rewrites are performed in place
// for efficiency. // for efficiency.
template<typename T> Expr<T> Fold(FoldingContext &context, Expr<T> &&expr) { template <typename T> Expr<T> Fold(FoldingContext &context, Expr<T> &&expr) {
return Expr<T>::Rewrite(context, std::move(expr)); return Expr<T>::Rewrite(context, std::move(expr));
} }
template<typename T> template <typename T>
std::optional<Expr<T>> Fold( std::optional<Expr<T>> Fold(
FoldingContext &context, std::optional<Expr<T>> &&expr) { FoldingContext &context, std::optional<Expr<T>> &&expr) {
if (expr) { if (expr) {
@ -46,7 +46,7 @@ std::optional<Expr<T>> Fold(
// an expression, if it has one. It returns a pointer, which is // an expression, if it has one. It returns a pointer, which is
// const-qualified when the expression is so. The value can be // const-qualified when the expression is so. The value can be
// parenthesized. // parenthesized.
template<typename T, typename EXPR> template <typename T, typename EXPR>
auto UnwrapConstantValue(EXPR &expr) -> common::Constify<Constant<T>, EXPR> * { auto UnwrapConstantValue(EXPR &expr) -> common::Constify<Constant<T>, EXPR> * {
if (auto *c{UnwrapExpr<Constant<T>>(expr)}) { if (auto *c{UnwrapExpr<Constant<T>>(expr)}) {
return c; return c;
@ -62,7 +62,7 @@ auto UnwrapConstantValue(EXPR &expr) -> common::Constify<Constant<T>, EXPR> * {
// GetScalarConstantValue() extracts the known scalar constant value of // GetScalarConstantValue() extracts the known scalar constant value of
// an expression, if it has one. The value can be parenthesized. // an expression, if it has one. The value can be parenthesized.
template<typename T, typename EXPR> template <typename T, typename EXPR>
auto GetScalarConstantValue(const EXPR &expr) -> std::optional<Scalar<T>> { auto GetScalarConstantValue(const EXPR &expr) -> std::optional<Scalar<T>> {
if (const Constant<T> *constant{UnwrapConstantValue<T>(expr)}) { if (const Constant<T> *constant{UnwrapConstantValue<T>(expr)}) {
return constant->GetScalarValue(); return constant->GetScalarValue();
@ -74,7 +74,7 @@ auto GetScalarConstantValue(const EXPR &expr) -> std::optional<Scalar<T>> {
// When an expression is a constant integer, ToInt64() extracts its value. // When an expression is a constant integer, ToInt64() extracts its value.
// Ensure that the expression has been folded beforehand when folding might // Ensure that the expression has been folded beforehand when folding might
// be required. // be required.
template<int KIND> template <int KIND>
std::optional<std::int64_t> ToInt64( std::optional<std::int64_t> ToInt64(
const Expr<Type<TypeCategory::Integer, KIND>> &expr) { const Expr<Type<TypeCategory::Integer, KIND>> &expr) {
if (auto scalar{ if (auto scalar{
@ -88,7 +88,7 @@ std::optional<std::int64_t> ToInt64(
std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &); std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &);
std::optional<std::int64_t> ToInt64(const Expr<SomeType> &); std::optional<std::int64_t> ToInt64(const Expr<SomeType> &);
template<typename A> template <typename A>
std::optional<std::int64_t> ToInt64(const std::optional<A> &x) { std::optional<std::int64_t> ToInt64(const std::optional<A> &x) {
if (x) { if (x) {
return ToInt64(*x); return ToInt64(*x);
@ -96,5 +96,5 @@ std::optional<std::int64_t> ToInt64(const std::optional<A> &x) {
return std::nullopt; return std::nullopt;
} }
} }
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_FOLD_H_ #endif // FORTRAN_EVALUATE_FOLD_H_

View File

@ -26,24 +26,25 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<typename A> template <typename A>
auto operator<<(llvm::raw_ostream &o, const A &x) -> decltype(x.AsFortran(o)) { auto operator<<(llvm::raw_ostream &o, const A &x) -> decltype(x.AsFortran(o)) {
return x.AsFortran(o); return x.AsFortran(o);
} }
template<typename A> template <typename A>
auto operator<<(llvm::raw_ostream &o, const A &x) -> decltype(o << x.AsFortran()) { auto operator<<(llvm::raw_ostream &o, const A &x)
-> decltype(o << x.AsFortran()) {
return o << x.AsFortran(); return o << x.AsFortran();
} }
template<typename A, bool COPYABLE> template <typename A, bool COPYABLE>
auto operator<<( auto operator<<(
llvm::raw_ostream &o, const Fortran::common::Indirection<A, COPYABLE> &x) llvm::raw_ostream &o, const Fortran::common::Indirection<A, COPYABLE> &x)
-> decltype(o << x.value()) { -> decltype(o << x.value()) {
return o << x.value(); return o << x.value();
} }
template<typename A> template <typename A>
auto operator<<(llvm::raw_ostream &o, const std::optional<A> &x) auto operator<<(llvm::raw_ostream &o, const std::optional<A> &x)
-> decltype(o << *x) { -> decltype(o << *x) {
if (x) { if (x) {
@ -53,5 +54,5 @@ auto operator<<(llvm::raw_ostream &o, const std::optional<A> &x)
} }
return o; return o;
} }
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_FORMATTING_H_ #endif // FORTRAN_EVALUATE_FORMATTING_H_

View File

@ -28,17 +28,17 @@ class FoldingContext;
using TypeCode = unsigned char; using TypeCode = unsigned char;
template<typename TR, typename... TA> using FuncPointer = TR (*)(TA...); template <typename TR, typename... TA> using FuncPointer = TR (*)(TA...);
// This specific type signature prevents GCC complaining about function casts. // This specific type signature prevents GCC complaining about function casts.
using GenericFunctionPointer = void (*)(void); using GenericFunctionPointer = void (*)(void);
enum class PassBy { Ref, Val }; enum class PassBy { Ref, Val };
template<typename TA, PassBy Pass = PassBy::Ref> struct ArgumentInfo { template <typename TA, PassBy Pass = PassBy::Ref> struct ArgumentInfo {
using Type = TA; using Type = TA;
static constexpr PassBy pass{Pass}; static constexpr PassBy pass{Pass};
}; };
template<typename TR, typename... ArgInfo> struct Signature { template <typename TR, typename... ArgInfo> struct Signature {
// Note valid template argument are of form // Note valid template argument are of form
//<TR, ArgumentInfo<TA, PassBy>...> where TA and TR belong to RuntimeTypes. //<TR, ArgumentInfo<TA, PassBy>...> where TA and TR belong to RuntimeTypes.
// RuntimeTypes is a type union defined in intrinsics-library-templates.h to // RuntimeTypes is a type union defined in intrinsics-library-templates.h to
@ -55,7 +55,7 @@ struct IntrinsicProcedureRuntimeDescription {
const bool isElemental; const bool isElemental;
const GenericFunctionPointer callable; const GenericFunctionPointer callable;
// Construct from description using host independent types (RuntimeTypes) // Construct from description using host independent types (RuntimeTypes)
template<typename TR, typename... ArgInfo> template <typename TR, typename... ArgInfo>
IntrinsicProcedureRuntimeDescription( IntrinsicProcedureRuntimeDescription(
const Signature<TR, ArgInfo...> &signature, bool isElemental = false); const Signature<TR, ArgInfo...> &signature, bool isElemental = false);
}; };
@ -64,19 +64,19 @@ struct IntrinsicProcedureRuntimeDescription {
// constant folding. // constant folding.
struct HostRuntimeIntrinsicProcedure : IntrinsicProcedureRuntimeDescription { struct HostRuntimeIntrinsicProcedure : IntrinsicProcedureRuntimeDescription {
// Construct from runtime pointer with host types (float, double....) // Construct from runtime pointer with host types (float, double....)
template<typename HostTR, typename... HostTA> template <typename HostTR, typename... HostTA>
HostRuntimeIntrinsicProcedure(const std::string &name, HostRuntimeIntrinsicProcedure(const std::string &name,
FuncPointer<HostTR, HostTA...> func, bool isElemental = false); FuncPointer<HostTR, HostTA...> func, bool isElemental = false);
HostRuntimeIntrinsicProcedure( HostRuntimeIntrinsicProcedure(
const IntrinsicProcedureRuntimeDescription &rteProc, const IntrinsicProcedureRuntimeDescription &rteProc,
GenericFunctionPointer handle) GenericFunctionPointer handle)
: IntrinsicProcedureRuntimeDescription{rteProc}, handle{handle} {} : IntrinsicProcedureRuntimeDescription{rteProc}, handle{handle} {}
GenericFunctionPointer handle; GenericFunctionPointer handle;
}; };
// Defines a wrapper type that indirects calls to host runtime functions. // Defines a wrapper type that indirects calls to host runtime functions.
// Valid ConstantContainer are Scalar (only for elementals) and Constant. // Valid ConstantContainer are Scalar (only for elementals) and Constant.
template<template<typename> typename ConstantContainer, typename TR, template <template <typename> typename ConstantContainer, typename TR,
typename... TA> typename... TA>
using HostProcedureWrapper = std::function<ConstantContainer<TR>( using HostProcedureWrapper = std::function<ConstantContainer<TR>(
FoldingContext &, ConstantContainer<TA>...)>; FoldingContext &, ConstantContainer<TA>...)>;
@ -95,7 +95,7 @@ public:
} }
bool HasEquivalentProcedure( bool HasEquivalentProcedure(
const IntrinsicProcedureRuntimeDescription &sym) const; const IntrinsicProcedureRuntimeDescription &sym) const;
template<template<typename> typename ConstantContainer, typename TR, template <template <typename> typename ConstantContainer, typename TR,
typename... TA> typename... TA>
std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>> std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>>
GetHostProcedureWrapper(const std::string &name) const; GetHostProcedureWrapper(const std::string &name) const;
@ -104,5 +104,5 @@ private:
std::multimap<std::string, const HostRuntimeIntrinsicProcedure> procedures_; std::multimap<std::string, const HostRuntimeIntrinsicProcedure> procedures_;
}; };
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_ #endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_

View File

@ -39,7 +39,7 @@ struct CallCharacteristics {
struct SpecificCall { struct SpecificCall {
SpecificCall(SpecificIntrinsic &&si, ActualArguments &&as) SpecificCall(SpecificIntrinsic &&si, ActualArguments &&as)
: specificIntrinsic{std::move(si)}, arguments{std::move(as)} {} : specificIntrinsic{std::move(si)}, arguments{std::move(as)} {}
SpecificIntrinsic specificIntrinsic; SpecificIntrinsic specificIntrinsic;
ActualArguments arguments; ActualArguments arguments;
}; };
@ -47,8 +47,8 @@ struct SpecificCall {
struct SpecificIntrinsicFunctionInterface : public characteristics::Procedure { struct SpecificIntrinsicFunctionInterface : public characteristics::Procedure {
SpecificIntrinsicFunctionInterface( SpecificIntrinsicFunctionInterface(
characteristics::Procedure &&p, std::string n, bool isRestrictedSpecific) characteristics::Procedure &&p, std::string n, bool isRestrictedSpecific)
: characteristics::Procedure{std::move(p)}, genericName{n}, : characteristics::Procedure{std::move(p)}, genericName{n},
isRestrictedSpecific{isRestrictedSpecific} {} isRestrictedSpecific{isRestrictedSpecific} {}
std::string genericName; std::string genericName;
bool isRestrictedSpecific; bool isRestrictedSpecific;
// N.B. If there are multiple arguments, they all have the same type. // N.B. If there are multiple arguments, they all have the same type.
@ -82,7 +82,7 @@ public:
llvm::raw_ostream &Dump(llvm::raw_ostream &) const; llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
private: private:
Implementation *impl_{nullptr}; // owning pointer Implementation *impl_{nullptr}; // owning pointer
}; };
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_INTRINSICS_H_ #endif // FORTRAN_EVALUATE_INTRINSICS_H_

View File

@ -35,7 +35,7 @@ static constexpr std::int64_t ScaledLogBaseTenOfTwo{301029995664};
// class template must be (or look like) an instance of Integer<>; // class template must be (or look like) an instance of Integer<>;
// the second specifies the number of effective bits (binary precision) // the second specifies the number of effective bits (binary precision)
// in the fraction. // in the fraction.
template<typename WORD, int PREC> template <typename WORD, int PREC>
class Real : public common::RealDetails<PREC> { class Real : public common::RealDetails<PREC> {
public: public:
using Word = WORD; using Word = WORD;
@ -49,11 +49,11 @@ public:
static constexpr int bits{Word::bits}; static constexpr int bits{Word::bits};
static_assert(bits >= Details::bits); static_assert(bits >= Details::bits);
using Fraction = Integer<binaryPrecision>; // all bits made explicit using Fraction = Integer<binaryPrecision>; // all bits made explicit
template<typename W, int P> friend class Real; template <typename W, int P> friend class Real;
constexpr Real() {} // +0.0 constexpr Real() {} // +0.0
constexpr Real(const Real &) = default; constexpr Real(const Real &) = default;
constexpr Real(const Word &bits) : word_{bits} {} constexpr Real(const Word &bits) : word_{bits} {}
constexpr Real &operator=(const Real &) = default; constexpr Real &operator=(const Real &) = default;
@ -91,10 +91,10 @@ public:
return Exponent() == 0 && !GetSignificand().IsZero(); return Exponent() == 0 && !GetSignificand().IsZero();
} }
constexpr Real ABS() const { // non-arithmetic, no flags returned constexpr Real ABS() const { // non-arithmetic, no flags returned
return {word_.IBCLR(bits - 1)}; return {word_.IBCLR(bits - 1)};
} }
constexpr Real SetSign(bool toNegative) const { // non-arithmetic constexpr Real SetSign(bool toNegative) const { // non-arithmetic
if (toNegative) { if (toNegative) {
return {word_.IBSET(bits - 1)}; return {word_.IBSET(bits - 1)};
} else { } else {
@ -122,7 +122,7 @@ public:
ValueWithRealFlags<Real> HYPOT( ValueWithRealFlags<Real> HYPOT(
const Real &, Rounding rounding = defaultRounding) const; const Real &, Rounding rounding = defaultRounding) const;
template<typename INT> constexpr INT EXPONENT() const { template <typename INT> constexpr INT EXPONENT() const {
if (Exponent() == maxExponent) { if (Exponent() == maxExponent) {
return INT::HUGE(); return INT::HUGE();
} else { } else {
@ -143,7 +143,7 @@ public:
} }
static constexpr Real TINY() { static constexpr Real TINY() {
Real tiny; Real tiny;
tiny.Normalize(false, 1, Fraction::MASKL(1)); // minimum *normal* number tiny.Normalize(false, 1, Fraction::MASKL(1)); // minimum *normal* number
return tiny; return tiny;
} }
@ -177,17 +177,17 @@ public:
return {infinity}; return {infinity};
} }
template<typename INT> template <typename INT>
static ValueWithRealFlags<Real> FromInteger( static ValueWithRealFlags<Real> FromInteger(
const INT &n, Rounding rounding = defaultRounding) { const INT &n, Rounding rounding = defaultRounding) {
bool isNegative{n.IsNegative()}; bool isNegative{n.IsNegative()};
INT absN{n}; INT absN{n};
if (isNegative) { if (isNegative) {
absN = n.Negate().value; // overflow is safe to ignore absN = n.Negate().value; // overflow is safe to ignore
} }
int leadz{absN.LEADZ()}; int leadz{absN.LEADZ()};
if (leadz >= absN.bits) { if (leadz >= absN.bits) {
return {}; // all bits zero -> +0.0 return {}; // all bits zero -> +0.0
} }
ValueWithRealFlags<Real> result; ValueWithRealFlags<Real> result;
int exponent{exponentBias + absN.bits - leadz - 1}; int exponent{exponentBias + absN.bits - leadz - 1};
@ -211,7 +211,7 @@ public:
common::RoundingMode = common::RoundingMode::ToZero) const; common::RoundingMode = common::RoundingMode::ToZero) const;
// Conversion to an integer (INT(), NINT(), FLOOR(), CEILING()) // Conversion to an integer (INT(), NINT(), FLOOR(), CEILING())
template<typename INT> template <typename INT>
constexpr ValueWithRealFlags<INT> ToInteger( constexpr ValueWithRealFlags<INT> ToInteger(
common::RoundingMode mode = common::RoundingMode::ToZero) const { common::RoundingMode mode = common::RoundingMode::ToZero) const {
ValueWithRealFlags<INT> result; ValueWithRealFlags<INT> result;
@ -226,7 +226,7 @@ public:
RealFlag::Overflow, exponent >= exponentBias + result.value.bits); RealFlag::Overflow, exponent >= exponentBias + result.value.bits);
result.flags |= intPart.flags; result.flags |= intPart.flags;
int shift{ int shift{
exponent - exponentBias - binaryPrecision + 1}; // positive -> left exponent - exponentBias - binaryPrecision + 1}; // positive -> left
result.value = result.value =
result.value.ConvertUnsigned(intPart.value.GetFraction().SHIFTR(-shift)) result.value.ConvertUnsigned(intPart.value.GetFraction().SHIFTR(-shift))
.value.SHIFTL(shift); .value.SHIFTL(shift);
@ -244,7 +244,7 @@ public:
return result; return result;
} }
template<typename A> template <typename A>
static ValueWithRealFlags<Real> Convert( static ValueWithRealFlags<Real> Convert(
const A &x, Rounding rounding = defaultRounding) { const A &x, Rounding rounding = defaultRounding) {
bool isNegative{x.IsNegative()}; bool isNegative{x.IsNegative()};
@ -312,10 +312,11 @@ public:
// Emits a character representation for an equivalent Fortran constant // Emits a character representation for an equivalent Fortran constant
// or parenthesized constant expression that produces this value. // or parenthesized constant expression that produces this value.
llvm::raw_ostream &AsFortran(llvm::raw_ostream &, int kind, bool minimal = false) const; llvm::raw_ostream &AsFortran(
llvm::raw_ostream &, int kind, bool minimal = false) const;
private: private:
using Significand = Integer<significandBits>; // no implicit bit using Significand = Integer<significandBits>; // no implicit bit
constexpr Significand GetSignificand() const { constexpr Significand GetSignificand() const {
return Significand::ConvertUnsigned(word_).value; return Significand::ConvertUnsigned(word_).value;
@ -361,15 +362,15 @@ private:
bool isNegative, int exponent, const Fraction &, Rounding, RoundingBits, bool isNegative, int exponent, const Fraction &, Rounding, RoundingBits,
bool multiply = false); bool multiply = false);
Word word_{}; // an Integer<> Word word_{}; // an Integer<>
}; };
extern template class Real<Integer<16>, 11>; // IEEE half format extern template class Real<Integer<16>, 11>; // IEEE half format
extern template class Real<Integer<16>, 8>; // the "other" half format extern template class Real<Integer<16>, 8>; // the "other" half format
extern template class Real<Integer<32>, 24>; // IEEE single extern template class Real<Integer<32>, 24>; // IEEE single
extern template class Real<Integer<64>, 53>; // IEEE double extern template class Real<Integer<64>, 53>; // IEEE double
extern template class Real<Integer<80>, 64>; // 80387 extended precision extern template class Real<Integer<80>, 64>; // 80387 extended precision
extern template class Real<Integer<128>, 113>; // IEEE quad extern template class Real<Integer<128>, 113>; // IEEE quad
// N.B. No "double-double" support. // N.B. No "double-double" support.
} } // namespace Fortran::evaluate::value
#endif // FORTRAN_EVALUATE_REAL_H_ #endif // FORTRAN_EVALUATE_REAL_H_

View File

@ -19,9 +19,9 @@ class RoundingBits {
public: public:
constexpr RoundingBits( constexpr RoundingBits(
bool guard = false, bool round = false, bool sticky = false) bool guard = false, bool round = false, bool sticky = false)
: guard_{guard}, round_{round}, sticky_{sticky} {} : guard_{guard}, round_{round}, sticky_{sticky} {}
template<typename FRACTION> template <typename FRACTION>
constexpr RoundingBits(const FRACTION &fraction, int rshift) { constexpr RoundingBits(const FRACTION &fraction, int rshift) {
if (rshift > 0 && rshift < fraction.bits + 1) { if (rshift > 0 && rshift < fraction.bits + 1) {
guard_ = fraction.BTEST(rshift - 1); guard_ = fraction.BTEST(rshift - 1);
@ -76,23 +76,30 @@ public:
// fraction, given a rounding mode and a summary of the lost bits. // fraction, given a rounding mode and a summary of the lost bits.
constexpr bool MustRound( constexpr bool MustRound(
Rounding rounding, bool isNegative, bool isOdd) const { Rounding rounding, bool isNegative, bool isOdd) const {
bool round{false}; // to dodge bogus g++ warning about missing return bool round{false}; // to dodge bogus g++ warning about missing return
switch (rounding.mode) { switch (rounding.mode) {
case common::RoundingMode::TiesToEven: case common::RoundingMode::TiesToEven:
round = guard_ && (round_ | sticky_ | isOdd); round = guard_ && (round_ | sticky_ | isOdd);
break; break;
case common::RoundingMode::ToZero: break; case common::RoundingMode::ToZero:
case common::RoundingMode::Down: round = isNegative && !empty(); break; break;
case common::RoundingMode::Up: round = !isNegative && !empty(); break; case common::RoundingMode::Down:
case common::RoundingMode::TiesAwayFromZero: round = guard_; break; round = isNegative && !empty();
break;
case common::RoundingMode::Up:
round = !isNegative && !empty();
break;
case common::RoundingMode::TiesAwayFromZero:
round = guard_;
break;
} }
return round; return round;
} }
private: private:
bool guard_{false}; // 0.5 * ulp (unit in lowest place) bool guard_{false}; // 0.5 * ulp (unit in lowest place)
bool round_{false}; // 0.25 * ulp bool round_{false}; // 0.25 * ulp
bool sticky_{false}; // true if any lesser-valued bit would be set bool sticky_{false}; // true if any lesser-valued bit would be set
}; };
} } // namespace Fortran::evaluate::value
#endif // FORTRAN_EVALUATE_ROUNDING_BITS_H_ #endif // FORTRAN_EVALUATE_ROUNDING_BITS_H_

View File

@ -53,7 +53,8 @@ std::optional<ConstantSubscripts> AsConstantExtents(
inline int GetRank(const Shape &s) { return static_cast<int>(s.size()); } inline int GetRank(const Shape &s) { return static_cast<int>(s.size()); }
template<typename A> std::optional<Shape> GetShape(FoldingContext &, const A &); template <typename A>
std::optional<Shape> GetShape(FoldingContext &, const A &);
// The dimension argument to these inquiries is zero-based, // The dimension argument to these inquiries is zero-based,
// unlike the DIM= arguments to many intrinsics. // unlike the DIM= arguments to many intrinsics.
@ -83,7 +84,7 @@ MaybeExtentExpr GetSize(Shape &&);
bool ContainsAnyImpliedDoIndex(const ExtentExpr &); bool ContainsAnyImpliedDoIndex(const ExtentExpr &);
class GetShapeHelper class GetShapeHelper
: public AnyTraverse<GetShapeHelper, std::optional<Shape>> { : public AnyTraverse<GetShapeHelper, std::optional<Shape>> {
public: public:
using Result = std::optional<Shape>; using Result = std::optional<Shape>;
using Base = AnyTraverse<GetShapeHelper, Result>; using Base = AnyTraverse<GetShapeHelper, Result>;
@ -92,7 +93,7 @@ public:
Result operator()(const ImpliedDoIndex &) const { return Scalar(); } Result operator()(const ImpliedDoIndex &) const { return Scalar(); }
Result operator()(const DescriptorInquiry &) const { return Scalar(); } Result operator()(const DescriptorInquiry &) const { return Scalar(); }
template<int KIND> Result operator()(const TypeParamInquiry<KIND> &) const { template <int KIND> Result operator()(const TypeParamInquiry<KIND> &) const {
return Scalar(); return Scalar();
} }
Result operator()(const BOZLiteralConstant &) const { return Scalar(); } Result operator()(const BOZLiteralConstant &) const { return Scalar(); }
@ -101,7 +102,7 @@ public:
} }
Result operator()(const StructureConstructor &) const { return Scalar(); } Result operator()(const StructureConstructor &) const { return Scalar(); }
template<typename T> Result operator()(const Constant<T> &c) const { template <typename T> Result operator()(const Constant<T> &c) const {
return AsShape(c.SHAPE()); return AsShape(c.SHAPE());
} }
@ -112,11 +113,11 @@ public:
Result operator()(const Substring &) const; Result operator()(const Substring &) const;
Result operator()(const ProcedureRef &) const; Result operator()(const ProcedureRef &) const;
template<typename T> template <typename T>
Result operator()(const ArrayConstructor<T> &aconst) const { Result operator()(const ArrayConstructor<T> &aconst) const {
return Shape{GetArrayConstructorExtent(aconst)}; return Shape{GetArrayConstructorExtent(aconst)};
} }
template<typename D, typename R, typename LO, typename RO> template <typename D, typename R, typename LO, typename RO>
Result operator()(const Operation<D, R, LO, RO> &operation) const { Result operator()(const Operation<D, R, LO, RO> &operation) const {
if (operation.right().Rank() > 0) { if (operation.right().Rank() > 0) {
return (*this)(operation.right()); return (*this)(operation.right());
@ -128,7 +129,7 @@ public:
private: private:
static Result Scalar() { return Shape{}; } static Result Scalar() { return Shape{}; }
template<typename T> template <typename T>
MaybeExtentExpr GetArrayConstructorValueExtent( MaybeExtentExpr GetArrayConstructorValueExtent(
const ArrayConstructorValue<T> &value) const { const ArrayConstructorValue<T> &value) const {
return std::visit( return std::visit(
@ -159,7 +160,7 @@ private:
value.u); value.u);
} }
template<typename T> template <typename T>
MaybeExtentExpr GetArrayConstructorExtent( MaybeExtentExpr GetArrayConstructorExtent(
const ArrayConstructorValues<T> &values) const { const ArrayConstructorValues<T> &values) const {
ExtentExpr result{0}; ExtentExpr result{0};
@ -176,7 +177,7 @@ private:
FoldingContext &context_; FoldingContext &context_;
}; };
template<typename A> template <typename A>
std::optional<Shape> GetShape(FoldingContext &context, const A &x) { std::optional<Shape> GetShape(FoldingContext &context, const A &x) {
return GetShapeHelper{context}(x); return GetShapeHelper{context}(x);
} }
@ -187,5 +188,5 @@ bool CheckConformance(parser::ContextualMessages &, const Shape &left,
const Shape &right, const char *leftIs = "left operand", const Shape &right, const char *leftIs = "left operand",
const char *rightIs = "right operand"); const char *rightIs = "right operand");
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_SHAPE_H_ #endif // FORTRAN_EVALUATE_SHAPE_H_

View File

@ -78,5 +78,5 @@ private:
int itemBytes_{1}; int itemBytes_{1};
std::vector<std::uint8_t> data_; std::vector<std::uint8_t> data_;
}; };
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_STATIC_DATA_H_ #endif // FORTRAN_EVALUATE_STATIC_DATA_H_

View File

@ -41,42 +41,43 @@
#include <type_traits> #include <type_traits>
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<typename Visitor, typename Result> class Traverse { template <typename Visitor, typename Result> class Traverse {
public: public:
explicit Traverse(Visitor &v) : visitor_{v} {} explicit Traverse(Visitor &v) : visitor_{v} {}
// Packaging // Packaging
template<typename A, bool C> template <typename A, bool C>
Result operator()(const common::Indirection<A, C> &x) const { Result operator()(const common::Indirection<A, C> &x) const {
return visitor_(x.value()); return visitor_(x.value());
} }
template<typename A> Result operator()(SymbolRef x) const { template <typename A> Result operator()(SymbolRef x) const {
return visitor_(*x); return visitor_(*x);
} }
template<typename A> Result operator()(const std::unique_ptr<A> &x) const { template <typename A> Result operator()(const std::unique_ptr<A> &x) const {
return visitor_(x.get()); return visitor_(x.get());
} }
template<typename A> Result operator()(const std::shared_ptr<A> &x) const { template <typename A> Result operator()(const std::shared_ptr<A> &x) const {
return visitor_(x.get()); return visitor_(x.get());
} }
template<typename A> Result operator()(const A *x) const { template <typename A> Result operator()(const A *x) const {
if (x) { if (x) {
return visitor_(*x); return visitor_(*x);
} else { } else {
return visitor_.Default(); return visitor_.Default();
} }
} }
template<typename A> Result operator()(const std::optional<A> &x) const { template <typename A> Result operator()(const std::optional<A> &x) const {
if (x) { if (x) {
return visitor_(*x); return visitor_(*x);
} else { } else {
return visitor_.Default(); return visitor_.Default();
} }
} }
template<typename... A> Result operator()(const std::variant<A...> &u) const { template <typename... A>
Result operator()(const std::variant<A...> &u) const {
return std::visit(visitor_, u); return std::visit(visitor_, u);
} }
template<typename A> Result operator()(const std::vector<A> &x) const { template <typename A> Result operator()(const std::vector<A> &x) const {
return CombineContents(x); return CombineContents(x);
} }
@ -85,7 +86,7 @@ public:
return visitor_.Default(); return visitor_.Default();
} }
Result operator()(const NullPointer &) const { return visitor_.Default(); } Result operator()(const NullPointer &) const { return visitor_.Default(); }
template<typename T> Result operator()(const Constant<T> &x) const { template <typename T> Result operator()(const Constant<T> &x) const {
if constexpr (T::category == TypeCategory::Derived) { if constexpr (T::category == TypeCategory::Derived) {
std::optional<Result> result; std::optional<Result> result;
for (const StructureConstructorValues &map : x.values()) { for (const StructureConstructorValues &map : x.values()) {
@ -119,7 +120,7 @@ public:
return visitor_(x.GetFirstSymbol()); return visitor_(x.GetFirstSymbol());
} }
} }
template<int KIND> Result operator()(const TypeParamInquiry<KIND> &x) const { template <int KIND> Result operator()(const TypeParamInquiry<KIND> &x) const {
return visitor_(x.base()); return visitor_(x.base());
} }
Result operator()(const Triplet &x) const { Result operator()(const Triplet &x) const {
@ -140,10 +141,10 @@ public:
Result operator()(const ComplexPart &x) const { Result operator()(const ComplexPart &x) const {
return visitor_(x.complex()); return visitor_(x.complex());
} }
template<typename T> Result operator()(const Designator<T> &x) const { template <typename T> Result operator()(const Designator<T> &x) const {
return visitor_(x.u); return visitor_(x.u);
} }
template<typename T> Result operator()(const Variable<T> &x) const { template <typename T> Result operator()(const Variable<T> &x) const {
return visitor_(x.u); return visitor_(x.u);
} }
Result operator()(const DescriptorInquiry &x) const { Result operator()(const DescriptorInquiry &x) const {
@ -173,20 +174,20 @@ public:
Result operator()(const ProcedureRef &x) const { Result operator()(const ProcedureRef &x) const {
return Combine(x.proc(), x.arguments()); return Combine(x.proc(), x.arguments());
} }
template<typename T> Result operator()(const FunctionRef<T> &x) const { template <typename T> Result operator()(const FunctionRef<T> &x) const {
return visitor_(static_cast<const ProcedureRef &>(x)); return visitor_(static_cast<const ProcedureRef &>(x));
} }
// Other primaries // Other primaries
template<typename T> template <typename T>
Result operator()(const ArrayConstructorValue<T> &x) const { Result operator()(const ArrayConstructorValue<T> &x) const {
return visitor_(x.u); return visitor_(x.u);
} }
template<typename T> template <typename T>
Result operator()(const ArrayConstructorValues<T> &x) const { Result operator()(const ArrayConstructorValues<T> &x) const {
return CombineContents(x); return CombineContents(x);
} }
template<typename T> Result operator()(const ImpliedDo<T> &x) const { template <typename T> Result operator()(const ImpliedDo<T> &x) const {
return Combine(x.lower(), x.upper(), x.stride(), x.values()); return Combine(x.lower(), x.upper(), x.stride(), x.values());
} }
Result operator()(const semantics::ParamValue &x) const { Result operator()(const semantics::ParamValue &x) const {
@ -207,23 +208,23 @@ public:
} }
// Operations and wrappers // Operations and wrappers
template<typename D, typename R, typename O> template <typename D, typename R, typename O>
Result operator()(const Operation<D, R, O> &op) const { Result operator()(const Operation<D, R, O> &op) const {
return visitor_(op.left()); return visitor_(op.left());
} }
template<typename D, typename R, typename LO, typename RO> template <typename D, typename R, typename LO, typename RO>
Result operator()(const Operation<D, R, LO, RO> &op) const { Result operator()(const Operation<D, R, LO, RO> &op) const {
return Combine(op.left(), op.right()); return Combine(op.left(), op.right());
} }
Result operator()(const Relational<SomeType> &x) const { Result operator()(const Relational<SomeType> &x) const {
return visitor_(x.u); return visitor_(x.u);
} }
template<typename T> Result operator()(const Expr<T> &x) const { template <typename T> Result operator()(const Expr<T> &x) const {
return visitor_(x.u); return visitor_(x.u);
} }
private: private:
template<typename ITER> Result CombineRange(ITER iter, ITER end) const { template <typename ITER> Result CombineRange(ITER iter, ITER end) const {
if (iter == end) { if (iter == end) {
return visitor_.Default(); return visitor_.Default();
} else { } else {
@ -235,11 +236,11 @@ private:
} }
} }
template<typename A> Result CombineContents(const A &x) const { template <typename A> Result CombineContents(const A &x) const {
return CombineRange(x.begin(), x.end()); return CombineRange(x.begin(), x.end());
} }
template<typename A, typename... Bs> template <typename A, typename... Bs>
Result Combine(const A &x, const Bs &... ys) const { Result Combine(const A &x, const Bs &... ys) const {
if constexpr (sizeof...(Bs) == 0) { if constexpr (sizeof...(Bs) == 0) {
return visitor_(x); return visitor_(x);
@ -253,7 +254,7 @@ private:
// For validity checks across an expression: if any operator() result is // For validity checks across an expression: if any operator() result is
// false, so is the overall result. // false, so is the overall result.
template<typename Visitor, bool DefaultValue, template <typename Visitor, bool DefaultValue,
typename Base = Traverse<Visitor, bool>> typename Base = Traverse<Visitor, bool>>
struct AllTraverse : public Base { struct AllTraverse : public Base {
AllTraverse(Visitor &v) : Base{v} {} AllTraverse(Visitor &v) : Base{v} {}
@ -265,7 +266,7 @@ struct AllTraverse : public Base {
// For searches over an expression: the first operator() result that // For searches over an expression: the first operator() result that
// is truthful is the final result. Works for Booleans, pointers, // is truthful is the final result. Works for Booleans, pointers,
// and std::optional<>. // and std::optional<>.
template<typename Visitor, typename Result = bool, template <typename Visitor, typename Result = bool,
typename Base = Traverse<Visitor, Result>> typename Base = Traverse<Visitor, Result>>
struct AnyTraverse : public Base { struct AnyTraverse : public Base {
AnyTraverse(Visitor &v) : Base{v} {} AnyTraverse(Visitor &v) : Base{v} {}
@ -280,7 +281,8 @@ struct AnyTraverse : public Base {
} }
}; };
template<typename Visitor, typename Set, typename Base = Traverse<Visitor, Set>> template <typename Visitor, typename Set,
typename Base = Traverse<Visitor, Set>>
struct SetTraverse : public Base { struct SetTraverse : public Base {
SetTraverse(Visitor &v) : Base{v} {} SetTraverse(Visitor &v) : Base{v} {}
using Base::operator(); using Base::operator();
@ -298,5 +300,5 @@ struct SetTraverse : public Base {
} }
}; };
} } // namespace Fortran::evaluate
#endif #endif

View File

@ -37,7 +37,7 @@ class DerivedTypeSpec;
class ParamValue; class ParamValue;
class Symbol; class Symbol;
bool IsDescriptor(const Symbol &); bool IsDescriptor(const Symbol &);
} } // namespace Fortran::semantics
namespace Fortran::evaluate { namespace Fortran::evaluate {
@ -45,7 +45,7 @@ using common::TypeCategory;
// Specific intrinsic types are represented by specializations of // Specific intrinsic types are represented by specializations of
// this class template Type<CATEGORY, KIND>. // this class template Type<CATEGORY, KIND>.
template<TypeCategory CATEGORY, int KIND = 0> class Type; template <TypeCategory CATEGORY, int KIND = 0> class Type;
using SubscriptInteger = Type<TypeCategory::Integer, 8>; using SubscriptInteger = Type<TypeCategory::Integer, 8>;
using CInteger = Type<TypeCategory::Integer, 4>; using CInteger = Type<TypeCategory::Integer, 4>;
@ -65,10 +65,12 @@ static constexpr bool IsValidKindOfIntrinsicType(
case TypeCategory::Complex: case TypeCategory::Complex:
return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 || return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 ||
kind == 16; kind == 16;
case TypeCategory::Character: return kind == 1 || kind == 2 || kind == 4; case TypeCategory::Character:
return kind == 1 || kind == 2 || kind == 4;
case TypeCategory::Logical: case TypeCategory::Logical:
return kind == 1 || kind == 2 || kind == 4 || kind == 8; return kind == 1 || kind == 2 || kind == 4 || kind == 8;
default: return false; default:
return false;
} }
} }
@ -86,12 +88,12 @@ public:
CHECK(IsValidKindOfIntrinsicType(category_, kind_)); CHECK(IsValidKindOfIntrinsicType(category_, kind_));
} }
constexpr DynamicType(int k, const semantics::ParamValue &pv) constexpr DynamicType(int k, const semantics::ParamValue &pv)
: category_{TypeCategory::Character}, kind_{k}, charLength_{&pv} { : category_{TypeCategory::Character}, kind_{k}, charLength_{&pv} {
CHECK(IsValidKindOfIntrinsicType(category_, kind_)); CHECK(IsValidKindOfIntrinsicType(category_, kind_));
} }
explicit constexpr DynamicType( explicit constexpr DynamicType(
const semantics::DerivedTypeSpec &dt, bool poly = false) const semantics::DerivedTypeSpec &dt, bool poly = false)
: category_{TypeCategory::Derived}, derived_{&dt} { : category_{TypeCategory::Derived}, derived_{&dt} {
if (poly) { if (poly) {
kind_ = ClassKind; kind_ = ClassKind;
} }
@ -113,7 +115,7 @@ public:
result.category_ = TypeCategory::Derived; result.category_ = TypeCategory::Derived;
result.kind_ = ClassKind; result.kind_ = ClassKind;
result.derived_ = nullptr; result.derived_ = nullptr;
return result; // CLASS(*) return result; // CLASS(*)
} }
static constexpr DynamicType AssumedType() { static constexpr DynamicType AssumedType() {
@ -121,7 +123,7 @@ public:
result.category_ = TypeCategory::Derived; result.category_ = TypeCategory::Derived;
result.kind_ = AssumedTypeKind; result.kind_ = AssumedTypeKind;
result.derived_ = nullptr; result.derived_ = nullptr;
return result; // TYPE(*) return result; // TYPE(*)
} }
// Comparison is deep -- type parameters are compared independently. // Comparison is deep -- type parameters are compared independently.
@ -145,13 +147,13 @@ public:
bool IsAssumedLengthCharacter() const; bool IsAssumedLengthCharacter() const;
bool IsUnknownLengthCharacter() const; bool IsUnknownLengthCharacter() const;
bool IsTypelessIntrinsicArgument() const; bool IsTypelessIntrinsicArgument() const;
constexpr bool IsAssumedType() const { // TYPE(*) constexpr bool IsAssumedType() const { // TYPE(*)
return kind_ == AssumedTypeKind; return kind_ == AssumedTypeKind;
} }
constexpr bool IsPolymorphic() const { // TYPE(*) or CLASS() constexpr bool IsPolymorphic() const { // TYPE(*) or CLASS()
return kind_ == ClassKind || IsAssumedType(); return kind_ == ClassKind || IsAssumedType();
} }
constexpr bool IsUnlimitedPolymorphic() const { // TYPE(*) or CLASS(*) constexpr bool IsUnlimitedPolymorphic() const { // TYPE(*) or CLASS(*)
return IsPolymorphic() && !derived_; return IsPolymorphic() && !derived_;
} }
constexpr const semantics::DerivedTypeSpec &GetDerivedTypeSpec() const { constexpr const semantics::DerivedTypeSpec &GetDerivedTypeSpec() const {
@ -174,17 +176,17 @@ public:
static std::optional<DynamicType> From(const semantics::DeclTypeSpec &); static std::optional<DynamicType> From(const semantics::DeclTypeSpec &);
static std::optional<DynamicType> From(const semantics::Symbol &); static std::optional<DynamicType> From(const semantics::Symbol &);
template<typename A> static std::optional<DynamicType> From(const A &x) { template <typename A> static std::optional<DynamicType> From(const A &x) {
return x.GetType(); return x.GetType();
} }
template<typename A> static std::optional<DynamicType> From(const A *p) { template <typename A> static std::optional<DynamicType> From(const A *p) {
if (!p) { if (!p) {
return std::nullopt; return std::nullopt;
} else { } else {
return From(*p); return From(*p);
} }
} }
template<typename A> template <typename A>
static std::optional<DynamicType> From(const std::optional<A> &x) { static std::optional<DynamicType> From(const std::optional<A> &x) {
if (x) { if (x) {
return From(*x); return From(*x);
@ -196,17 +198,17 @@ public:
private: private:
// Special kind codes are used to distinguish the following Fortran types. // Special kind codes are used to distinguish the following Fortran types.
enum SpecialKind { enum SpecialKind {
TypelessKind = -1, // BOZ actual argument to intrinsic function TypelessKind = -1, // BOZ actual argument to intrinsic function
ClassKind = -2, // CLASS(T) or CLASS(*) ClassKind = -2, // CLASS(T) or CLASS(*)
AssumedTypeKind = -3, // TYPE(*) AssumedTypeKind = -3, // TYPE(*)
}; };
constexpr DynamicType() {} constexpr DynamicType() {}
TypeCategory category_{TypeCategory::Derived}; // overridable default TypeCategory category_{TypeCategory::Derived}; // overridable default
int kind_{0}; int kind_{0};
const semantics::ParamValue *charLength_{nullptr}; const semantics::ParamValue *charLength_{nullptr};
const semantics::DerivedTypeSpec *derived_{nullptr}; // TYPE(T), CLASS(T) const semantics::DerivedTypeSpec *derived_{nullptr}; // TYPE(T), CLASS(T)
}; };
// Return the DerivedTypeSpec of a DynamicType if it has one. // Return the DerivedTypeSpec of a DynamicType if it has one.
@ -216,7 +218,7 @@ const semantics::DerivedTypeSpec *GetDerivedTypeSpec(
std::string DerivedTypeSpecAsFortran(const semantics::DerivedTypeSpec &); std::string DerivedTypeSpecAsFortran(const semantics::DerivedTypeSpec &);
template<TypeCategory CATEGORY, int KIND = 0> struct TypeBase { template <TypeCategory CATEGORY, int KIND = 0> struct TypeBase {
static constexpr TypeCategory category{CATEGORY}; static constexpr TypeCategory category{CATEGORY};
static constexpr int kind{KIND}; static constexpr int kind{KIND};
constexpr bool operator==(const TypeBase &) const { return true; } constexpr bool operator==(const TypeBase &) const { return true; }
@ -224,15 +226,15 @@ template<TypeCategory CATEGORY, int KIND = 0> struct TypeBase {
static std::string AsFortran() { return GetType().AsFortran(); } static std::string AsFortran() { return GetType().AsFortran(); }
}; };
template<int KIND> template <int KIND>
class Type<TypeCategory::Integer, KIND> class Type<TypeCategory::Integer, KIND>
: public TypeBase<TypeCategory::Integer, KIND> { : public TypeBase<TypeCategory::Integer, KIND> {
public: public:
using Scalar = value::Integer<8 * KIND>; using Scalar = value::Integer<8 * KIND>;
}; };
// REAL(KIND=2) is IEEE half-precision (16 bits) // REAL(KIND=2) is IEEE half-precision (16 bits)
template<> template <>
class Type<TypeCategory::Real, 2> : public TypeBase<TypeCategory::Real, 2> { class Type<TypeCategory::Real, 2> : public TypeBase<TypeCategory::Real, 2> {
public: public:
using Scalar = using Scalar =
@ -241,7 +243,7 @@ public:
// REAL(KIND=3) identifies the "other" half-precision format, which is // REAL(KIND=3) identifies the "other" half-precision format, which is
// basically REAL(4) without its least-order 16 fraction bits. // basically REAL(4) without its least-order 16 fraction bits.
template<> template <>
class Type<TypeCategory::Real, 3> : public TypeBase<TypeCategory::Real, 3> { class Type<TypeCategory::Real, 3> : public TypeBase<TypeCategory::Real, 3> {
public: public:
using Scalar = using Scalar =
@ -249,7 +251,7 @@ public:
}; };
// REAL(KIND=4) is IEEE-754 single precision (32 bits) // REAL(KIND=4) is IEEE-754 single precision (32 bits)
template<> template <>
class Type<TypeCategory::Real, 4> : public TypeBase<TypeCategory::Real, 4> { class Type<TypeCategory::Real, 4> : public TypeBase<TypeCategory::Real, 4> {
public: public:
using Scalar = using Scalar =
@ -257,7 +259,7 @@ public:
}; };
// REAL(KIND=8) is IEEE double precision (64 bits) // REAL(KIND=8) is IEEE double precision (64 bits)
template<> template <>
class Type<TypeCategory::Real, 8> : public TypeBase<TypeCategory::Real, 8> { class Type<TypeCategory::Real, 8> : public TypeBase<TypeCategory::Real, 8> {
public: public:
using Scalar = using Scalar =
@ -265,52 +267,52 @@ public:
}; };
// REAL(KIND=10) is x87 FPU extended precision (80 bits, all explicit) // REAL(KIND=10) is x87 FPU extended precision (80 bits, all explicit)
template<> template <>
class Type<TypeCategory::Real, 10> : public TypeBase<TypeCategory::Real, 10> { class Type<TypeCategory::Real, 10> : public TypeBase<TypeCategory::Real, 10> {
public: public:
using Scalar = value::Real<value::Integer<80>, 64>; using Scalar = value::Real<value::Integer<80>, 64>;
}; };
// REAL(KIND=16) is IEEE quad precision (128 bits) // REAL(KIND=16) is IEEE quad precision (128 bits)
template<> template <>
class Type<TypeCategory::Real, 16> : public TypeBase<TypeCategory::Real, 16> { class Type<TypeCategory::Real, 16> : public TypeBase<TypeCategory::Real, 16> {
public: public:
using Scalar = value::Real<value::Integer<128>, 113>; using Scalar = value::Real<value::Integer<128>, 113>;
}; };
// The KIND type parameter on COMPLEX is the kind of each of its components. // The KIND type parameter on COMPLEX is the kind of each of its components.
template<int KIND> template <int KIND>
class Type<TypeCategory::Complex, KIND> class Type<TypeCategory::Complex, KIND>
: public TypeBase<TypeCategory::Complex, KIND> { : public TypeBase<TypeCategory::Complex, KIND> {
public: public:
using Part = Type<TypeCategory::Real, KIND>; using Part = Type<TypeCategory::Real, KIND>;
using Scalar = value::Complex<typename Part::Scalar>; using Scalar = value::Complex<typename Part::Scalar>;
}; };
template<> template <>
class Type<TypeCategory::Character, 1> class Type<TypeCategory::Character, 1>
: public TypeBase<TypeCategory::Character, 1> { : public TypeBase<TypeCategory::Character, 1> {
public: public:
using Scalar = std::string; using Scalar = std::string;
}; };
template<> template <>
class Type<TypeCategory::Character, 2> class Type<TypeCategory::Character, 2>
: public TypeBase<TypeCategory::Character, 2> { : public TypeBase<TypeCategory::Character, 2> {
public: public:
using Scalar = std::u16string; using Scalar = std::u16string;
}; };
template<> template <>
class Type<TypeCategory::Character, 4> class Type<TypeCategory::Character, 4>
: public TypeBase<TypeCategory::Character, 4> { : public TypeBase<TypeCategory::Character, 4> {
public: public:
using Scalar = std::u32string; using Scalar = std::u32string;
}; };
template<int KIND> template <int KIND>
class Type<TypeCategory::Logical, KIND> class Type<TypeCategory::Logical, KIND>
: public TypeBase<TypeCategory::Logical, KIND> { : public TypeBase<TypeCategory::Logical, KIND> {
public: public:
using Scalar = value::Logical<8 * KIND>; using Scalar = value::Logical<8 * KIND>;
}; };
@ -318,7 +320,7 @@ public:
// Type functions // Type functions
// Given a specific type, find the type of the same kind in another category. // Given a specific type, find the type of the same kind in another category.
template<TypeCategory CATEGORY, typename T> template <TypeCategory CATEGORY, typename T>
using SameKind = Type<CATEGORY, std::decay_t<T>::kind>; using SameKind = Type<CATEGORY, std::decay_t<T>::kind>;
// Many expressions, including subscripts, CHARACTER lengths, array bounds, // Many expressions, including subscripts, CHARACTER lengths, array bounds,
@ -329,16 +331,16 @@ using IndirectSubscriptIntegerExpr =
// For each intrinsic type category CAT, CategoryTypes<CAT> is an instantiation // For each intrinsic type category CAT, CategoryTypes<CAT> is an instantiation
// of std::tuple<Type<CAT, K>> that comprises every kind value K in that // of std::tuple<Type<CAT, K>> that comprises every kind value K in that
// category that could possibly be supported on any target. // category that could possibly be supported on any target.
template<TypeCategory CATEGORY, int KIND> template <TypeCategory CATEGORY, int KIND>
using CategoryKindTuple = using CategoryKindTuple =
std::conditional_t<IsValidKindOfIntrinsicType(CATEGORY, KIND), std::conditional_t<IsValidKindOfIntrinsicType(CATEGORY, KIND),
std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>; std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>;
template<TypeCategory CATEGORY, int... KINDS> template <TypeCategory CATEGORY, int... KINDS>
using CategoryTypesHelper = using CategoryTypesHelper =
common::CombineTuples<CategoryKindTuple<CATEGORY, KINDS>...>; common::CombineTuples<CategoryKindTuple<CATEGORY, KINDS>...>;
template<TypeCategory CATEGORY> template <TypeCategory CATEGORY>
using CategoryTypes = CategoryTypesHelper<CATEGORY, 1, 2, 3, 4, 8, 10, 16, 32>; using CategoryTypes = CategoryTypesHelper<CATEGORY, 1, 2, 3, 4, 8, 10, 16, 32>;
using IntegerTypes = CategoryTypes<TypeCategory::Integer>; using IntegerTypes = CategoryTypes<TypeCategory::Integer>;
@ -355,18 +357,18 @@ using LengthlessIntrinsicTypes =
common::CombineTuples<NumericTypes, LogicalTypes>; common::CombineTuples<NumericTypes, LogicalTypes>;
// Predicates: does a type represent a specific intrinsic type? // Predicates: does a type represent a specific intrinsic type?
template<typename T> template <typename T>
constexpr bool IsSpecificIntrinsicType{common::HasMember<T, AllIntrinsicTypes>}; constexpr bool IsSpecificIntrinsicType{common::HasMember<T, AllIntrinsicTypes>};
// Predicate: is a type an intrinsic type that is completely characterized // Predicate: is a type an intrinsic type that is completely characterized
// by its category and kind parameter value, or might it have a derived type // by its category and kind parameter value, or might it have a derived type
// &/or a length type parameter? // &/or a length type parameter?
template<typename T> template <typename T>
constexpr bool IsLengthlessIntrinsicType{ constexpr bool IsLengthlessIntrinsicType{
common::HasMember<T, LengthlessIntrinsicTypes>}; common::HasMember<T, LengthlessIntrinsicTypes>};
// Represents a type of any supported kind within a particular category. // Represents a type of any supported kind within a particular category.
template<TypeCategory CATEGORY> struct SomeKind { template <TypeCategory CATEGORY> struct SomeKind {
static constexpr TypeCategory category{CATEGORY}; static constexpr TypeCategory category{CATEGORY};
constexpr bool operator==(const SomeKind &) const { return true; } constexpr bool operator==(const SomeKind &) const { return true; }
}; };
@ -384,16 +386,16 @@ struct SomeType {};
class StructureConstructor; class StructureConstructor;
// Represents any derived type, polymorphic or not, as well as CLASS(*). // Represents any derived type, polymorphic or not, as well as CLASS(*).
template<> class SomeKind<TypeCategory::Derived> { template <> class SomeKind<TypeCategory::Derived> {
public: public:
static constexpr TypeCategory category{TypeCategory::Derived}; static constexpr TypeCategory category{TypeCategory::Derived};
using Scalar = StructureConstructor; using Scalar = StructureConstructor;
constexpr SomeKind() {} // CLASS(*) constexpr SomeKind() {} // CLASS(*)
constexpr explicit SomeKind(const semantics::DerivedTypeSpec &dts) constexpr explicit SomeKind(const semantics::DerivedTypeSpec &dts)
: derivedTypeSpec_{&dts} {} : derivedTypeSpec_{&dts} {}
constexpr explicit SomeKind(const DynamicType &dt) constexpr explicit SomeKind(const DynamicType &dt)
: SomeKind(dt.GetDerivedTypeSpec()) {} : SomeKind(dt.GetDerivedTypeSpec()) {}
CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(SomeKind) CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(SomeKind)
bool IsUnlimitedPolymorphic() const { return !derivedTypeSpec_; } bool IsUnlimitedPolymorphic() const { return !derivedTypeSpec_; }
@ -427,13 +429,13 @@ using SomeCategory = std::tuple<SomeInteger, SomeReal, SomeComplex,
using AllTypes = using AllTypes =
common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>; common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>;
template<typename T> using Scalar = typename std::decay_t<T>::Scalar; template <typename T> using Scalar = typename std::decay_t<T>::Scalar;
// When Scalar<T> is S, then TypeOf<S> is T. // When Scalar<T> is S, then TypeOf<S> is T.
// TypeOf is implemented by scanning all supported types for a match // TypeOf is implemented by scanning all supported types for a match
// with Type<T>::Scalar. // with Type<T>::Scalar.
template<typename CONST> struct TypeOfHelper { template <typename CONST> struct TypeOfHelper {
template<typename T> struct Predicate { template <typename T> struct Predicate {
static constexpr bool value() { static constexpr bool value() {
return std::is_same_v<std::decay_t<CONST>, return std::is_same_v<std::decay_t<CONST>,
std::decay_t<typename T::Scalar>>; std::decay_t<typename T::Scalar>>;
@ -445,7 +447,7 @@ template<typename CONST> struct TypeOfHelper {
std::tuple_element_t<index, AllIntrinsicTypes>, void>; std::tuple_element_t<index, AllIntrinsicTypes>, void>;
}; };
template<typename CONST> using TypeOf = typename TypeOfHelper<CONST>::type; template <typename CONST> using TypeOf = typename TypeOfHelper<CONST>::type;
int SelectedCharKind(const std::string &, int defaultKind); int SelectedCharKind(const std::string &, int defaultKind);
int SelectedIntKind(std::int64_t precision = 0); int SelectedIntKind(std::int64_t precision = 0);
@ -511,5 +513,5 @@ bool IsKindTypeParameter(const semantics::Symbol &);
#define FOR_EACH_TYPE_AND_KIND(PREFIX, SUFFIX) \ #define FOR_EACH_TYPE_AND_KIND(PREFIX, SUFFIX) \
FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \ FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX) FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX)
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_TYPE_H_ #endif // FORTRAN_EVALUATE_TYPE_H_

View File

@ -44,7 +44,7 @@ using SymbolVector = std::vector<SymbolRef>;
// Forward declarations // Forward declarations
struct DataRef; struct DataRef;
template<typename T> struct Variable; template <typename T> struct Variable;
// Reference a base object in memory. This can be a Fortran symbol, // Reference a base object in memory. This can be a Fortran symbol,
// static data (e.g., CHARACTER literal), or compiler-created temporary. // static data (e.g., CHARACTER literal), or compiler-created temporary.
@ -76,7 +76,7 @@ public:
Component(const DataRef &b, const Symbol &c) : base_{b}, symbol_{c} {} Component(const DataRef &b, const Symbol &c) : base_{b}, symbol_{c} {}
Component(DataRef &&b, const Symbol &c) : base_{std::move(b)}, symbol_{c} {} Component(DataRef &&b, const Symbol &c) : base_{std::move(b)}, symbol_{c} {}
Component(common::CopyableIndirection<DataRef> &&b, const Symbol &c) Component(common::CopyableIndirection<DataRef> &&b, const Symbol &c)
: base_{std::move(b)}, symbol_{c} {} : base_{std::move(b)}, symbol_{c} {}
const DataRef &base() const { return base_.value(); } const DataRef &base() const { return base_.value(); }
DataRef &base() { return base_.value(); } DataRef &base() { return base_.value(); }
@ -107,7 +107,7 @@ public:
const Symbol &GetLastSymbol() const; const Symbol &GetLastSymbol() const;
const Component &GetComponent() const { return std::get<Component>(u_); } const Component &GetComponent() const { return std::get<Component>(u_); }
Component &GetComponent() { return std::get<Component>(u_); } Component &GetComponent() { return std::get<Component>(u_); }
const Component *UnwrapComponent() const; // null if just a Symbol const Component *UnwrapComponent() const; // null if just a Symbol
Component *UnwrapComponent(); Component *UnwrapComponent();
int Rank() const; int Rank() const;
@ -128,20 +128,20 @@ private:
// KIND(x), which is then folded to a constant value. // KIND(x), which is then folded to a constant value.
// "Bare" type parameter references within a derived type definition do // "Bare" type parameter references within a derived type definition do
// not have base objects. // not have base objects.
template<int KIND> class TypeParamInquiry { template <int KIND> class TypeParamInquiry {
public: public:
using Result = Type<TypeCategory::Integer, KIND>; using Result = Type<TypeCategory::Integer, KIND>;
CLASS_BOILERPLATE(TypeParamInquiry) CLASS_BOILERPLATE(TypeParamInquiry)
TypeParamInquiry(NamedEntity &&x, const Symbol &param) TypeParamInquiry(NamedEntity &&x, const Symbol &param)
: base_{std::move(x)}, parameter_{param} {} : base_{std::move(x)}, parameter_{param} {}
TypeParamInquiry(std::optional<NamedEntity> &&x, const Symbol &param) TypeParamInquiry(std::optional<NamedEntity> &&x, const Symbol &param)
: base_{std::move(x)}, parameter_{param} {} : base_{std::move(x)}, parameter_{param} {}
const std::optional<NamedEntity> &base() const { return base_; } const std::optional<NamedEntity> &base() const { return base_; }
std::optional<NamedEntity> &base() { return base_; } std::optional<NamedEntity> &base() { return base_; }
const Symbol &parameter() const { return parameter_; } const Symbol &parameter() const { return parameter_; }
static constexpr int Rank() { return 0; } // always scalar static constexpr int Rank() { return 0; } // always scalar
bool operator==(const TypeParamInquiry &) const; bool operator==(const TypeParamInquiry &) const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
@ -166,7 +166,7 @@ public:
Triplet &set_lower(Expr<SubscriptInteger> &&); Triplet &set_lower(Expr<SubscriptInteger> &&);
std::optional<Expr<SubscriptInteger>> upper() const; std::optional<Expr<SubscriptInteger>> upper() const;
Triplet &set_upper(Expr<SubscriptInteger> &&); Triplet &set_upper(Expr<SubscriptInteger> &&);
Expr<SubscriptInteger> stride() const; // N.B. result is not optional<> Expr<SubscriptInteger> stride() const; // N.B. result is not optional<>
Triplet &set_stride(Expr<SubscriptInteger> &&); Triplet &set_stride(Expr<SubscriptInteger> &&);
bool operator==(const Triplet &) const; bool operator==(const Triplet &) const;
@ -182,7 +182,7 @@ private:
struct Subscript { struct Subscript {
EVALUATE_UNION_CLASS_BOILERPLATE(Subscript) EVALUATE_UNION_CLASS_BOILERPLATE(Subscript)
explicit Subscript(Expr<SubscriptInteger> &&s) explicit Subscript(Expr<SubscriptInteger> &&s)
: u{IndirectSubscriptIntegerExpr::Make(std::move(s))} {} : u{IndirectSubscriptIntegerExpr::Make(std::move(s))} {}
int Rank() const; int Rank() const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
std::variant<IndirectSubscriptIntegerExpr, Triplet> u; std::variant<IndirectSubscriptIntegerExpr, Triplet> u;
@ -197,11 +197,11 @@ class ArrayRef {
public: public:
CLASS_BOILERPLATE(ArrayRef) CLASS_BOILERPLATE(ArrayRef)
ArrayRef(const Symbol &symbol, std::vector<Subscript> &&ss) ArrayRef(const Symbol &symbol, std::vector<Subscript> &&ss)
: base_{symbol}, subscript_(std::move(ss)) {} : base_{symbol}, subscript_(std::move(ss)) {}
ArrayRef(Component &&c, std::vector<Subscript> &&ss) ArrayRef(Component &&c, std::vector<Subscript> &&ss)
: base_{std::move(c)}, subscript_(std::move(ss)) {} : base_{std::move(c)}, subscript_(std::move(ss)) {}
ArrayRef(NamedEntity &&base, std::vector<Subscript> &&ss) ArrayRef(NamedEntity &&base, std::vector<Subscript> &&ss)
: base_{std::move(base)}, subscript_(std::move(ss)) {} : base_{std::move(base)}, subscript_(std::move(ss)) {}
NamedEntity &base() { return base_; } NamedEntity &base() { return base_; }
const NamedEntity &base() const { return base_; } const NamedEntity &base() const { return base_; }
@ -211,7 +211,7 @@ public:
int size() const { return static_cast<int>(subscript_.size()); } int size() const { return static_cast<int>(subscript_.size()); }
Subscript &at(int n) { return subscript_.at(n); } Subscript &at(int n) { return subscript_.at(n); }
const Subscript &at(int n) const { return subscript_.at(n); } const Subscript &at(int n) const { return subscript_.at(n); }
template<typename A> common::IfNoLvalue<Subscript &, A> emplace_back(A &&x) { template <typename A> common::IfNoLvalue<Subscript &, A> emplace_back(A &&x) {
return subscript_.emplace_back(std::move(x)); return subscript_.emplace_back(std::move(x));
} }
@ -275,7 +275,7 @@ private:
std::vector<Subscript> subscript_; std::vector<Subscript> subscript_;
std::vector<Expr<SubscriptInteger>> cosubscript_; std::vector<Expr<SubscriptInteger>> cosubscript_;
std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_, team_; std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_, team_;
bool teamIsTeamNumber_{false}; // false: TEAM=, true: TEAM_NUMBER= bool teamIsTeamNumber_{false}; // false: TEAM=, true: TEAM_NUMBER=
}; };
// R911 data-ref is defined syntactically as a series of part-refs, which // R911 data-ref is defined syntactically as a series of part-refs, which
@ -305,13 +305,13 @@ public:
CLASS_BOILERPLATE(Substring) CLASS_BOILERPLATE(Substring)
Substring(DataRef &&parent, std::optional<Expr<SubscriptInteger>> &&lower, Substring(DataRef &&parent, std::optional<Expr<SubscriptInteger>> &&lower,
std::optional<Expr<SubscriptInteger>> &&upper) std::optional<Expr<SubscriptInteger>> &&upper)
: parent_{std::move(parent)} { : parent_{std::move(parent)} {
SetBounds(lower, upper); SetBounds(lower, upper);
} }
Substring(StaticDataObject::Pointer &&parent, Substring(StaticDataObject::Pointer &&parent,
std::optional<Expr<SubscriptInteger>> &&lower, std::optional<Expr<SubscriptInteger>> &&lower,
std::optional<Expr<SubscriptInteger>> &&upper) std::optional<Expr<SubscriptInteger>> &&upper)
: parent_{std::move(parent)} { : parent_{std::move(parent)} {
SetBounds(lower, upper); SetBounds(lower, upper);
} }
@ -323,7 +323,7 @@ public:
Parent &parent() { return parent_; } Parent &parent() { return parent_; }
int Rank() const; int Rank() const;
template<typename A> const A *GetParentIf() const { template <typename A> const A *GetParentIf() const {
return std::get_if<A>(&parent_); return std::get_if<A>(&parent_);
} }
BaseObject GetBaseObject() const; BaseObject GetBaseObject() const;
@ -366,7 +366,7 @@ private:
// calls to pointer-valued functions. Its variant holds everything that // calls to pointer-valued functions. Its variant holds everything that
// a DataRef can, and possibly also a substring reference or a // a DataRef can, and possibly also a substring reference or a
// complex component (%RE/%IM) reference. // complex component (%RE/%IM) reference.
template<typename T> class Designator { template <typename T> class Designator {
using DataRefs = std::decay_t<decltype(DataRef::u)>; using DataRefs = std::decay_t<decltype(DataRef::u)>;
using MaybeSubstring = using MaybeSubstring =
std::conditional_t<T::category == TypeCategory::Character, std::conditional_t<T::category == TypeCategory::Character,
@ -383,7 +383,7 @@ public:
EVALUATE_UNION_CLASS_BOILERPLATE(Designator) EVALUATE_UNION_CLASS_BOILERPLATE(Designator)
Designator(const DataRef &that) : u{common::CopyVariant<Variant>(that.u)} {} Designator(const DataRef &that) : u{common::CopyVariant<Variant>(that.u)} {}
Designator(DataRef &&that) Designator(DataRef &&that)
: u{common::MoveVariant<Variant>(std::move(that.u))} {} : u{common::MoveVariant<Variant>(std::move(that.u))} {}
std::optional<DynamicType> GetType() const; std::optional<DynamicType> GetType() const;
int Rank() const; int Rank() const;
@ -397,7 +397,7 @@ public:
FOR_EACH_CHARACTER_KIND(extern template class Designator, ) FOR_EACH_CHARACTER_KIND(extern template class Designator, )
template<typename T> struct Variable { template <typename T> struct Variable {
using Result = T; using Result = T;
static_assert(IsSpecificIntrinsicType<Result> || static_assert(IsSpecificIntrinsicType<Result> ||
std::is_same_v<Result, SomeKind<TypeCategory::Derived>>); std::is_same_v<Result, SomeKind<TypeCategory::Derived>>);
@ -429,19 +429,19 @@ public:
Field field() const { return field_; } Field field() const { return field_; }
int dimension() const { return dimension_; } int dimension() const { return dimension_; }
static constexpr int Rank() { return 0; } // always scalar static constexpr int Rank() { return 0; } // always scalar
bool operator==(const DescriptorInquiry &) const; bool operator==(const DescriptorInquiry &) const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
private: private:
NamedEntity base_; NamedEntity base_;
Field field_; Field field_;
int dimension_{0}; // zero-based int dimension_{0}; // zero-based
}; };
#define INSTANTIATE_VARIABLE_TEMPLATES \ #define INSTANTIATE_VARIABLE_TEMPLATES \
EXPAND_FOR_EACH_INTEGER_KIND( \ EXPAND_FOR_EACH_INTEGER_KIND( \
TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) \ TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) \
FOR_EACH_SPECIFIC_TYPE(template class Designator, ) FOR_EACH_SPECIFIC_TYPE(template class Designator, )
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_VARIABLE_H_ #endif // FORTRAN_EVALUATE_VARIABLE_H_

View File

@ -80,7 +80,7 @@ typedef signed char CFI_type_t;
#define CFI_type_char 32 #define CFI_type_char 32
#define CFI_type_cptr 33 #define CFI_type_cptr 33
#define CFI_type_struct 34 #define CFI_type_struct 34
#define CFI_type_other (-1) // must be negative #define CFI_type_other (-1) // must be negative
/* Error code macros */ /* Error code macros */
#define CFI_SUCCESS 0 /* must be zero */ #define CFI_SUCCESS 0 /* must be zero */
@ -108,13 +108,13 @@ namespace cfi_internal {
// The below structure emulates a flexible array. This structure does not take // The below structure emulates a flexible array. This structure does not take
// care of getting the memory storage. Note that it already contains one element // care of getting the memory storage. Note that it already contains one element
// because a struct cannot be empty. // because a struct cannot be empty.
template<typename T> struct FlexibleArray : T { template <typename T> struct FlexibleArray : T {
T &operator[](int index) { return *(this + index); } T &operator[](int index) { return *(this + index); }
const T &operator[](int index) const { return *(this + index); } const T &operator[](int index) const { return *(this + index); }
operator T *() { return this; } operator T *() { return this; }
operator const T *() const { return this; } operator const T *() const { return this; }
}; };
} } // namespace cfi_internal
#endif #endif
/* 18.5.3 generic data descriptor */ /* 18.5.3 generic data descriptor */
@ -139,13 +139,13 @@ typedef struct CFI_cdesc_t {
// The struct below take care of getting the memory storage for C++ CFI_cdesc_t // The struct below take care of getting the memory storage for C++ CFI_cdesc_t
// that contain an emulated flexible array. // that contain an emulated flexible array.
namespace cfi_internal { namespace cfi_internal {
template<int r> struct CdescStorage : public CFI_cdesc_t { template <int r> struct CdescStorage : public CFI_cdesc_t {
static_assert((r > 1 && r <= CFI_MAX_RANK), "CFI_INVALID_RANK"); static_assert((r > 1 && r <= CFI_MAX_RANK), "CFI_INVALID_RANK");
CFI_dim_t dim[r - 1]; CFI_dim_t dim[r - 1];
}; };
template<> struct CdescStorage<1> : public CFI_cdesc_t {}; template <> struct CdescStorage<1> : public CFI_cdesc_t {};
template<> struct CdescStorage<0> : public CFI_cdesc_t {}; template <> struct CdescStorage<0> : public CFI_cdesc_t {};
} } // namespace cfi_internal
#define CFI_CDESC_T(rank) cfi_internal::CdescStorage<rank> #define CFI_CDESC_T(rank) cfi_internal::CdescStorage<rank>
#else #else
#define CFI_CDESC_T(rank) \ #define CFI_CDESC_T(rank) \
@ -174,8 +174,8 @@ int CFI_select_part(CFI_cdesc_t *, const CFI_cdesc_t *source,
int CFI_setpointer( int CFI_setpointer(
CFI_cdesc_t *, const CFI_cdesc_t *source, const CFI_index_t lower_bounds[]); CFI_cdesc_t *, const CFI_cdesc_t *source, const CFI_index_t lower_bounds[]);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
} // inline namespace Fortran_2018 } // inline namespace Fortran_2018
} }
} }
#endif #endif

View File

@ -30,7 +30,7 @@ public:
constexpr CharBlock() {} constexpr CharBlock() {}
constexpr CharBlock(const char *x, std::size_t n = 1) : interval_{x, n} {} constexpr CharBlock(const char *x, std::size_t n = 1) : interval_{x, n} {}
constexpr CharBlock(const char *b, const char *ep1) constexpr CharBlock(const char *b, const char *ep1)
: interval_{b, static_cast<std::size_t>(ep1 - b)} {} : interval_{b, static_cast<std::size_t>(ep1 - b)} {}
CharBlock(const std::string &s) : interval_{s.data(), s.size()} {} CharBlock(const std::string &s) : interval_{s.data(), s.size()} {}
constexpr CharBlock(const CharBlock &) = default; constexpr CharBlock(const CharBlock &) = default;
constexpr CharBlock(CharBlock &&) = default; constexpr CharBlock(CharBlock &&) = default;
@ -61,7 +61,7 @@ public:
return ch; return ch;
} }
} }
return ' '; // non no-blank character return ' '; // non no-blank character
} }
bool IsBlank() const { return FirstNonBlank() == ' '; } bool IsBlank() const { return FirstNonBlank() == ' '; }
@ -140,10 +140,10 @@ inline bool operator>(const char *left, const CharBlock &right) {
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const CharBlock &x); llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const CharBlock &x);
} } // namespace Fortran::parser
// Specializations to enable std::unordered_map<CharBlock, ...> &c. // Specializations to enable std::unordered_map<CharBlock, ...> &c.
template<> struct std::hash<Fortran::parser::CharBlock> { template <> struct std::hash<Fortran::parser::CharBlock> {
std::size_t operator()(const Fortran::parser::CharBlock &x) const { std::size_t operator()(const Fortran::parser::CharBlock &x) const {
std::size_t hash{0}, bytes{x.size()}; std::size_t hash{0}, bytes{x.size()};
for (std::size_t j{0}; j < bytes; ++j) { for (std::size_t j{0}; j < bytes; ++j) {
@ -152,4 +152,4 @@ template<> struct std::hash<Fortran::parser::CharBlock> {
return hash; return hash;
} }
}; };
#endif // FORTRAN_PARSER_CHAR_BLOCK_H_ #endif // FORTRAN_PARSER_CHAR_BLOCK_H_

View File

@ -24,8 +24,8 @@ class CharBuffer {
public: public:
CharBuffer() {} CharBuffer() {}
CharBuffer(CharBuffer &&that) CharBuffer(CharBuffer &&that)
: blocks_(std::move(that.blocks_)), last_{that.last_}, bytes_{that.bytes_}, : blocks_(std::move(that.blocks_)), last_{that.last_},
lastBlockEmpty_{that.lastBlockEmpty_} { bytes_{that.bytes_}, lastBlockEmpty_{that.lastBlockEmpty_} {
that.clear(); that.clear();
} }
CharBuffer &operator=(CharBuffer &&that) { CharBuffer &operator=(CharBuffer &&that) {
@ -73,5 +73,5 @@ private:
std::size_t bytes_{0}; std::size_t bytes_{0};
bool lastBlockEmpty_{false}; bool lastBlockEmpty_{false};
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_CHAR_BUFFER_H_ #endif // FORTRAN_PARSER_CHAR_BUFFER_H_

View File

@ -75,5 +75,5 @@ private:
constexpr SetOfChars(std::uint64_t b) : bits_{b} {} constexpr SetOfChars(std::uint64_t b) : bits_{b} {}
std::uint64_t bits_{0}; std::uint64_t bits_{0};
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_CHAR_SET_H_ #endif // FORTRAN_PARSER_CHAR_SET_H_

View File

@ -103,33 +103,51 @@ inline constexpr char HexadecimalDigitValue(char ch) {
inline constexpr std::optional<char> BackslashEscapeValue(char ch) { inline constexpr std::optional<char> BackslashEscapeValue(char ch) {
switch (ch) { switch (ch) {
case 'a': return std::nullopt; // '\a'; PGF90 doesn't know \a case 'a':
case 'b': return '\b'; return std::nullopt; // '\a'; PGF90 doesn't know \a
case 'f': return '\f'; case 'b':
case 'n': return '\n'; return '\b';
case 'r': return '\r'; case 'f':
case 't': return '\t'; return '\f';
case 'v': return '\v'; case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '"': case '"':
case '\'': case '\'':
case '\\': return ch; case '\\':
default: return std::nullopt; return ch;
default:
return std::nullopt;
} }
} }
inline constexpr std::optional<char> BackslashEscapeChar(char ch) { inline constexpr std::optional<char> BackslashEscapeChar(char ch) {
switch (ch) { switch (ch) {
case '\a': return std::nullopt; // 'a'; PGF90 doesn't know \a case '\a':
case '\b': return 'b'; return std::nullopt; // 'a'; PGF90 doesn't know \a
case '\f': return 'f'; case '\b':
case '\n': return 'n'; return 'b';
case '\r': return 'r'; case '\f':
case '\t': return 't'; return 'f';
case '\v': return 'v'; case '\n':
return 'n';
case '\r':
return 'r';
case '\t':
return 't';
case '\v':
return 'v';
case '"': case '"':
case '\'': case '\'':
case '\\': return ch; case '\\':
default: return std::nullopt; return ch;
default:
return std::nullopt;
} }
} }
@ -139,13 +157,13 @@ struct EncodedCharacter {
int bytes{0}; int bytes{0};
}; };
template<Encoding ENCODING> EncodedCharacter EncodeCharacter(char32_t ucs); template <Encoding ENCODING> EncodedCharacter EncodeCharacter(char32_t ucs);
template<> EncodedCharacter EncodeCharacter<Encoding::LATIN_1>(char32_t); template <> EncodedCharacter EncodeCharacter<Encoding::LATIN_1>(char32_t);
template<> EncodedCharacter EncodeCharacter<Encoding::UTF_8>(char32_t); template <> EncodedCharacter EncodeCharacter<Encoding::UTF_8>(char32_t);
EncodedCharacter EncodeCharacter(Encoding, char32_t ucs); EncodedCharacter EncodeCharacter(Encoding, char32_t ucs);
template<Encoding ENCODING, typename STRING> template <Encoding ENCODING, typename STRING>
std::string EncodeString(const STRING &); std::string EncodeString(const STRING &);
extern template std::string EncodeString<Encoding::LATIN_1, std::string>( extern template std::string EncodeString<Encoding::LATIN_1, std::string>(
const std::string &); const std::string &);
@ -154,7 +172,7 @@ extern template std::string EncodeString<Encoding::UTF_8, std::u32string>(
// EmitQuotedChar drives callbacks "emit" and "insert" to output the // EmitQuotedChar drives callbacks "emit" and "insert" to output the
// bytes of an encoding for a codepoint. // bytes of an encoding for a codepoint.
template<typename NORMAL, typename INSERTED> template <typename NORMAL, typename INSERTED>
void EmitQuotedChar(char32_t ch, const NORMAL &emit, const INSERTED &insert, void EmitQuotedChar(char32_t ch, const NORMAL &emit, const INSERTED &insert,
bool backslashEscapes = true, Encoding encoding = Encoding::UTF_8) { bool backslashEscapes = true, Encoding encoding = Encoding::UTF_8) {
auto emitOneByte{[&](std::uint8_t ch) { auto emitOneByte{[&](std::uint8_t ch) {
@ -175,7 +193,7 @@ void EmitQuotedChar(char32_t ch, const NORMAL &emit, const INSERTED &insert,
insert('0' + ((ch >> 3) & 7)); insert('0' + ((ch >> 3) & 7));
insert('0' + (ch & 7)); insert('0' + (ch & 7));
} }
} else if (ch == '\n') { // always escape newlines } else if (ch == '\n') { // always escape newlines
insert('\\'); insert('\\');
insert('n'); insert('n');
} else { } else {
@ -203,20 +221,20 @@ int UTF_8CharacterBytes(const char *);
struct DecodedCharacter { struct DecodedCharacter {
char32_t codepoint{0}; char32_t codepoint{0};
int bytes{0}; // signifying failure int bytes{0}; // signifying failure
}; };
template<Encoding ENCODING> template <Encoding ENCODING>
DecodedCharacter DecodeRawCharacter(const char *, std::size_t); DecodedCharacter DecodeRawCharacter(const char *, std::size_t);
template<> template <>
DecodedCharacter DecodeRawCharacter<Encoding::LATIN_1>( DecodedCharacter DecodeRawCharacter<Encoding::LATIN_1>(
const char *, std::size_t); const char *, std::size_t);
template<> template <>
DecodedCharacter DecodeRawCharacter<Encoding::UTF_8>(const char *, std::size_t); DecodedCharacter DecodeRawCharacter<Encoding::UTF_8>(const char *, std::size_t);
// DecodeCharacter optionally handles backslash escape sequences, too. // DecodeCharacter optionally handles backslash escape sequences, too.
template<Encoding ENCODING> template <Encoding ENCODING>
DecodedCharacter DecodeCharacter( DecodedCharacter DecodeCharacter(
const char *, std::size_t, bool backslashEscapes); const char *, std::size_t, bool backslashEscapes);
extern template DecodedCharacter DecodeCharacter<Encoding::LATIN_1>( extern template DecodedCharacter DecodeCharacter<Encoding::LATIN_1>(
@ -227,7 +245,7 @@ extern template DecodedCharacter DecodeCharacter<Encoding::UTF_8>(
DecodedCharacter DecodeCharacter( DecodedCharacter DecodeCharacter(
Encoding, const char *, std::size_t, bool backslashEscapes); Encoding, const char *, std::size_t, bool backslashEscapes);
template<typename RESULT, Encoding ENCODING> template <typename RESULT, Encoding ENCODING>
RESULT DecodeString(const std::string &, bool backslashEscapes); RESULT DecodeString(const std::string &, bool backslashEscapes);
extern template std::string DecodeString<std::string, Encoding::LATIN_1>( extern template std::string DecodeString<std::string, Encoding::LATIN_1>(
const std::string &, bool); const std::string &, bool);
@ -235,5 +253,5 @@ extern template std::u16string DecodeString<std::u16string, Encoding::UTF_8>(
const std::string &, bool); const std::string &, bool);
extern template std::u32string DecodeString<std::u32string, Encoding::UTF_8>( extern template std::u32string DecodeString<std::u32string, Encoding::UTF_8>(
const std::string &, bool); const std::string &, bool);
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_CHARACTERS_H_ #endif // FORTRAN_PARSER_CHARACTERS_H_

View File

@ -23,9 +23,9 @@ namespace Fortran::parser {
// When SHOW_ALL_SOURCE_MEMBERS is defined, HasSource<T>::value is true if T has // When SHOW_ALL_SOURCE_MEMBERS is defined, HasSource<T>::value is true if T has
// a member named source // a member named source
template<typename T, typename = int> struct HasSource : std::false_type {}; template <typename T, typename = int> struct HasSource : std::false_type {};
#ifdef SHOW_ALL_SOURCE_MEMBERS #ifdef SHOW_ALL_SOURCE_MEMBERS
template<typename T> template <typename T>
struct HasSource<T, decltype((void)T::source, 0)> : std::true_type {}; struct HasSource<T, decltype((void)T::source, 0)> : std::true_type {};
#endif #endif
@ -35,9 +35,9 @@ struct HasSource<T, decltype((void)T::source, 0)> : std::true_type {};
class ParseTreeDumper { class ParseTreeDumper {
public: public:
explicit ParseTreeDumper( explicit ParseTreeDumper(llvm::raw_ostream &out,
llvm::raw_ostream &out, const AnalyzedObjectsAsFortran *asFortran = nullptr) const AnalyzedObjectsAsFortran *asFortran = nullptr)
: out_(out), asFortran_{asFortran} {} : out_(out), asFortran_{asFortran} {}
static constexpr const char *GetNodeName(const char *) { return "char *"; } static constexpr const char *GetNodeName(const char *) { return "char *"; }
#define NODE_NAME(T, N) \ #define NODE_NAME(T, N) \
@ -682,7 +682,7 @@ public:
#undef NODE #undef NODE
#undef NODE_NAME #undef NODE_NAME
template<typename T> bool Pre(const T &x) { template <typename T> bool Pre(const T &x) {
std::string fortran{AsFortran<T>(x)}; std::string fortran{AsFortran<T>(x)};
if (fortran.empty() && (UnionTrait<T> || WrapperTrait<T>)) { if (fortran.empty() && (UnionTrait<T> || WrapperTrait<T>)) {
Prefix(GetNodeName(x)); Prefix(GetNodeName(x));
@ -698,7 +698,7 @@ public:
return true; return true;
} }
template<typename T> void Post(const T &x) { template <typename T> void Post(const T &x) {
if (AsFortran<T>(x).empty() && (UnionTrait<T> || WrapperTrait<T>)) { if (AsFortran<T>(x).empty() && (UnionTrait<T> || WrapperTrait<T>)) {
EndLineIfNonempty(); EndLineIfNonempty();
} else { } else {
@ -711,55 +711,57 @@ public:
bool Pre(const CharBlock &) { return true; } bool Pre(const CharBlock &) { return true; }
void Post(const CharBlock &) {} void Post(const CharBlock &) {}
template<typename T> bool Pre(const Statement<T> &) { return true; } template <typename T> bool Pre(const Statement<T> &) { return true; }
template<typename T> void Post(const Statement<T> &) {} template <typename T> void Post(const Statement<T> &) {}
template<typename T> bool Pre(const UnlabeledStatement<T> &) { return true; } template <typename T> bool Pre(const UnlabeledStatement<T> &) { return true; }
template<typename T> void Post(const UnlabeledStatement<T> &) {} template <typename T> void Post(const UnlabeledStatement<T> &) {}
template<typename T> bool Pre(const common::Indirection<T> &) { return true; } template <typename T> bool Pre(const common::Indirection<T> &) {
template<typename T> void Post(const common::Indirection<T> &) {} return true;
}
template <typename T> void Post(const common::Indirection<T> &) {}
template<typename A> bool Pre(const Scalar<A> &) { template <typename A> bool Pre(const Scalar<A> &) {
Prefix("Scalar"); Prefix("Scalar");
return true; return true;
} }
template<typename A> void Post(const Scalar<A> &) { EndLineIfNonempty(); } template <typename A> void Post(const Scalar<A> &) { EndLineIfNonempty(); }
template<typename A> bool Pre(const Constant<A> &) { template <typename A> bool Pre(const Constant<A> &) {
Prefix("Constant"); Prefix("Constant");
return true; return true;
} }
template<typename A> void Post(const Constant<A> &) { EndLineIfNonempty(); } template <typename A> void Post(const Constant<A> &) { EndLineIfNonempty(); }
template<typename A> bool Pre(const Integer<A> &) { template <typename A> bool Pre(const Integer<A> &) {
Prefix("Integer"); Prefix("Integer");
return true; return true;
} }
template<typename A> void Post(const Integer<A> &) { EndLineIfNonempty(); } template <typename A> void Post(const Integer<A> &) { EndLineIfNonempty(); }
template<typename A> bool Pre(const Logical<A> &) { template <typename A> bool Pre(const Logical<A> &) {
Prefix("Logical"); Prefix("Logical");
return true; return true;
} }
template<typename A> void Post(const Logical<A> &) { EndLineIfNonempty(); } template <typename A> void Post(const Logical<A> &) { EndLineIfNonempty(); }
template<typename A> bool Pre(const DefaultChar<A> &) { template <typename A> bool Pre(const DefaultChar<A> &) {
Prefix("DefaultChar"); Prefix("DefaultChar");
return true; return true;
} }
template<typename A> void Post(const DefaultChar<A> &) { template <typename A> void Post(const DefaultChar<A> &) {
EndLineIfNonempty(); EndLineIfNonempty();
} }
template<typename... A> bool Pre(const std::tuple<A...> &) { return true; } template <typename... A> bool Pre(const std::tuple<A...> &) { return true; }
template<typename... A> void Post(const std::tuple<A...> &) {} template <typename... A> void Post(const std::tuple<A...> &) {}
template<typename... A> bool Pre(const std::variant<A...> &) { return true; } template <typename... A> bool Pre(const std::variant<A...> &) { return true; }
template<typename... A> void Post(const std::variant<A...> &) {} template <typename... A> void Post(const std::variant<A...> &) {}
protected: protected:
// Return a Fortran representation of this node to include in the dump // Return a Fortran representation of this node to include in the dump
template<typename T> std::string AsFortran(const T &x) { template <typename T> std::string AsFortran(const T &x) {
std::string buf; std::string buf;
llvm::raw_string_ostream ss{buf}; llvm::raw_string_ostream ss{buf};
if constexpr (std::is_same_v<T, Expr>) { if constexpr (std::is_same_v<T, Expr>) {
@ -835,12 +837,12 @@ private:
bool emptyline_{false}; bool emptyline_{false};
}; };
template<typename T> template <typename T>
void DumpTree(llvm::raw_ostream &out, const T &x, void DumpTree(llvm::raw_ostream &out, const T &x,
const AnalyzedObjectsAsFortran *asFortran = nullptr) { const AnalyzedObjectsAsFortran *asFortran = nullptr) {
ParseTreeDumper dumper{out, asFortran}; ParseTreeDumper dumper{out, asFortran};
Walk(x, dumper); Walk(x, dumper);
} }
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_DUMP_PARSE_TREE_H_ #endif // FORTRAN_PARSER_DUMP_PARSE_TREE_H_

View File

@ -41,12 +41,12 @@ struct IntrinsicTypeDataEditDesc {
IntrinsicTypeDataEditDesc &operator=(IntrinsicTypeDataEditDesc &&) = default; IntrinsicTypeDataEditDesc &operator=(IntrinsicTypeDataEditDesc &&) = default;
IntrinsicTypeDataEditDesc(Kind &&k, std::optional<int> &&w, IntrinsicTypeDataEditDesc(Kind &&k, std::optional<int> &&w,
std::optional<int> &&d, std::optional<int> &&e) std::optional<int> &&d, std::optional<int> &&e)
: kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{ : kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{
std::move(e)} {} std::move(e)} {}
Kind kind; Kind kind;
std::optional<int> width; // w std::optional<int> width; // w
std::optional<int> digits; // m or d std::optional<int> digits; // m or d
std::optional<int> exponentWidth; // e std::optional<int> exponentWidth; // e
}; };
// R1307 data-edit-desc (part 2 of 2) -> // R1307 data-edit-desc (part 2 of 2) ->
@ -57,7 +57,7 @@ struct DerivedTypeDataEditDesc {
DerivedTypeDataEditDesc(DerivedTypeDataEditDesc &&) = default; DerivedTypeDataEditDesc(DerivedTypeDataEditDesc &&) = default;
DerivedTypeDataEditDesc &operator=(DerivedTypeDataEditDesc &&) = default; DerivedTypeDataEditDesc &operator=(DerivedTypeDataEditDesc &&) = default;
DerivedTypeDataEditDesc(std::string &&t, std::list<std::int64_t> &&p) DerivedTypeDataEditDesc(std::string &&t, std::list<std::int64_t> &&p)
: type{std::move(t)}, parameters{std::move(p)} {} : type{std::move(t)}, parameters{std::move(p)} {}
std::string type; std::string type;
std::list<std::int64_t> parameters; std::list<std::int64_t> parameters;
}; };
@ -94,8 +94,8 @@ struct ControlEditDesc {
RP, RP,
DC, DC,
DP, DP,
Dollar, // extension: inhibit newline on output Dollar, // extension: inhibit newline on output
Backslash, // ditto, but only on terminals Backslash, // ditto, but only on terminals
}; };
ControlEditDesc() = delete; ControlEditDesc() = delete;
ControlEditDesc(ControlEditDesc &&) = default; ControlEditDesc(ControlEditDesc &&) = default;
@ -104,7 +104,7 @@ struct ControlEditDesc {
ControlEditDesc(Kind k, std::int64_t ct) : 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} {} ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {}
Kind kind; Kind kind;
std::int64_t count{1}; // r, k, or n std::int64_t count{1}; // r, k, or n
}; };
// R1304 format-item -> // R1304 format-item ->
@ -116,10 +116,10 @@ struct FormatItem {
FormatItem() = delete; FormatItem() = delete;
FormatItem(FormatItem &&) = default; FormatItem(FormatItem &&) = default;
FormatItem &operator=(FormatItem &&) = default; FormatItem &operator=(FormatItem &&) = default;
template<typename A, typename = common::NoLvalue<A>> template <typename A, typename = common::NoLvalue<A>>
FormatItem(std::optional<std::uint64_t> &&r, A &&x) FormatItem(std::optional<std::uint64_t> &&r, A &&x)
: repeatCount{std::move(r)}, u{std::move(x)} {} : repeatCount{std::move(r)}, u{std::move(x)} {}
template<typename A, typename = common::NoLvalue<A>> template <typename A, typename = common::NoLvalue<A>>
explicit FormatItem(A &&x) : u{std::move(x)} {} explicit FormatItem(A &&x) : u{std::move(x)} {}
std::optional<std::uint64_t> repeatCount; std::optional<std::uint64_t> repeatCount;
std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc, std::variant<IntrinsicTypeDataEditDesc, DerivedTypeDataEditDesc,
@ -136,10 +136,10 @@ struct FormatSpecification {
FormatSpecification(FormatSpecification &&) = default; FormatSpecification(FormatSpecification &&) = default;
FormatSpecification &operator=(FormatSpecification &&) = default; FormatSpecification &operator=(FormatSpecification &&) = default;
explicit FormatSpecification(std::list<FormatItem> &&is) explicit FormatSpecification(std::list<FormatItem> &&is)
: items(std::move(is)) {} : items(std::move(is)) {}
FormatSpecification(std::list<FormatItem> &&is, std::list<FormatItem> &&us) FormatSpecification(std::list<FormatItem> &&is, std::list<FormatItem> &&us)
: items(std::move(is)), unlimitedItems(std::move(us)) {} : items(std::move(is)), unlimitedItems(std::move(us)) {}
std::list<FormatItem> items, unlimitedItems; std::list<FormatItem> items, unlimitedItems;
}; };
} } // namespace Fortran::format
#endif // FORTRAN_PARSER_FORMAT_SPECIFICATION_H_ #endif // FORTRAN_PARSER_FORMAT_SPECIFICATION_H_

View File

@ -47,12 +47,12 @@ private:
std::map<std::size_t, LogForPosition> perPos_; std::map<std::size_t, LogForPosition> perPos_;
}; };
template<typename PA> class InstrumentedParser { template <typename PA> class InstrumentedParser {
public: public:
using resultType = typename PA::resultType; using resultType = typename PA::resultType;
constexpr InstrumentedParser(const InstrumentedParser &) = default; constexpr InstrumentedParser(const InstrumentedParser &) = default;
constexpr InstrumentedParser(const MessageFixedText &tag, const PA &parser) constexpr InstrumentedParser(const MessageFixedText &tag, const PA &parser)
: tag_{tag}, parser_{parser} {} : tag_{tag}, parser_{parser} {}
std::optional<resultType> Parse(ParseState &state) const { std::optional<resultType> Parse(ParseState &state) const {
if (UserState * ustate{state.userState()}) { if (UserState * ustate{state.userState()}) {
if (ParsingLog * log{ustate->log()}) { if (ParsingLog * log{ustate->log()}) {
@ -75,10 +75,10 @@ private:
const PA parser_; const PA parser_;
}; };
template<typename PA> template <typename PA>
inline constexpr auto instrumented( inline constexpr auto instrumented(
const MessageFixedText &tag, const PA &parser) { const MessageFixedText &tag, const PA &parser) {
return InstrumentedParser{tag, parser}; return InstrumentedParser{tag, parser};
} }
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_INSTRUMENTED_PARSER_H_ #endif // FORTRAN_PARSER_INSTRUMENTED_PARSER_H_

View File

@ -34,7 +34,7 @@ class MessageFixedText {
public: public:
constexpr MessageFixedText( constexpr MessageFixedText(
const char str[], std::size_t n, bool isFatal = false) const char str[], std::size_t n, bool isFatal = false)
: text_{str, n}, isFatal_{isFatal} {} : text_{str, n}, isFatal_{isFatal} {}
constexpr MessageFixedText(const MessageFixedText &) = default; constexpr MessageFixedText(const MessageFixedText &) = default;
constexpr MessageFixedText(MessageFixedText &&) = default; constexpr MessageFixedText(MessageFixedText &&) = default;
constexpr MessageFixedText &operator=(const MessageFixedText &) = default; constexpr MessageFixedText &operator=(const MessageFixedText &) = default;
@ -57,7 +57,7 @@ constexpr MessageFixedText operator""_err_en_US(
const char str[], std::size_t n) { const char str[], std::size_t n) {
return MessageFixedText{str, n, true /* fatal */}; return MessageFixedText{str, n, true /* fatal */};
} }
} } // namespace literals
// The construction of a MessageFormattedText uses a MessageFixedText // The construction of a MessageFormattedText uses a MessageFixedText
// as a vsnprintf() formatting string that is applied to the // as a vsnprintf() formatting string that is applied to the
@ -66,9 +66,9 @@ constexpr MessageFixedText operator""_err_en_US(
// char pointers that are suitable for '%s' formatting. // char pointers that are suitable for '%s' formatting.
class MessageFormattedText { class MessageFormattedText {
public: public:
template<typename... A> template <typename... A>
MessageFormattedText(const MessageFixedText &text, A &&... x) MessageFormattedText(const MessageFixedText &text, A &&... x)
: isFatal_{text.isFatal()} { : isFatal_{text.isFatal()} {
Format(&text, Convert(std::forward<A>(x))...); Format(&text, Convert(std::forward<A>(x))...);
} }
MessageFormattedText(const MessageFormattedText &) = default; MessageFormattedText(const MessageFormattedText &) = default;
@ -82,15 +82,15 @@ public:
private: private:
void Format(const MessageFixedText *, ...); void Format(const MessageFixedText *, ...);
template<typename A> A Convert(const A &x) { template <typename A> A Convert(const A &x) {
static_assert(!std::is_class_v<std::decay_t<A>>); static_assert(!std::is_class_v<std::decay_t<A>>);
return x; return x;
} }
template<typename A> A Convert(A &x) { template <typename A> A Convert(A &x) {
static_assert(!std::is_class_v<std::decay_t<A>>); static_assert(!std::is_class_v<std::decay_t<A>>);
return x; return x;
} }
template<typename A> common::IfNoLvalue<A, A> Convert(A &&x) { template <typename A> common::IfNoLvalue<A, A> Convert(A &&x) {
static_assert(!std::is_class_v<std::decay_t<A>>); static_assert(!std::is_class_v<std::decay_t<A>>);
return std::move(x); return std::move(x);
} }
@ -103,7 +103,7 @@ private:
bool isFatal_{false}; bool isFatal_{false};
std::string string_; std::string string_;
std::forward_list<std::string> conversions_; // preserves created strings std::forward_list<std::string> conversions_; // preserves created strings
}; };
// Represents a formatted rendition of "expected '%s'"_err_en_US // Represents a formatted rendition of "expected '%s'"_err_en_US
@ -146,27 +146,27 @@ public:
Message &operator=(Message &&) = default; Message &operator=(Message &&) = default;
Message(ProvenanceRange pr, const MessageFixedText &t) Message(ProvenanceRange pr, const MessageFixedText &t)
: location_{pr}, text_{t} {} : location_{pr}, text_{t} {}
Message(ProvenanceRange pr, const MessageFormattedText &s) Message(ProvenanceRange pr, const MessageFormattedText &s)
: location_{pr}, text_{s} {} : location_{pr}, text_{s} {}
Message(ProvenanceRange pr, MessageFormattedText &&s) Message(ProvenanceRange pr, MessageFormattedText &&s)
: location_{pr}, text_{std::move(s)} {} : location_{pr}, text_{std::move(s)} {}
Message(ProvenanceRange pr, const MessageExpectedText &t) Message(ProvenanceRange pr, const MessageExpectedText &t)
: location_{pr}, text_{t} {} : location_{pr}, text_{t} {}
Message(CharBlock csr, const MessageFixedText &t) Message(CharBlock csr, const MessageFixedText &t)
: location_{csr}, text_{t} {} : location_{csr}, text_{t} {}
Message(CharBlock csr, const MessageFormattedText &s) Message(CharBlock csr, const MessageFormattedText &s)
: location_{csr}, text_{s} {} : location_{csr}, text_{s} {}
Message(CharBlock csr, MessageFormattedText &&s) Message(CharBlock csr, MessageFormattedText &&s)
: location_{csr}, text_{std::move(s)} {} : location_{csr}, text_{std::move(s)} {}
Message(CharBlock csr, const MessageExpectedText &t) Message(CharBlock csr, const MessageExpectedText &t)
: location_{csr}, text_{t} {} : location_{csr}, text_{t} {}
template<typename RANGE, typename A, typename... As> template <typename RANGE, typename A, typename... As>
Message(RANGE r, const MessageFixedText &t, A &&x, As &&... xs) Message(RANGE r, const MessageFixedText &t, A &&x, As &&... xs)
: location_{r}, text_{MessageFormattedText{ : location_{r}, text_{MessageFormattedText{
t, std::forward<A>(x), std::forward<As>(xs)...}} {} t, std::forward<A>(x), std::forward<As>(xs)...}} {}
bool attachmentIsContext() const { return attachmentIsContext_; } bool attachmentIsContext() const { return attachmentIsContext_; }
Reference attachment() const { return attachment_; } Reference attachment() const { return attachment_; }
@ -177,16 +177,16 @@ public:
} }
Message &Attach(Message *); Message &Attach(Message *);
Message &Attach(std::unique_ptr<Message> &&); Message &Attach(std::unique_ptr<Message> &&);
template<typename... A> Message &Attach(A &&... args) { template <typename... A> Message &Attach(A &&... args) {
return Attach(new Message{std::forward<A>(args)...}); // reference-counted return Attach(new Message{std::forward<A>(args)...}); // reference-counted
} }
bool SortBefore(const Message &that) const; bool SortBefore(const Message &that) const;
bool IsFatal() const; bool IsFatal() const;
std::string ToString() const; std::string ToString() const;
std::optional<ProvenanceRange> GetProvenanceRange(const CookedSource &) const; std::optional<ProvenanceRange> GetProvenanceRange(const CookedSource &) const;
void Emit( void Emit(llvm::raw_ostream &, const CookedSource &,
llvm::raw_ostream &, const CookedSource &, bool echoSourceLine = true) const; bool echoSourceLine = true) const;
// If this Message or any of its attachments locates itself via a CharBlock // If this Message or any of its attachments locates itself via a CharBlock
// within a particular CookedSource, replace its location with the // within a particular CookedSource, replace its location with the
@ -232,7 +232,7 @@ public:
bool empty() const { return messages_.empty(); } bool empty() const { return messages_.empty(); }
void clear(); void clear();
template<typename... A> Message &Say(A &&... args) { template <typename... A> Message &Say(A &&... args) {
last_ = messages_.emplace_after(last_, std::forward<A>(args)...); last_ = messages_.emplace_after(last_, std::forward<A>(args)...);
return *last_; return *last_;
} }
@ -272,7 +272,7 @@ public:
ContextualMessages(CharBlock at, Messages *m) : at_{at}, messages_{m} {} ContextualMessages(CharBlock at, Messages *m) : at_{at}, messages_{m} {}
explicit ContextualMessages(Messages *m) : messages_{m} {} explicit ContextualMessages(Messages *m) : messages_{m} {}
ContextualMessages(const ContextualMessages &that) ContextualMessages(const ContextualMessages &that)
: at_{that.at_}, messages_{that.messages_} {} : at_{that.at_}, messages_{that.messages_} {}
CharBlock at() const { return at_; } CharBlock at() const { return at_; }
Messages *messages() const { return messages_; } Messages *messages() const { return messages_; }
@ -296,7 +296,7 @@ public:
return common::ScopedSet(messages_, nullptr); return common::ScopedSet(messages_, nullptr);
} }
template<typename... A> Message *Say(CharBlock at, A &&... args) { template <typename... A> Message *Say(CharBlock at, A &&... args) {
if (messages_ != nullptr) { if (messages_ != nullptr) {
return &messages_->Say(at, std::forward<A>(args)...); return &messages_->Say(at, std::forward<A>(args)...);
} else { } else {
@ -304,7 +304,7 @@ public:
} }
} }
template<typename... A> Message *Say(A &&... args) { template <typename... A> Message *Say(A &&... args) {
return Say(at_, std::forward<A>(args)...); return Say(at_, std::forward<A>(args)...);
} }
@ -312,5 +312,5 @@ private:
CharBlock at_; CharBlock at_;
Messages *messages_{nullptr}; Messages *messages_{nullptr};
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_MESSAGE_H_ #endif // FORTRAN_PARSER_MESSAGE_H_

View File

@ -36,24 +36,24 @@ class ParseState {
public: public:
// TODO: Add a constructor for parsing a normalized module file. // TODO: Add a constructor for parsing a normalized module file.
ParseState(const CookedSource &cooked) ParseState(const CookedSource &cooked)
: p_{&cooked.data().front()}, limit_{&cooked.data().back() + 1} {} : p_{&cooked.data().front()}, limit_{&cooked.data().back() + 1} {}
ParseState(const ParseState &that) ParseState(const ParseState &that)
: p_{that.p_}, limit_{that.limit_}, context_{that.context_}, : p_{that.p_}, limit_{that.limit_}, context_{that.context_},
userState_{that.userState_}, inFixedForm_{that.inFixedForm_}, userState_{that.userState_}, inFixedForm_{that.inFixedForm_},
anyErrorRecovery_{that.anyErrorRecovery_}, anyErrorRecovery_{that.anyErrorRecovery_},
anyConformanceViolation_{that.anyConformanceViolation_}, anyConformanceViolation_{that.anyConformanceViolation_},
deferMessages_{that.deferMessages_}, deferMessages_{that.deferMessages_},
anyDeferredMessages_{that.anyDeferredMessages_}, anyDeferredMessages_{that.anyDeferredMessages_},
anyTokenMatched_{that.anyTokenMatched_} {} anyTokenMatched_{that.anyTokenMatched_} {}
ParseState(ParseState &&that) ParseState(ParseState &&that)
: p_{that.p_}, limit_{that.limit_}, messages_{std::move(that.messages_)}, : p_{that.p_}, limit_{that.limit_}, messages_{std::move(that.messages_)},
context_{std::move(that.context_)}, userState_{that.userState_}, context_{std::move(that.context_)}, userState_{that.userState_},
inFixedForm_{that.inFixedForm_}, inFixedForm_{that.inFixedForm_},
anyErrorRecovery_{that.anyErrorRecovery_}, anyErrorRecovery_{that.anyErrorRecovery_},
anyConformanceViolation_{that.anyConformanceViolation_}, anyConformanceViolation_{that.anyConformanceViolation_},
deferMessages_{that.deferMessages_}, deferMessages_{that.deferMessages_},
anyDeferredMessages_{that.anyDeferredMessages_}, anyDeferredMessages_{that.anyDeferredMessages_},
anyTokenMatched_{that.anyTokenMatched_} {} anyTokenMatched_{that.anyTokenMatched_} {}
ParseState &operator=(const ParseState &that) { ParseState &operator=(const ParseState &that) {
p_ = that.p_, limit_ = that.limit_, context_ = that.context_; p_ = that.p_, limit_ = that.limit_, context_ = that.context_;
userState_ = that.userState_, inFixedForm_ = that.inFixedForm_; userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
@ -121,7 +121,7 @@ public:
const char *GetLocation() const { return p_; } const char *GetLocation() const { return p_; }
void PushContext(MessageFixedText text) { void PushContext(MessageFixedText text) {
auto m{new Message{p_, text}}; // reference-counted auto m{new Message{p_, text}}; // reference-counted
m->SetContext(context_.get()); m->SetContext(context_.get());
context_ = Message::Reference{m}; context_ = Message::Reference{m};
} }
@ -131,17 +131,18 @@ public:
context_ = context_->attachment(); context_ = context_->attachment();
} }
template<typename... A> void Say(CharBlock range, A &&... args) { template <typename... A> void Say(CharBlock range, A &&... args) {
if (deferMessages_) { if (deferMessages_) {
anyDeferredMessages_ = true; anyDeferredMessages_ = true;
} else { } else {
messages_.Say(range, std::forward<A>(args)...).SetContext(context_.get()); messages_.Say(range, std::forward<A>(args)...).SetContext(context_.get());
} }
} }
template<typename... A> void Say(const MessageFixedText &text, A &&... args) { template <typename... A>
void Say(const MessageFixedText &text, A &&... args) {
Say(p_, text, std::forward<A>(args)...); Say(p_, text, std::forward<A>(args)...);
} }
template<typename... A> template <typename... A>
void Say(const MessageExpectedText &text, A &&... args) { void Say(const MessageExpectedText &text, A &&... args) {
Say(p_, text, std::forward<A>(args)...); Say(p_, text, std::forward<A>(args)...);
} }
@ -228,5 +229,5 @@ private:
// reflected in the copy and move constructors defined at the top of this // reflected in the copy and move constructors defined at the top of this
// class definition! // class definition!
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_PARSE_STATE_H_ #endif // FORTRAN_PARSER_PARSE_STATE_H_

View File

@ -29,7 +29,7 @@ namespace Fortran::parser {
// Default case for visitation of non-class data members, strings, and // Default case for visitation of non-class data members, strings, and
// any other non-decomposable values. // any other non-decomposable values.
template<typename A, typename V> template <typename A, typename V>
std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> || std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> ||
std::is_same_v<CharBlock, A>> std::is_same_v<CharBlock, A>>
Walk(const A &x, V &visitor) { Walk(const A &x, V &visitor) {
@ -37,7 +37,7 @@ Walk(const A &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename M> template <typename A, typename M>
std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> || std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> ||
std::is_same_v<CharBlock, A>> std::is_same_v<CharBlock, A>>
Walk(A &x, M &mutator) { Walk(A &x, M &mutator) {
@ -46,25 +46,25 @@ Walk(A &x, M &mutator) {
} }
} }
template<typename V> void Walk(const format::ControlEditDesc &, V &); template <typename V> void Walk(const format::ControlEditDesc &, V &);
template<typename M> void Walk(format::ControlEditDesc &, M &); template <typename M> void Walk(format::ControlEditDesc &, M &);
template<typename V> void Walk(const format::DerivedTypeDataEditDesc &, V &); template <typename V> void Walk(const format::DerivedTypeDataEditDesc &, V &);
template<typename M> void Walk(format::DerivedTypeDataEditDesc &, M &); template <typename M> void Walk(format::DerivedTypeDataEditDesc &, M &);
template<typename V> void Walk(const format::FormatItem &, V &); template <typename V> void Walk(const format::FormatItem &, V &);
template<typename M> void Walk(format::FormatItem &, M &); template <typename M> void Walk(format::FormatItem &, M &);
template<typename V> void Walk(const format::FormatSpecification &, V &); template <typename V> void Walk(const format::FormatSpecification &, V &);
template<typename M> void Walk(format::FormatSpecification &, M &); template <typename M> void Walk(format::FormatSpecification &, M &);
template<typename V> void Walk(const format::IntrinsicTypeDataEditDesc &, V &); template <typename V> void Walk(const format::IntrinsicTypeDataEditDesc &, V &);
template<typename M> void Walk(format::IntrinsicTypeDataEditDesc &, M &); template <typename M> void Walk(format::IntrinsicTypeDataEditDesc &, M &);
// Traversal of needed STL template classes (optional, list, tuple, variant) // Traversal of needed STL template classes (optional, list, tuple, variant)
template<typename T, typename V> template <typename T, typename V>
void Walk(const std::optional<T> &x, V &visitor) { void Walk(const std::optional<T> &x, V &visitor) {
if (x) { if (x) {
Walk(*x, visitor); Walk(*x, visitor);
} }
} }
template<typename T, typename M> void Walk(std::optional<T> &x, M &mutator) { template <typename T, typename M> void Walk(std::optional<T> &x, M &mutator) {
if (x) { if (x) {
Walk(*x, mutator); Walk(*x, mutator);
} }
@ -72,17 +72,17 @@ template<typename T, typename M> void Walk(std::optional<T> &x, M &mutator) {
// For most lists, just traverse the elements; but when a list constitutes // For most lists, just traverse the elements; but when a list constitutes
// a Block (i.e., std::list<ExecutionPartConstruct>), also invoke the // a Block (i.e., std::list<ExecutionPartConstruct>), also invoke the
// visitor/mutator on the list itself. // visitor/mutator on the list itself.
template<typename T, typename V> void Walk(const std::list<T> &x, V &visitor) { template <typename T, typename V> void Walk(const std::list<T> &x, V &visitor) {
for (const auto &elem : x) { for (const auto &elem : x) {
Walk(elem, visitor); Walk(elem, visitor);
} }
} }
template<typename T, typename M> void Walk(std::list<T> &x, M &mutator) { template <typename T, typename M> void Walk(std::list<T> &x, M &mutator) {
for (auto &elem : x) { for (auto &elem : x) {
Walk(elem, mutator); Walk(elem, mutator);
} }
} }
template<typename V> void Walk(const Block &x, V &visitor) { template <typename V> void Walk(const Block &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
for (const auto &elem : x) { for (const auto &elem : x) {
Walk(elem, visitor); Walk(elem, visitor);
@ -90,7 +90,7 @@ template<typename V> void Walk(const Block &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(Block &x, M &mutator) { template <typename M> void Walk(Block &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
for (auto &elem : x) { for (auto &elem : x) {
Walk(elem, mutator); Walk(elem, mutator);
@ -98,14 +98,14 @@ template<typename M> void Walk(Block &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<std::size_t I = 0, typename Func, typename T> template <std::size_t I = 0, typename Func, typename T>
void ForEachInTuple(const T &tuple, Func func) { void ForEachInTuple(const T &tuple, Func func) {
func(std::get<I>(tuple)); func(std::get<I>(tuple));
if constexpr (I + 1 < std::tuple_size_v<T>) { if constexpr (I + 1 < std::tuple_size_v<T>) {
ForEachInTuple<I + 1>(tuple, func); ForEachInTuple<I + 1>(tuple, func);
} }
} }
template<typename V, typename... A> template <typename V, typename... A>
void Walk(const std::tuple<A...> &x, V &visitor) { void Walk(const std::tuple<A...> &x, V &visitor) {
if (sizeof...(A) > 0) { if (sizeof...(A) > 0) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
@ -114,14 +114,15 @@ void Walk(const std::tuple<A...> &x, V &visitor) {
} }
} }
} }
template<std::size_t I = 0, typename Func, typename T> template <std::size_t I = 0, typename Func, typename T>
void ForEachInTuple(T &tuple, Func func) { void ForEachInTuple(T &tuple, Func func) {
func(std::get<I>(tuple)); func(std::get<I>(tuple));
if constexpr (I + 1 < std::tuple_size_v<T>) { if constexpr (I + 1 < std::tuple_size_v<T>) {
ForEachInTuple<I + 1>(tuple, func); ForEachInTuple<I + 1>(tuple, func);
} }
} }
template<typename M, typename... A> void Walk(std::tuple<A...> &x, M &mutator) { template <typename M, typename... A>
void Walk(std::tuple<A...> &x, M &mutator) {
if (sizeof...(A) > 0) { if (sizeof...(A) > 0) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); }); ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); });
@ -129,28 +130,28 @@ template<typename M, typename... A> void Walk(std::tuple<A...> &x, M &mutator) {
} }
} }
} }
template<typename V, typename... A> template <typename V, typename... A>
void Walk(const std::variant<A...> &x, V &visitor) { void Walk(const std::variant<A...> &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
std::visit([&](const auto &y) { Walk(y, visitor); }, x); std::visit([&](const auto &y) { Walk(y, visitor); }, x);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M, typename... A> template <typename M, typename... A>
void Walk(std::variant<A...> &x, M &mutator) { void Walk(std::variant<A...> &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
std::visit([&](auto &y) { Walk(y, mutator); }, x); std::visit([&](auto &y) { Walk(y, mutator); }, x);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename A, typename B, typename V> template <typename A, typename B, typename V>
void Walk(const std::pair<A, B> &x, V &visitor) { void Walk(const std::pair<A, B> &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.first, visitor); Walk(x.first, visitor);
Walk(x.second, visitor); Walk(x.second, visitor);
} }
} }
template<typename A, typename B, typename M> template <typename A, typename B, typename M>
void Walk(std::pair<A, B> &x, M &mutator) { void Walk(std::pair<A, B> &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.first, mutator); Walk(x.first, mutator);
@ -160,27 +161,27 @@ void Walk(std::pair<A, B> &x, M &mutator) {
// Trait-determined traversal of empty, tuple, union, wrapper, // Trait-determined traversal of empty, tuple, union, wrapper,
// and constraint-checking classes. // and constraint-checking classes.
template<typename A, typename V> template <typename A, typename V>
std::enable_if_t<EmptyTrait<A>> Walk(const A &x, V &visitor) { std::enable_if_t<EmptyTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename M> template <typename A, typename M>
std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) { std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename A, typename V> template <typename A, typename V>
std::enable_if_t<TupleTrait<A>> Walk(const A &x, V &visitor) { std::enable_if_t<TupleTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.t, visitor); Walk(x.t, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename M> template <typename A, typename M>
std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) { std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.t, mutator); Walk(x.t, mutator);
@ -188,14 +189,14 @@ std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
} }
} }
template<typename A, typename V> template <typename A, typename V>
std::enable_if_t<UnionTrait<A>> Walk(const A &x, V &visitor) { std::enable_if_t<UnionTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.u, visitor); Walk(x.u, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename M> template <typename A, typename M>
std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) { std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.u, mutator); Walk(x.u, mutator);
@ -203,14 +204,14 @@ std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
} }
} }
template<typename A, typename V> template <typename A, typename V>
std::enable_if_t<WrapperTrait<A>> Walk(const A &x, V &visitor) { std::enable_if_t<WrapperTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.v, visitor); Walk(x.v, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename M> template <typename A, typename M>
std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) { std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.v, mutator); Walk(x.v, mutator);
@ -218,14 +219,14 @@ std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
} }
} }
template<typename A, typename V> template <typename A, typename V>
std::enable_if_t<ConstraintTrait<A>> Walk(const A &x, V &visitor) { std::enable_if_t<ConstraintTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.thing, visitor); Walk(x.thing, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename M> template <typename A, typename M>
std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) { std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.thing, mutator); Walk(x.thing, mutator);
@ -233,16 +234,16 @@ std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) {
} }
} }
template<typename T, typename V> template <typename T, typename V>
void Walk(const common::Indirection<T> &x, V &visitor) { void Walk(const common::Indirection<T> &x, V &visitor) {
Walk(x.value(), visitor); Walk(x.value(), visitor);
} }
template<typename T, typename M> template <typename T, typename M>
void Walk(common::Indirection<T> &x, M &mutator) { void Walk(common::Indirection<T> &x, M &mutator) {
Walk(x.value(), mutator); Walk(x.value(), mutator);
} }
template<typename T, typename V> void Walk(const Statement<T> &x, V &visitor) { template <typename T, typename V> void Walk(const Statement<T> &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
// N.B. The label, if any, is not visited. // N.B. The label, if any, is not visited.
Walk(x.source, visitor); Walk(x.source, visitor);
@ -250,7 +251,7 @@ template<typename T, typename V> void Walk(const Statement<T> &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename T, typename M> void Walk(Statement<T> &x, M &mutator) { template <typename T, typename M> void Walk(Statement<T> &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
// N.B. The label, if any, is not visited. // N.B. The label, if any, is not visited.
Walk(x.source, mutator); Walk(x.source, mutator);
@ -259,7 +260,7 @@ template<typename T, typename M> void Walk(Statement<T> &x, M &mutator) {
} }
} }
template<typename T, typename V> template <typename T, typename V>
void Walk(const UnlabeledStatement<T> &x, V &visitor) { void Walk(const UnlabeledStatement<T> &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
@ -267,7 +268,7 @@ void Walk(const UnlabeledStatement<T> &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename T, typename M> template <typename T, typename M>
void Walk(UnlabeledStatement<T> &x, M &mutator) { void Walk(UnlabeledStatement<T> &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
@ -276,48 +277,48 @@ void Walk(UnlabeledStatement<T> &x, M &mutator) {
} }
} }
template<typename V> void Walk(const Name &x, V &visitor) { template <typename V> void Walk(const Name &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(Name &x, M &mutator) { template <typename M> void Walk(Name &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const AcSpec &x, V &visitor) { template <typename V> void Walk(const AcSpec &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.type, visitor); Walk(x.type, visitor);
Walk(x.values, visitor); Walk(x.values, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(AcSpec &x, M &mutator) { template <typename M> void Walk(AcSpec &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.type, mutator); Walk(x.type, mutator);
Walk(x.values, mutator); Walk(x.values, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const ArrayElement &x, V &visitor) { template <typename V> void Walk(const ArrayElement &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.base, visitor); Walk(x.base, visitor);
Walk(x.subscripts, visitor); Walk(x.subscripts, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(ArrayElement &x, M &mutator) { template <typename M> void Walk(ArrayElement &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.base, mutator); Walk(x.base, mutator);
Walk(x.subscripts, mutator); Walk(x.subscripts, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const CharSelector::LengthAndKind &x, V &visitor) { void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.length, visitor); Walk(x.length, visitor);
@ -325,130 +326,131 @@ void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(CharSelector::LengthAndKind &x, M &mutator) { template <typename M> void Walk(CharSelector::LengthAndKind &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.length, mutator); Walk(x.length, mutator);
Walk(x.kind, mutator); Walk(x.kind, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const CaseValueRange::Range &x, V &visitor) { template <typename V> void Walk(const CaseValueRange::Range &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.lower, visitor); Walk(x.lower, visitor);
Walk(x.upper, visitor); Walk(x.upper, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(CaseValueRange::Range &x, M &mutator) { template <typename M> void Walk(CaseValueRange::Range &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.lower, mutator); Walk(x.lower, mutator);
Walk(x.upper, mutator); Walk(x.upper, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const CoindexedNamedObject &x, V &visitor) { template <typename V> void Walk(const CoindexedNamedObject &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.base, visitor); Walk(x.base, visitor);
Walk(x.imageSelector, visitor); Walk(x.imageSelector, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(CoindexedNamedObject &x, M &mutator) { template <typename M> void Walk(CoindexedNamedObject &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.base, mutator); Walk(x.base, mutator);
Walk(x.imageSelector, mutator); Walk(x.imageSelector, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const DeclarationTypeSpec::Class &x, V &visitor) { void Walk(const DeclarationTypeSpec::Class &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.derived, visitor); Walk(x.derived, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(DeclarationTypeSpec::Class &x, M &mutator) { template <typename M> void Walk(DeclarationTypeSpec::Class &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.derived, mutator); Walk(x.derived, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const DeclarationTypeSpec::Type &x, V &visitor) { template <typename V>
void Walk(const DeclarationTypeSpec::Type &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.derived, visitor); Walk(x.derived, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(DeclarationTypeSpec::Type &x, M &mutator) { template <typename M> void Walk(DeclarationTypeSpec::Type &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.derived, mutator); Walk(x.derived, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const ImportStmt &x, V &visitor) { template <typename V> void Walk(const ImportStmt &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.names, visitor); Walk(x.names, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(ImportStmt &x, M &mutator) { template <typename M> void Walk(ImportStmt &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.names, mutator); Walk(x.names, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) { void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.selector, visitor); Walk(x.selector, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(IntrinsicTypeSpec::Character &x, M &mutator) { template <typename M> void Walk(IntrinsicTypeSpec::Character &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.selector, mutator); Walk(x.selector, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) { void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.kind, visitor); Walk(x.kind, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) { template <typename M> void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.kind, mutator); Walk(x.kind, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) { void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.kind, visitor); Walk(x.kind, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) { template <typename M> void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.kind, mutator); Walk(x.kind, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) { template <typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.kind, visitor); Walk(x.kind, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(IntrinsicTypeSpec::Real &x, M &mutator) { template <typename M> void Walk(IntrinsicTypeSpec::Real &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.kind, mutator); Walk(x.kind, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename A, typename B, typename V> template <typename A, typename B, typename V>
void Walk(const LoopBounds<A, B> &x, V &visitor) { void Walk(const LoopBounds<A, B> &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.name, visitor); Walk(x.name, visitor);
@ -458,7 +460,7 @@ void Walk(const LoopBounds<A, B> &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename A, typename B, typename M> template <typename A, typename B, typename M>
void Walk(LoopBounds<A, B> &x, M &mutator) { void Walk(LoopBounds<A, B> &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.name, mutator); Walk(x.name, mutator);
@ -468,61 +470,61 @@ void Walk(LoopBounds<A, B> &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const CommonStmt &x, V &visitor) { template <typename V> void Walk(const CommonStmt &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.blocks, visitor); Walk(x.blocks, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(CommonStmt &x, M &mutator) { template <typename M> void Walk(CommonStmt &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.blocks, mutator); Walk(x.blocks, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const Expr &x, V &visitor) { template <typename V> void Walk(const Expr &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
Walk(x.u, visitor); Walk(x.u, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(Expr &x, M &mutator) { template <typename M> void Walk(Expr &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
Walk(x.u, mutator); Walk(x.u, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const Designator &x, V &visitor) { template <typename V> void Walk(const Designator &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
Walk(x.u, visitor); Walk(x.u, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(Designator &x, M &mutator) { template <typename M> void Walk(Designator &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
Walk(x.u, mutator); Walk(x.u, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const Call &x, V &visitor) { template <typename V> void Walk(const Call &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
Walk(x.t, visitor); Walk(x.t, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(Call &x, M &mutator) { template <typename M> void Walk(Call &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
Walk(x.t, mutator); Walk(x.t, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const PartRef &x, V &visitor) { template <typename V> void Walk(const PartRef &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.name, visitor); Walk(x.name, visitor);
Walk(x.subscripts, visitor); Walk(x.subscripts, visitor);
@ -530,7 +532,7 @@ template<typename V> void Walk(const PartRef &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(PartRef &x, M &mutator) { template <typename M> void Walk(PartRef &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.name, mutator); Walk(x.name, mutator);
Walk(x.subscripts, mutator); Walk(x.subscripts, mutator);
@ -538,7 +540,7 @@ template<typename M> void Walk(PartRef &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const ReadStmt &x, V &visitor) { template <typename V> void Walk(const ReadStmt &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.iounit, visitor); Walk(x.iounit, visitor);
Walk(x.format, visitor); Walk(x.format, visitor);
@ -547,7 +549,7 @@ template<typename V> void Walk(const ReadStmt &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(ReadStmt &x, M &mutator) { template <typename M> void Walk(ReadStmt &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.iounit, mutator); Walk(x.iounit, mutator);
Walk(x.format, mutator); Walk(x.format, mutator);
@ -556,75 +558,76 @@ template<typename M> void Walk(ReadStmt &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const SignedIntLiteralConstant &x, V &visitor) { template <typename V> void Walk(const SignedIntLiteralConstant &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
Walk(x.t, visitor); Walk(x.t, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(SignedIntLiteralConstant &x, M &mutator) { template <typename M> void Walk(SignedIntLiteralConstant &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
Walk(x.t, mutator); Walk(x.t, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const RealLiteralConstant &x, V &visitor) { template <typename V> void Walk(const RealLiteralConstant &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.real, visitor); Walk(x.real, visitor);
Walk(x.kind, visitor); Walk(x.kind, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(RealLiteralConstant &x, M &mutator) { template <typename M> void Walk(RealLiteralConstant &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.real, mutator); Walk(x.real, mutator);
Walk(x.kind, mutator); Walk(x.kind, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const RealLiteralConstant::Real &x, V &visitor) { template <typename V>
void Walk(const RealLiteralConstant::Real &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(RealLiteralConstant::Real &x, M &mutator) { template <typename M> void Walk(RealLiteralConstant::Real &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const StructureComponent &x, V &visitor) { template <typename V> void Walk(const StructureComponent &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.base, visitor); Walk(x.base, visitor);
Walk(x.component, visitor); Walk(x.component, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(StructureComponent &x, M &mutator) { template <typename M> void Walk(StructureComponent &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.base, mutator); Walk(x.base, mutator);
Walk(x.component, mutator); Walk(x.component, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const Suffix &x, V &visitor) { template <typename V> void Walk(const Suffix &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.binding, visitor); Walk(x.binding, visitor);
Walk(x.resultName, visitor); Walk(x.resultName, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(Suffix &x, M &mutator) { template <typename M> void Walk(Suffix &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.binding, mutator); Walk(x.binding, mutator);
Walk(x.resultName, mutator); Walk(x.resultName, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) { void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.interfaceName, visitor); Walk(x.interfaceName, visitor);
@ -633,7 +636,7 @@ void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> template <typename M>
void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) { void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.interfaceName, mutator); Walk(x.interfaceName, mutator);
@ -642,7 +645,7 @@ void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) { void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.attributes, visitor); Walk(x.attributes, visitor);
@ -650,7 +653,7 @@ void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> template <typename M>
void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) { void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.attributes, mutator); Walk(x.attributes, mutator);
@ -658,7 +661,7 @@ void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const UseStmt &x, V &visitor) { template <typename V> void Walk(const UseStmt &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.nature, visitor); Walk(x.nature, visitor);
Walk(x.moduleName, visitor); Walk(x.moduleName, visitor);
@ -666,7 +669,7 @@ template<typename V> void Walk(const UseStmt &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(UseStmt &x, M &mutator) { template <typename M> void Walk(UseStmt &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.nature, mutator); Walk(x.nature, mutator);
Walk(x.moduleName, mutator); Walk(x.moduleName, mutator);
@ -674,7 +677,7 @@ template<typename M> void Walk(UseStmt &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const WriteStmt &x, V &visitor) { template <typename V> void Walk(const WriteStmt &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.iounit, visitor); Walk(x.iounit, visitor);
Walk(x.format, visitor); Walk(x.format, visitor);
@ -683,7 +686,7 @@ template<typename V> void Walk(const WriteStmt &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(WriteStmt &x, M &mutator) { template <typename M> void Walk(WriteStmt &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.iounit, mutator); Walk(x.iounit, mutator);
Walk(x.format, mutator); Walk(x.format, mutator);
@ -692,19 +695,19 @@ template<typename M> void Walk(WriteStmt &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const format::ControlEditDesc &x, V &visitor) { template <typename V> void Walk(const format::ControlEditDesc &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.kind, visitor); Walk(x.kind, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(format::ControlEditDesc &x, M &mutator) { template <typename M> void Walk(format::ControlEditDesc &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.kind, mutator); Walk(x.kind, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) { void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.type, visitor); Walk(x.type, visitor);
@ -712,28 +715,29 @@ void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) { template <typename M>
void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.type, mutator); Walk(x.type, mutator);
Walk(x.parameters, mutator); Walk(x.parameters, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const format::FormatItem &x, V &visitor) { template <typename V> void Walk(const format::FormatItem &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.repeatCount, visitor); Walk(x.repeatCount, visitor);
Walk(x.u, visitor); Walk(x.u, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(format::FormatItem &x, M &mutator) { template <typename M> void Walk(format::FormatItem &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.repeatCount, mutator); Walk(x.repeatCount, mutator);
Walk(x.u, mutator); Walk(x.u, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const format::FormatSpecification &x, V &visitor) { void Walk(const format::FormatSpecification &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.items, visitor); Walk(x.items, visitor);
@ -741,14 +745,14 @@ void Walk(const format::FormatSpecification &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(format::FormatSpecification &x, M &mutator) { template <typename M> void Walk(format::FormatSpecification &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.items, mutator); Walk(x.items, mutator);
Walk(x.unlimitedItems, mutator); Walk(x.unlimitedItems, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) { void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.kind, visitor); Walk(x.kind, visitor);
@ -758,7 +762,7 @@ void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> template <typename M>
void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) { void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.kind, mutator); Walk(x.kind, mutator);
@ -768,21 +772,21 @@ void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> void Walk(const CompilerDirective &x, V &visitor) { template <typename V> void Walk(const CompilerDirective &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.source, visitor); Walk(x.source, visitor);
Walk(x.u, visitor); Walk(x.u, visitor);
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(CompilerDirective &x, M &mutator) { template <typename M> void Walk(CompilerDirective &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.source, mutator); Walk(x.source, mutator);
Walk(x.u, mutator); Walk(x.u, mutator);
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { void Walk(const OmpLinearClause::WithModifier &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.modifier, visitor); Walk(x.modifier, visitor);
@ -791,7 +795,7 @@ void Walk(const OmpLinearClause::WithModifier &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> void Walk(OmpLinearClause::WithModifier &x, M &mutator) { template <typename M> void Walk(OmpLinearClause::WithModifier &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.modifier, mutator); Walk(x.modifier, mutator);
Walk(x.names, mutator); Walk(x.names, mutator);
@ -799,7 +803,7 @@ template<typename M> void Walk(OmpLinearClause::WithModifier &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
template<typename V> template <typename V>
void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) { void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) {
if (visitor.Pre(x)) { if (visitor.Pre(x)) {
Walk(x.names, visitor); Walk(x.names, visitor);
@ -807,7 +811,7 @@ void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) {
visitor.Post(x); visitor.Post(x);
} }
} }
template<typename M> template <typename M>
void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) { void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
if (mutator.Pre(x)) { if (mutator.Pre(x)) {
Walk(x.names, mutator); Walk(x.names, mutator);
@ -815,5 +819,5 @@ void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
mutator.Post(x); mutator.Post(x);
} }
} }
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ #endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_

View File

@ -58,15 +58,15 @@ namespace Fortran::semantics {
class Symbol; class Symbol;
class DeclTypeSpec; class DeclTypeSpec;
class DerivedTypeSpec; class DerivedTypeSpec;
} } // namespace Fortran::semantics
// Expressions in the parse tree have owning pointers that can be set to // Expressions in the parse tree have owning pointers that can be set to
// type-checked generic expression representations by semantic analysis. // type-checked generic expression representations by semantic analysis.
namespace Fortran::evaluate { namespace Fortran::evaluate {
struct GenericExprWrapper; // forward definition, wraps Expr<SomeType> struct GenericExprWrapper; // forward definition, wraps Expr<SomeType>
struct GenericAssignmentWrapper; // forward definition, represent assignment struct GenericAssignmentWrapper; // forward definition, represent assignment
class ProcedureRef; // forward definition, represents a CALL statement class ProcedureRef; // forward definition, represents a CALL statement
} } // namespace Fortran::evaluate
// Most non-template classes in this file use these default definitions // Most non-template classes in this file use these default definitions
// for their move constructor and move assignment operator=, and disable // for their move constructor and move assignment operator=, and disable
@ -97,7 +97,7 @@ class ProcedureRef; // forward definition, represents a CALL statement
// Many classes below simply wrap a std::variant<> discriminated union, // Many classes below simply wrap a std::variant<> discriminated union,
// which is conventionally named "u". // which is conventionally named "u".
#define UNION_CLASS_BOILERPLATE(classname) \ #define UNION_CLASS_BOILERPLATE(classname) \
template<typename A, typename = common::NoLvalue<A>> \ template <typename A, typename = common::NoLvalue<A>> \
classname(A &&x) : u(std::move(x)) {} \ classname(A &&x) : u(std::move(x)) {} \
using UnionTrait = std::true_type; \ using UnionTrait = std::true_type; \
BOILERPLATE(classname) BOILERPLATE(classname)
@ -105,7 +105,7 @@ class ProcedureRef; // forward definition, represents a CALL statement
// Many other classes below simply wrap a std::tuple<> structure, which // Many other classes below simply wrap a std::tuple<> structure, which
// is conventionally named "t". // is conventionally named "t".
#define TUPLE_CLASS_BOILERPLATE(classname) \ #define TUPLE_CLASS_BOILERPLATE(classname) \
template<typename... Ts, typename = common::NoLvalue<Ts...>> \ template <typename... Ts, typename = common::NoLvalue<Ts...>> \
classname(Ts &&... args) : t(std::move(args)...) {} \ classname(Ts &&... args) : t(std::move(args)...) {} \
using TupleTrait = std::true_type; \ using TupleTrait = std::true_type; \
BOILERPLATE(classname) BOILERPLATE(classname)
@ -129,123 +129,123 @@ namespace Fortran::parser {
// Some references to the representations of their parses require // Some references to the representations of their parses require
// indirection. The Indirect<> pointer wrapper class is used to // indirection. The Indirect<> pointer wrapper class is used to
// enforce ownership semantics and non-nullability. // enforce ownership semantics and non-nullability.
struct SpecificationPart; // R504 struct SpecificationPart; // R504
struct ExecutableConstruct; // R514 struct ExecutableConstruct; // R514
struct ActionStmt; // R515 struct ActionStmt; // R515
struct AcImpliedDo; // R774 struct AcImpliedDo; // R774
struct DataImpliedDo; // R840 struct DataImpliedDo; // R840
struct Designator; // R901 struct Designator; // R901
struct Variable; // R902 struct Variable; // R902
struct Expr; // R1001 struct Expr; // R1001
struct WhereConstruct; // R1042 struct WhereConstruct; // R1042
struct ForallConstruct; // R1050 struct ForallConstruct; // R1050
struct InputImpliedDo; // R1218 struct InputImpliedDo; // R1218
struct OutputImpliedDo; // R1218 struct OutputImpliedDo; // R1218
struct FunctionReference; // R1520 struct FunctionReference; // R1520
struct FunctionSubprogram; // R1529 struct FunctionSubprogram; // R1529
struct SubroutineSubprogram; // R1534 struct SubroutineSubprogram; // R1534
// These additional forward references are declared so that the order of // These additional forward references are declared so that the order of
// class definitions in this header file can remain reasonably consistent // class definitions in this header file can remain reasonably consistent
// with order of the the requirement productions in the grammar. // with order of the the requirement productions in the grammar.
struct DerivedTypeDef; // R726 struct DerivedTypeDef; // R726
struct EnumDef; // R759 struct EnumDef; // R759
struct TypeDeclarationStmt; // R801 struct TypeDeclarationStmt; // R801
struct AccessStmt; // R827 struct AccessStmt; // R827
struct AllocatableStmt; // R829 struct AllocatableStmt; // R829
struct AsynchronousStmt; // R831 struct AsynchronousStmt; // R831
struct BindStmt; // R832 struct BindStmt; // R832
struct CodimensionStmt; // R834 struct CodimensionStmt; // R834
struct ContiguousStmt; // R836 struct ContiguousStmt; // R836
struct DataStmt; // R837 struct DataStmt; // R837
struct DataStmtValue; // R843 struct DataStmtValue; // R843
struct DimensionStmt; // R848 struct DimensionStmt; // R848
struct IntentStmt; // R849 struct IntentStmt; // R849
struct OptionalStmt; // R850 struct OptionalStmt; // R850
struct ParameterStmt; // R851 struct ParameterStmt; // R851
struct OldParameterStmt; struct OldParameterStmt;
struct PointerStmt; // R853 struct PointerStmt; // R853
struct ProtectedStmt; // R855 struct ProtectedStmt; // R855
struct SaveStmt; // R856 struct SaveStmt; // R856
struct TargetStmt; // R859 struct TargetStmt; // R859
struct ValueStmt; // R861 struct ValueStmt; // R861
struct VolatileStmt; // R862 struct VolatileStmt; // R862
struct ImplicitStmt; // R863 struct ImplicitStmt; // R863
struct ImportStmt; // R867 struct ImportStmt; // R867
struct NamelistStmt; // R868 struct NamelistStmt; // R868
struct EquivalenceStmt; // R870 struct EquivalenceStmt; // R870
struct CommonStmt; // R873 struct CommonStmt; // R873
struct Substring; // R908 struct Substring; // R908
struct CharLiteralConstantSubstring; struct CharLiteralConstantSubstring;
struct DataRef; // R911 struct DataRef; // R911
struct StructureComponent; // R913 struct StructureComponent; // R913
struct CoindexedNamedObject; // R914 struct CoindexedNamedObject; // R914
struct ArrayElement; // R917 struct ArrayElement; // R917
struct AllocateStmt; // R927 struct AllocateStmt; // R927
struct NullifyStmt; // R939 struct NullifyStmt; // R939
struct DeallocateStmt; // R941 struct DeallocateStmt; // R941
struct AssignmentStmt; // R1032 struct AssignmentStmt; // R1032
struct PointerAssignmentStmt; // R1033 struct PointerAssignmentStmt; // R1033
struct WhereStmt; // R1041, R1045, R1046 struct WhereStmt; // R1041, R1045, R1046
struct ForallStmt; // R1055 struct ForallStmt; // R1055
struct AssociateConstruct; // R1102 struct AssociateConstruct; // R1102
struct BlockConstruct; // R1107 struct BlockConstruct; // R1107
struct ChangeTeamConstruct; // R1111 struct ChangeTeamConstruct; // R1111
struct CriticalConstruct; // R1116 struct CriticalConstruct; // R1116
struct DoConstruct; // R1119 struct DoConstruct; // R1119
struct LabelDoStmt; // R1121 struct LabelDoStmt; // R1121
struct ConcurrentHeader; // R1125 struct ConcurrentHeader; // R1125
struct EndDoStmt; // R1132 struct EndDoStmt; // R1132
struct CycleStmt; // R1133 struct CycleStmt; // R1133
struct IfConstruct; // R1134 struct IfConstruct; // R1134
struct IfStmt; // R1139 struct IfStmt; // R1139
struct CaseConstruct; // R1140 struct CaseConstruct; // R1140
struct SelectRankConstruct; // R1148 struct SelectRankConstruct; // R1148
struct SelectTypeConstruct; // R1152 struct SelectTypeConstruct; // R1152
struct ExitStmt; // R1156 struct ExitStmt; // R1156
struct GotoStmt; // R1157 struct GotoStmt; // R1157
struct ComputedGotoStmt; // R1158 struct ComputedGotoStmt; // R1158
struct StopStmt; // R1160, R1161 struct StopStmt; // R1160, R1161
struct SyncAllStmt; // R1164 struct SyncAllStmt; // R1164
struct SyncImagesStmt; // R1166 struct SyncImagesStmt; // R1166
struct SyncMemoryStmt; // R1168 struct SyncMemoryStmt; // R1168
struct SyncTeamStmt; // R1169 struct SyncTeamStmt; // R1169
struct EventPostStmt; // R1170, R1171 struct EventPostStmt; // R1170, R1171
struct EventWaitStmt; // R1172, R1173, R1174 struct EventWaitStmt; // R1172, R1173, R1174
struct FormTeamStmt; // R1175, R1176, R1177 struct FormTeamStmt; // R1175, R1176, R1177
struct LockStmt; // R1178 struct LockStmt; // R1178
struct UnlockStmt; // R1180 struct UnlockStmt; // R1180
struct OpenStmt; // R1204 struct OpenStmt; // R1204
struct CloseStmt; // R1208 struct CloseStmt; // R1208
struct ReadStmt; // R1210 struct ReadStmt; // R1210
struct WriteStmt; // R1211 struct WriteStmt; // R1211
struct PrintStmt; // R1212 struct PrintStmt; // R1212
struct WaitStmt; // R1222 struct WaitStmt; // R1222
struct BackspaceStmt; // R1224 struct BackspaceStmt; // R1224
struct EndfileStmt; // R1225 struct EndfileStmt; // R1225
struct RewindStmt; // R1226 struct RewindStmt; // R1226
struct FlushStmt; // R1228 struct FlushStmt; // R1228
struct InquireStmt; // R1230 struct InquireStmt; // R1230
struct FormatStmt; // R1301 struct FormatStmt; // R1301
struct MainProgram; // R1401 struct MainProgram; // R1401
struct Module; // R1404 struct Module; // R1404
struct UseStmt; // R1409 struct UseStmt; // R1409
struct Submodule; // R1416 struct Submodule; // R1416
struct BlockData; // R1420 struct BlockData; // R1420
struct InterfaceBlock; // R1501 struct InterfaceBlock; // R1501
struct GenericSpec; // R1508 struct GenericSpec; // R1508
struct GenericStmt; // R1510 struct GenericStmt; // R1510
struct ExternalStmt; // R1511 struct ExternalStmt; // R1511
struct ProcedureDeclarationStmt; // R1512 struct ProcedureDeclarationStmt; // R1512
struct IntrinsicStmt; // R1519 struct IntrinsicStmt; // R1519
struct Call; // R1520 & R1521 struct Call; // R1520 & R1521
struct CallStmt; // R1521 struct CallStmt; // R1521
struct ProcedureDesignator; // R1522 struct ProcedureDesignator; // R1522
struct ActualArg; // R1524 struct ActualArg; // R1524
struct SeparateModuleSubprogram; // R1538 struct SeparateModuleSubprogram; // R1538
struct EntryStmt; // R1541 struct EntryStmt; // R1541
struct ReturnStmt; // R1542 struct ReturnStmt; // R1542
struct StmtFunctionStmt; // R1544 struct StmtFunctionStmt; // R1544
// Directives, extensions, and deprecated statements // Directives, extensions, and deprecated statements
struct CompilerDirective; struct CompilerDirective;
@ -274,7 +274,7 @@ struct Verbatim {
// R403 scalar-xyz -> xyz // R403 scalar-xyz -> xyz
// These template class wrappers correspond to the Standard's modifiers // These template class wrappers correspond to the Standard's modifiers
// scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz. // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
template<typename A> struct Scalar { template <typename A> struct Scalar {
using ConstraintTrait = std::true_type; using ConstraintTrait = std::true_type;
Scalar(Scalar &&that) = default; Scalar(Scalar &&that) = default;
Scalar(A &&that) : thing(std::move(that)) {} Scalar(A &&that) : thing(std::move(that)) {}
@ -282,7 +282,7 @@ template<typename A> struct Scalar {
A thing; A thing;
}; };
template<typename A> struct Constant { template <typename A> struct Constant {
using ConstraintTrait = std::true_type; using ConstraintTrait = std::true_type;
Constant(Constant &&that) = default; Constant(Constant &&that) = default;
Constant(A &&that) : thing(std::move(that)) {} Constant(A &&that) : thing(std::move(that)) {}
@ -290,7 +290,7 @@ template<typename A> struct Constant {
A thing; A thing;
}; };
template<typename A> struct Integer { template <typename A> struct Integer {
using ConstraintTrait = std::true_type; using ConstraintTrait = std::true_type;
Integer(Integer &&that) = default; Integer(Integer &&that) = default;
Integer(A &&that) : thing(std::move(that)) {} Integer(A &&that) : thing(std::move(that)) {}
@ -298,7 +298,7 @@ template<typename A> struct Integer {
A thing; A thing;
}; };
template<typename A> struct Logical { template <typename A> struct Logical {
using ConstraintTrait = std::true_type; using ConstraintTrait = std::true_type;
Logical(Logical &&that) = default; Logical(Logical &&that) = default;
Logical(A &&that) : thing(std::move(that)) {} Logical(A &&that) : thing(std::move(that)) {}
@ -306,7 +306,7 @@ template<typename A> struct Logical {
A thing; A thing;
}; };
template<typename A> struct DefaultChar { template <typename A> struct DefaultChar {
using ConstraintTrait = std::true_type; using ConstraintTrait = std::true_type;
DefaultChar(DefaultChar &&that) = default; DefaultChar(DefaultChar &&that) = default;
DefaultChar(A &&that) : thing(std::move(that)) {} DefaultChar(A &&that) : thing(std::move(that)) {}
@ -314,11 +314,11 @@ template<typename A> struct DefaultChar {
A thing; A thing;
}; };
using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024 using LogicalExpr = Logical<common::Indirection<Expr>>; // R1024
using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025 using DefaultCharExpr = DefaultChar<common::Indirection<Expr>>; // R1025
using IntExpr = Integer<common::Indirection<Expr>>; // R1026 using IntExpr = Integer<common::Indirection<Expr>>; // R1026
using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029 using ConstantExpr = Constant<common::Indirection<Expr>>; // R1029
using IntConstantExpr = Integer<ConstantExpr>; // R1031 using IntConstantExpr = Integer<ConstantExpr>; // R1031
using ScalarLogicalExpr = Scalar<LogicalExpr>; using ScalarLogicalExpr = Scalar<LogicalExpr>;
using ScalarIntExpr = Scalar<IntExpr>; using ScalarIntExpr = Scalar<IntExpr>;
using ScalarIntConstantExpr = Scalar<IntConstantExpr>; using ScalarIntConstantExpr = Scalar<IntConstantExpr>;
@ -328,18 +328,18 @@ using ScalarDefaultCharExpr = Scalar<DefaultCharExpr>;
using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>; using ScalarDefaultCharConstantExpr = Scalar<DefaultChar<ConstantExpr>>;
// R611 label -> digit [digit]... // R611 label -> digit [digit]...
using Label = std::uint64_t; // validated later, must be in [1..99999] using Label = std::uint64_t; // validated later, must be in [1..99999]
// A wrapper for xzy-stmt productions that are statements, so that // A wrapper for xzy-stmt productions that are statements, so that
// source provenances and labels have a uniform representation. // source provenances and labels have a uniform representation.
template<typename A> struct UnlabeledStatement { template <typename A> struct UnlabeledStatement {
explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {} explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {}
CharBlock source; CharBlock source;
A statement; A statement;
}; };
template<typename A> struct Statement : public UnlabeledStatement<A> { template <typename A> struct Statement : public UnlabeledStatement<A> {
Statement(std::optional<long> &&lab, A &&s) Statement(std::optional<long> &&lab, A &&s)
: UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {} : UnlabeledStatement<A>{std::move(s)}, label(std::move(lab)) {}
std::optional<Label> label; std::optional<Label> label;
}; };
@ -548,7 +548,7 @@ WRAPPER_CLASS(Program, std::list<ProgramUnit>);
struct Name { struct Name {
std::string ToString() const { return source.ToString(); } std::string ToString() const { return source.ToString(); }
CharBlock source; CharBlock source;
mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics mutable semantics::Symbol *symbol{nullptr}; // filled in during semantics
}; };
// R516 keyword -> name // R516 keyword -> name
@ -609,7 +609,7 @@ EMPTY_CLASS(Star);
struct TypeParamValue { struct TypeParamValue {
UNION_CLASS_BOILERPLATE(TypeParamValue); UNION_CLASS_BOILERPLATE(TypeParamValue);
EMPTY_CLASS(Deferred); // : EMPTY_CLASS(Deferred); // :
std::variant<ScalarIntExpr, Star, Deferred> u; std::variant<ScalarIntExpr, Star, Deferred> u;
}; };
@ -647,14 +647,14 @@ struct CharSelector {
struct LengthAndKind { struct LengthAndKind {
BOILERPLATE(LengthAndKind); BOILERPLATE(LengthAndKind);
LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k) LengthAndKind(std::optional<TypeParamValue> &&l, ScalarIntConstantExpr &&k)
: length(std::move(l)), kind(std::move(k)) {} : length(std::move(l)), kind(std::move(k)) {}
std::optional<TypeParamValue> length; std::optional<TypeParamValue> length;
ScalarIntConstantExpr kind; ScalarIntConstantExpr kind;
}; };
CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k) CharSelector(TypeParamValue &&l, ScalarIntConstantExpr &&k)
: u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {} : u{LengthAndKind{std::make_optional(std::move(l)), std::move(k)}} {}
CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l) CharSelector(ScalarIntConstantExpr &&k, std::optional<TypeParamValue> &&l)
: u{LengthAndKind{std::move(l), std::move(k)}} {} : u{LengthAndKind{std::move(l), std::move(k)}} {}
std::variant<LengthSelector, LengthAndKind> u; std::variant<LengthSelector, LengthAndKind> u;
}; };
@ -770,7 +770,7 @@ struct RealLiteralConstant {
CharBlock source; CharBlock source;
}; };
RealLiteralConstant(Real &&r, std::optional<KindParam> &&k) RealLiteralConstant(Real &&r, std::optional<KindParam> &&k)
: real{std::move(r)}, kind{std::move(k)} {} : real{std::move(r)}, kind{std::move(k)} {}
Real real; Real real;
std::optional<KindParam> kind; std::optional<KindParam> kind;
}; };
@ -797,7 +797,7 @@ struct ComplexPart {
// R718 complex-literal-constant -> ( real-part , imag-part ) // R718 complex-literal-constant -> ( real-part , imag-part )
struct ComplexLiteralConstant { struct ComplexLiteralConstant {
TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant); TUPLE_CLASS_BOILERPLATE(ComplexLiteralConstant);
std::tuple<ComplexPart, ComplexPart> t; // real, imaginary std::tuple<ComplexPart, ComplexPart> t; // real, imaginary
}; };
// Extension: signed COMPLEX constant // Extension: signed COMPLEX constant
@ -1077,15 +1077,15 @@ struct TypeBoundProcedureStmt {
BOILERPLATE(WithoutInterface); BOILERPLATE(WithoutInterface);
WithoutInterface( WithoutInterface(
std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds) std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds)
: attributes(std::move(as)), declarations(std::move(ds)) {} : attributes(std::move(as)), declarations(std::move(ds)) {}
std::list<BindAttr> attributes; std::list<BindAttr> attributes;
std::list<TypeBoundProcDecl> declarations; std::list<TypeBoundProcDecl> declarations;
}; };
struct WithInterface { struct WithInterface {
BOILERPLATE(WithInterface); BOILERPLATE(WithInterface);
WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs) WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs)
: interfaceName(std::move(n)), attributes(std::move(as)), : interfaceName(std::move(n)), attributes(std::move(as)),
bindingNames(std::move(bs)) {} bindingNames(std::move(bs)) {}
Name interfaceName; Name interfaceName;
std::list<BindAttr> attributes; std::list<BindAttr> attributes;
std::list<Name> bindingNames; std::list<Name> bindingNames;
@ -1184,7 +1184,7 @@ struct EnumDef {
// R773 ac-value -> expr | ac-implied-do // R773 ac-value -> expr | ac-implied-do
struct AcValue { struct AcValue {
struct Triplet { // PGI/Intel extension struct Triplet { // PGI/Intel extension
TUPLE_CLASS_BOILERPLATE(Triplet); TUPLE_CLASS_BOILERPLATE(Triplet);
std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t; std::tuple<ScalarIntExpr, ScalarIntExpr, std::optional<ScalarIntExpr>> t;
}; };
@ -1198,7 +1198,7 @@ struct AcValue {
struct AcSpec { struct AcSpec {
BOILERPLATE(AcSpec); BOILERPLATE(AcSpec);
AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs) AcSpec(std::optional<TypeSpec> &&ts, std::list<AcValue> &&xs)
: type(std::move(ts)), values(std::move(xs)) {} : type(std::move(ts)), values(std::move(xs)) {}
explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {} explicit AcSpec(TypeSpec &&ts) : type{std::move(ts)} {}
std::optional<TypeSpec> type; std::optional<TypeSpec> type;
std::list<AcValue> values; std::list<AcValue> values;
@ -1210,12 +1210,12 @@ WRAPPER_CLASS(ArrayConstructor, AcSpec);
// R1124 do-variable -> scalar-int-variable-name // R1124 do-variable -> scalar-int-variable-name
using DoVariable = Scalar<Integer<Name>>; using DoVariable = Scalar<Integer<Name>>;
template<typename VAR, typename BOUND> struct LoopBounds { template <typename VAR, typename BOUND> struct LoopBounds {
LoopBounds(LoopBounds &&that) = default; LoopBounds(LoopBounds &&that) = default;
LoopBounds( LoopBounds(
VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step) VAR &&name, BOUND &&lower, BOUND &&upper, std::optional<BOUND> &&step)
: name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)}, : name{std::move(name)}, lower{std::move(lower)}, upper{std::move(upper)},
step{std::move(step)} {} step{std::move(step)} {}
LoopBounds &operator=(LoopBounds &&) = default; LoopBounds &operator=(LoopBounds &&) = default;
VAR name; VAR name;
BOUND lower, upper; BOUND lower, upper;
@ -1528,7 +1528,7 @@ struct ImplicitSpec {
// R866 implicit-name-spec -> EXTERNAL | TYPE // R866 implicit-name-spec -> EXTERNAL | TYPE
struct ImplicitStmt { struct ImplicitStmt {
UNION_CLASS_BOILERPLATE(ImplicitStmt); UNION_CLASS_BOILERPLATE(ImplicitStmt);
ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866 ENUM_CLASS(ImplicitNoneNameSpec, External, Type) // R866
std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u; std::variant<std::list<ImplicitSpec>, std::list<ImplicitNoneNameSpec>> u;
}; };
@ -1624,8 +1624,7 @@ struct Expr {
using IntrinsicUnary::IntrinsicUnary; using IntrinsicUnary::IntrinsicUnary;
}; };
WRAPPER_CLASS( WRAPPER_CLASS(PercentLoc, common::Indirection<Variable>); // %LOC(v) extension
PercentLoc, common::Indirection<Variable>); // %LOC(v) extension
struct DefinedUnary { struct DefinedUnary {
TUPLE_CLASS_BOILERPLATE(DefinedUnary); TUPLE_CLASS_BOILERPLATE(DefinedUnary);
@ -1721,8 +1720,8 @@ struct PartRef {
BOILERPLATE(PartRef); BOILERPLATE(PartRef);
PartRef(Name &&n, std::list<SectionSubscript> &&ss, PartRef(Name &&n, std::list<SectionSubscript> &&ss,
std::optional<ImageSelector> &&is) std::optional<ImageSelector> &&is)
: name{std::move(n)}, : name{std::move(n)},
subscripts(std::move(ss)), imageSelector{std::move(is)} {} subscripts(std::move(ss)), imageSelector{std::move(is)} {}
Name name; Name name;
std::list<SectionSubscript> subscripts; std::list<SectionSubscript> subscripts;
std::optional<ImageSelector> imageSelector; std::optional<ImageSelector> imageSelector;
@ -1792,7 +1791,7 @@ using ScalarIntVariable = Scalar<Integer<Variable>>;
struct StructureComponent { struct StructureComponent {
BOILERPLATE(StructureComponent); BOILERPLATE(StructureComponent);
StructureComponent(DataRef &&dr, Name &&n) StructureComponent(DataRef &&dr, Name &&n)
: base{std::move(dr)}, component(std::move(n)) {} : base{std::move(dr)}, component(std::move(n)) {}
DataRef base; DataRef base;
Name component; Name component;
}; };
@ -1807,7 +1806,7 @@ struct ProcComponentRef {
struct CoindexedNamedObject { struct CoindexedNamedObject {
BOILERPLATE(CoindexedNamedObject); BOILERPLATE(CoindexedNamedObject);
CoindexedNamedObject(DataRef &&dr, ImageSelector &&is) CoindexedNamedObject(DataRef &&dr, ImageSelector &&is)
: base{std::move(dr)}, imageSelector{std::move(is)} {} : base{std::move(dr)}, imageSelector{std::move(is)} {}
DataRef base; DataRef base;
ImageSelector imageSelector; ImageSelector imageSelector;
}; };
@ -1816,7 +1815,7 @@ struct CoindexedNamedObject {
struct ArrayElement { struct ArrayElement {
BOILERPLATE(ArrayElement); BOILERPLATE(ArrayElement);
ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss) ArrayElement(DataRef &&dr, std::list<SectionSubscript> &&ss)
: base{std::move(dr)}, subscripts(std::move(ss)) {} : base{std::move(dr)}, subscripts(std::move(ss)) {}
Substring ConvertToSubstring(); Substring ConvertToSubstring();
StructureConstructor ConvertToStructureConstructor( StructureConstructor ConvertToStructureConstructor(
const semantics::DerivedTypeSpec &); const semantics::DerivedTypeSpec &);
@ -2287,8 +2286,8 @@ struct CaseValueRange {
struct Range { struct Range {
BOILERPLATE(Range); BOILERPLATE(Range);
Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u) Range(std::optional<CaseValue> &&l, std::optional<CaseValue> &&u)
: lower{std::move(l)}, upper{std::move(u)} {} : lower{std::move(l)}, upper{std::move(u)} {}
std::optional<CaseValue> lower, upper; // not both missing std::optional<CaseValue> lower, upper; // not both missing
}; };
std::variant<CaseValue, Range> u; std::variant<CaseValue, Range> u;
}; };
@ -2625,13 +2624,13 @@ struct ReadStmt {
BOILERPLATE(ReadStmt); BOILERPLATE(ReadStmt);
ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f, ReadStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
std::list<IoControlSpec> &&cs, std::list<InputItem> &&its) std::list<IoControlSpec> &&cs, std::list<InputItem> &&its)
: iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)), : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
items(std::move(its)) {} items(std::move(its)) {}
std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
// followed by untagged format/namelist // followed by untagged format/namelist
std::optional<Format> format; // if second in controls without FMT=/NML=, or std::optional<Format> format; // if second in controls without FMT=/NML=, or
// no (io-control-spec-list); might be // no (io-control-spec-list); might be
// an untagged namelist group name // an untagged namelist group name
std::list<IoControlSpec> controls; std::list<IoControlSpec> controls;
std::list<InputItem> items; std::list<InputItem> items;
}; };
@ -2647,12 +2646,12 @@ struct WriteStmt {
BOILERPLATE(WriteStmt); BOILERPLATE(WriteStmt);
WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f, WriteStmt(std::optional<IoUnit> &&i, std::optional<Format> &&f,
std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its) std::list<IoControlSpec> &&cs, std::list<OutputItem> &&its)
: iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)), : iounit{std::move(i)}, format{std::move(f)}, controls(std::move(cs)),
items(std::move(its)) {} items(std::move(its)) {}
std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or std::optional<IoUnit> iounit; // if first in controls without UNIT= &/or
// followed by untagged format/namelist // followed by untagged format/namelist
std::optional<Format> format; // if second in controls without FMT=/NML=; std::optional<Format> format; // if second in controls without FMT=/NML=;
// might be an untagged namelist group, too // might be an untagged namelist group, too
std::list<IoControlSpec> controls; std::list<IoControlSpec> controls;
std::list<OutputItem> items; std::list<OutputItem> items;
}; };
@ -2947,10 +2946,10 @@ struct Only {
// R1410 module-nature -> INTRINSIC | NON_INTRINSIC // R1410 module-nature -> INTRINSIC | NON_INTRINSIC
struct UseStmt { struct UseStmt {
BOILERPLATE(UseStmt); BOILERPLATE(UseStmt);
ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410 ENUM_CLASS(ModuleNature, Intrinsic, Non_Intrinsic) // R1410
template<typename A> template <typename A>
UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x) UseStmt(std::optional<ModuleNature> &&nat, Name &&n, std::list<A> &&x)
: nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {} : nature(std::move(nat)), moduleName(std::move(n)), u(std::move(x)) {}
std::optional<ModuleNature> nature; std::optional<ModuleNature> nature;
Name moduleName; Name moduleName;
std::variant<std::list<Rename>, std::list<Only>> u; std::variant<std::list<Rename>, std::list<Only>> u;
@ -2998,9 +2997,9 @@ struct PrefixSpec {
struct Suffix { struct Suffix {
BOILERPLATE(Suffix); BOILERPLATE(Suffix);
Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn) Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
: binding(std::move(lbs)), resultName(std::move(rn)) {} : binding(std::move(lbs)), resultName(std::move(rn)) {}
Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs) Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs)
: binding(std::move(lbs)), resultName(std::move(rn)) {} : binding(std::move(lbs)), resultName(std::move(rn)) {}
std::optional<LanguageBindingSpec> binding; std::optional<LanguageBindingSpec> binding;
std::optional<Name> resultName; std::optional<Name> resultName;
}; };
@ -3103,8 +3102,8 @@ WRAPPER_CLASS(AltReturnSpec, Label);
// expr | variable | procedure-name | proc-component-ref | // expr | variable | procedure-name | proc-component-ref |
// alt-return-spec // alt-return-spec
struct ActualArg { struct ActualArg {
WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension WRAPPER_CLASS(PercentRef, Variable); // %REF(v) extension
WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension WRAPPER_CLASS(PercentVal, Expr); // %VAL(x) extension
UNION_CLASS_BOILERPLATE(ActualArg); UNION_CLASS_BOILERPLATE(ActualArg);
ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {} ActualArg(Expr &&x) : u{common::Indirection<Expr>(std::move(x))} {}
std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal> std::variant<common::Indirection<Expr>, AltReturnSpec, PercentRef, PercentVal>
@ -3136,7 +3135,7 @@ struct CallStmt {
WRAPPER_CLASS_BOILERPLATE(CallStmt, Call); WRAPPER_CLASS_BOILERPLATE(CallStmt, Call);
mutable std::unique_ptr<evaluate::ProcedureRef, mutable std::unique_ptr<evaluate::ProcedureRef,
common::Deleter<evaluate::ProcedureRef>> common::Deleter<evaluate::ProcedureRef>>
typedCall; // filled by semantics typedCall; // filled by semantics
}; };
// R1529 function-subprogram -> // R1529 function-subprogram ->
@ -3371,7 +3370,7 @@ struct OmpLinearClause {
BOILERPLATE(WithModifier); BOILERPLATE(WithModifier);
WithModifier(OmpLinearModifier &&m, std::list<Name> &&n, WithModifier(OmpLinearModifier &&m, std::list<Name> &&n,
std::optional<ScalarIntConstantExpr> &&s) std::optional<ScalarIntConstantExpr> &&s)
: modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {} : modifier(std::move(m)), names(std::move(n)), step(std::move(s)) {}
OmpLinearModifier modifier; OmpLinearModifier modifier;
std::list<Name> names; std::list<Name> names;
std::optional<ScalarIntConstantExpr> step; std::optional<ScalarIntConstantExpr> step;
@ -3380,7 +3379,7 @@ struct OmpLinearClause {
BOILERPLATE(WithoutModifier); BOILERPLATE(WithoutModifier);
WithoutModifier( WithoutModifier(
std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s) std::list<Name> &&n, std::optional<ScalarIntConstantExpr> &&s)
: names(std::move(n)), step(std::move(s)) {} : names(std::move(n)), step(std::move(s)) {}
std::list<Name> names; std::list<Name> names;
std::optional<ScalarIntConstantExpr> step; std::optional<ScalarIntConstantExpr> step;
}; };
@ -3774,7 +3773,7 @@ struct OpenMPBlockConstruct {
struct OpenMPLoopConstruct { struct OpenMPLoopConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct); TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
OpenMPLoopConstruct(OmpBeginLoopDirective &&a) OpenMPLoopConstruct(OmpBeginLoopDirective &&a)
: t({std::move(a), std::nullopt, std::nullopt}) {} : t({std::move(a), std::nullopt, std::nullopt}) {}
std::tuple<OmpBeginLoopDirective, std::optional<DoConstruct>, std::tuple<OmpBeginLoopDirective, std::optional<DoConstruct>,
std::optional<OmpEndLoopDirective>> std::optional<OmpEndLoopDirective>>
t; t;
@ -3787,5 +3786,5 @@ struct OpenMPConstruct {
OpenMPCriticalConstruct> OpenMPCriticalConstruct>
u; u;
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_PARSE_TREE_H_ #endif // FORTRAN_PARSER_PARSE_TREE_H_

View File

@ -56,8 +56,8 @@ public:
void Parse(llvm::raw_ostream &debugOutput); void Parse(llvm::raw_ostream &debugOutput);
void ClearLog(); void ClearLog();
void EmitMessage(llvm::raw_ostream &o, const char *at, const std::string &message, void EmitMessage(llvm::raw_ostream &o, const char *at,
bool echoSourceLine = false) const { const std::string &message, bool echoSourceLine = false) const {
cooked_.allSources().EmitMessage( cooked_.allSources().EmitMessage(
o, cooked_.GetProvenanceRange(CharBlock(at)), message, echoSourceLine); o, cooked_.GetProvenanceRange(CharBlock(at)), message, echoSourceLine);
} }
@ -73,5 +73,5 @@ private:
std::optional<Program> parseTree_; std::optional<Program> parseTree_;
ParsingLog log_; ParsingLog log_;
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_PARSING_H_ #endif // FORTRAN_PARSER_PARSING_H_

View File

@ -168,8 +168,8 @@ public:
Provenance, std::size_t *offset = nullptr) const; Provenance, std::size_t *offset = nullptr) const;
std::optional<SourcePosition> GetSourcePosition(Provenance) const; std::optional<SourcePosition> GetSourcePosition(Provenance) const;
std::optional<ProvenanceRange> GetFirstFileProvenance() const; std::optional<ProvenanceRange> GetFirstFileProvenance() const;
std::string GetPath(Provenance) const; // __FILE__ std::string GetPath(Provenance) const; // __FILE__
int GetLineNumber(Provenance) const; // __LINE__ int GetLineNumber(Provenance) const; // __LINE__
Provenance CompilerInsertionProvenance(char ch); Provenance CompilerInsertionProvenance(char ch);
Provenance CompilerInsertionProvenance(const char *, std::size_t); Provenance CompilerInsertionProvenance(const char *, std::size_t);
ProvenanceRange IntersectionWithSourceFiles(ProvenanceRange) const; ProvenanceRange IntersectionWithSourceFiles(ProvenanceRange) const;
@ -256,17 +256,17 @@ public:
} }
std::size_t BufferedBytes() const; std::size_t BufferedBytes() const;
void Marshal(); // marshals text into one contiguous block void Marshal(); // marshals text into one contiguous block
void CompileProvenanceRangeToOffsetMappings(); void CompileProvenanceRangeToOffsetMappings();
std::string AcquireData() { return std::move(data_); } std::string AcquireData() { return std::move(data_); }
llvm::raw_ostream &Dump(llvm::raw_ostream &) const; llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
private: private:
AllSources &allSources_; AllSources &allSources_;
CharBuffer buffer_; // before Marshal() CharBuffer buffer_; // before Marshal()
std::string data_; // all of it, prescanned and preprocessed std::string data_; // all of it, prescanned and preprocessed
OffsetToProvenanceMappings provenanceMap_; OffsetToProvenanceMappings provenanceMap_;
ProvenanceRangeToOffsetMappings invertedMap_; ProvenanceRangeToOffsetMappings invertedMap_;
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_PROVENANCE_H_ #endif // FORTRAN_PARSER_PROVENANCE_H_

View File

@ -15,11 +15,11 @@
// - A Unicode byte order mark is recognized if present. // - A Unicode byte order mark is recognized if present.
#include "characters.h" #include "characters.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstddef> #include <cstddef>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "llvm/Support/MemoryBuffer.h"
namespace llvm { namespace llvm {
class raw_ostream; class raw_ostream;
@ -43,7 +43,9 @@ public:
explicit SourceFile(Encoding e) : encoding_{e} {} explicit SourceFile(Encoding e) : encoding_{e} {}
~SourceFile(); ~SourceFile();
std::string path() const { return path_; } std::string path() const { return path_; }
llvm::ArrayRef<char> content() const { return buf_->getBuffer().slice(bom_end_, buf_end_ - bom_end_); } llvm::ArrayRef<char> content() const {
return buf_->getBuffer().slice(bom_end_, buf_end_ - bom_end_);
}
std::size_t bytes() const { return content().size(); } std::size_t bytes() const { return content().size(); }
std::size_t lines() const { return lineStart_.size(); } std::size_t lines() const { return lineStart_.size(); }
Encoding encoding() const { return encoding_; } Encoding encoding() const { return encoding_; }
@ -64,9 +66,9 @@ private:
std::string path_; std::string path_;
std::unique_ptr<llvm::WritableMemoryBuffer> buf_; std::unique_ptr<llvm::WritableMemoryBuffer> buf_;
std::vector<std::size_t> lineStart_; std::vector<std::size_t> lineStart_;
std::size_t bom_end_ {0}; std::size_t bom_end_{0};
std::size_t buf_end_; std::size_t buf_end_;
Encoding encoding_; Encoding encoding_;
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_SOURCE_H_ #endif // FORTRAN_PARSER_SOURCE_H_

View File

@ -34,7 +34,7 @@ const Name &GetLastName(const AllocateObject &);
// wrapped in a struct to avoid prototypes. // wrapped in a struct to avoid prototypes.
struct UnwrapperHelper { struct UnwrapperHelper {
template<typename A, typename B> static const A *Unwrap(B *p) { template <typename A, typename B> static const A *Unwrap(B *p) {
if (p) { if (p) {
return Unwrap<A>(*p); return Unwrap<A>(*p);
} else { } else {
@ -42,17 +42,17 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename B, bool COPY> template <typename A, typename B, bool COPY>
static const A *Unwrap(const common::Indirection<B, COPY> &x) { static const A *Unwrap(const common::Indirection<B, COPY> &x) {
return Unwrap<A>(x.value()); return Unwrap<A>(x.value());
} }
template<typename A, typename... Bs> template <typename A, typename... Bs>
static const A *Unwrap(const std::variant<Bs...> &x) { static const A *Unwrap(const std::variant<Bs...> &x) {
return std::visit([](const auto &y) { return Unwrap<A>(y); }, x); return std::visit([](const auto &y) { return Unwrap<A>(y); }, x);
} }
template<typename A, typename B> template <typename A, typename B>
static const A *Unwrap(const std::optional<B> &o) { static const A *Unwrap(const std::optional<B> &o) {
if (o) { if (o) {
return Unwrap<A>(*o); return Unwrap<A>(*o);
@ -61,7 +61,7 @@ struct UnwrapperHelper {
} }
} }
template<typename A, typename B> static const A *Unwrap(B &x) { template <typename A, typename B> static const A *Unwrap(B &x) {
if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) { if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) {
return &x; return &x;
} else if constexpr (ConstraintTrait<B>) { } else if constexpr (ConstraintTrait<B>) {
@ -76,10 +76,10 @@ struct UnwrapperHelper {
} }
}; };
template<typename A, typename B> const A *Unwrap(const B &x) { template <typename A, typename B> const A *Unwrap(const B &x) {
return UnwrapperHelper::Unwrap<A>(x); return UnwrapperHelper::Unwrap<A>(x);
} }
template<typename A, typename B> A *Unwrap(B &x) { template <typename A, typename B> A *Unwrap(B &x) {
return const_cast<A *>(Unwrap<A, B>(const_cast<const B &>(x))); return const_cast<A *>(Unwrap<A, B>(const_cast<const B &>(x)));
} }
@ -87,5 +87,5 @@ template<typename A, typename B> A *Unwrap(B &x) {
const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &); const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &);
const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &); const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &);
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_TOOLS_H_ #endif // FORTRAN_PARSER_TOOLS_H_

View File

@ -22,7 +22,7 @@ namespace Fortran::evaluate {
struct GenericExprWrapper; struct GenericExprWrapper;
struct GenericAssignmentWrapper; struct GenericAssignmentWrapper;
class ProcedureRef; class ProcedureRef;
} } // namespace Fortran::evaluate
namespace Fortran::parser { namespace Fortran::parser {
@ -48,6 +48,6 @@ void Unparse(llvm::raw_ostream &out, const Program &program,
Encoding encoding = Encoding::UTF_8, bool capitalizeKeywords = true, Encoding encoding = Encoding::UTF_8, bool capitalizeKeywords = true,
bool backslashEscapes = true, preStatementType *preStatement = nullptr, bool backslashEscapes = true, preStatementType *preStatement = nullptr,
AnalyzedObjectsAsFortran * = nullptr); AnalyzedObjectsAsFortran * = nullptr);
} } // namespace Fortran::parser
#endif #endif

View File

@ -30,12 +30,12 @@ class CookedSource;
class ParsingLog; class ParsingLog;
class ParseState; class ParseState;
class Success {}; // for when one must return something that's present class Success {}; // for when one must return something that's present
class UserState { class UserState {
public: public:
UserState(const CookedSource &cooked, common::LanguageFeatureControl features) UserState(const CookedSource &cooked, common::LanguageFeatureControl features)
: cooked_{cooked}, features_{features} {} : cooked_{cooked}, features_{features} {}
const CookedSource &cooked() const { return cooked_; } const CookedSource &cooked() const { return cooked_; }
const common::LanguageFeatureControl &features() const { return features_; } const common::LanguageFeatureControl &features() const { return features_; }
@ -139,5 +139,5 @@ struct StructureComponents {
using resultType = DataComponentDefStmt; using resultType = DataComponentDefStmt;
static std::optional<DataComponentDefStmt> Parse(ParseState &); static std::optional<DataComponentDefStmt> Parse(ParseState &);
}; };
} } // namespace Fortran::parser
#endif // FORTRAN_PARSER_USER_STATE_H_ #endif // FORTRAN_PARSER_USER_STATE_H_

View File

@ -50,5 +50,5 @@ std::string AttrToString(Attr attr);
llvm::raw_ostream &operator<<(llvm::raw_ostream &o, Attr attr); llvm::raw_ostream &operator<<(llvm::raw_ostream &o, Attr attr);
llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const Attrs &attrs); llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const Attrs &attrs);
} } // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_ATTR_H_ #endif // FORTRAN_SEMANTICS_ATTR_H_

View File

@ -29,8 +29,8 @@ using namespace Fortran::parser::literals;
namespace Fortran::parser { namespace Fortran::parser {
struct SourceLocationFindingVisitor { struct SourceLocationFindingVisitor {
template<typename A> bool Pre(const A &) { return true; } template <typename A> bool Pre(const A &) { return true; }
template<typename A> void Post(const A &) {} template <typename A> void Post(const A &) {}
bool Pre(const Expr &x) { bool Pre(const Expr &x) {
source = x.source; source = x.source;
return false; return false;
@ -51,7 +51,7 @@ struct SourceLocationFindingVisitor {
source = x.source; source = x.source;
return false; return false;
} }
template<typename A> bool Pre(const UnlabeledStatement<A> &stmt) { template <typename A> bool Pre(const UnlabeledStatement<A> &stmt) {
source = stmt.source; source = stmt.source;
return false; return false;
} }
@ -60,12 +60,12 @@ struct SourceLocationFindingVisitor {
CharBlock source; CharBlock source;
}; };
template<typename A> CharBlock FindSourceLocation(const A &x) { template <typename A> CharBlock FindSourceLocation(const A &x) {
SourceLocationFindingVisitor visitor; SourceLocationFindingVisitor visitor;
Walk(x, visitor); Walk(x, visitor);
return visitor.source; return visitor.source;
} }
} } // namespace Fortran::parser
using namespace Fortran::parser::literals; using namespace Fortran::parser::literals;
@ -89,10 +89,10 @@ struct SetExprHelper {
} }
void Set(const parser::Expr &x) { Set(x.typedExpr); } void Set(const parser::Expr &x) { Set(x.typedExpr); }
void Set(const parser::Variable &x) { Set(x.typedExpr); } void Set(const parser::Variable &x) { Set(x.typedExpr); }
template<typename T> void Set(const common::Indirection<T> &x) { template <typename T> void Set(const common::Indirection<T> &x) {
Set(x.value()); Set(x.value());
} }
template<typename T> void Set(const T &x) { template <typename T> void Set(const T &x) {
if constexpr (ConstraintTrait<T>) { if constexpr (ConstraintTrait<T>) {
Set(x.thing); Set(x.thing);
} else if constexpr (WrapperTrait<T>) { } else if constexpr (WrapperTrait<T>) {
@ -103,11 +103,11 @@ struct SetExprHelper {
GenericExprWrapper expr_; GenericExprWrapper expr_;
}; };
template<typename T> void ResetExpr(const T &x) { template <typename T> void ResetExpr(const T &x) {
SetExprHelper{GenericExprWrapper{/* error indicator */}}.Set(x); SetExprHelper{GenericExprWrapper{/* error indicator */}}.Set(x);
} }
template<typename T> void SetExpr(const T &x, Expr<SomeType> &&expr) { template <typename T> void SetExpr(const T &x, Expr<SomeType> &&expr) {
SetExprHelper{GenericExprWrapper{std::move(expr)}}.Set(x); SetExprHelper{GenericExprWrapper{std::move(expr)}}.Set(x);
} }
@ -117,7 +117,7 @@ public:
explicit ExpressionAnalyzer(semantics::SemanticsContext &sc) : context_{sc} {} explicit ExpressionAnalyzer(semantics::SemanticsContext &sc) : context_{sc} {}
ExpressionAnalyzer(semantics::SemanticsContext &sc, FoldingContext &fc) ExpressionAnalyzer(semantics::SemanticsContext &sc, FoldingContext &fc)
: context_{sc}, foldingContext_{fc} {} : context_{sc}, foldingContext_{fc} {}
ExpressionAnalyzer(ExpressionAnalyzer &) = default; ExpressionAnalyzer(ExpressionAnalyzer &) = default;
semantics::SemanticsContext &context() const { return context_; } semantics::SemanticsContext &context() const { return context_; }
@ -128,11 +128,11 @@ public:
return foldingContext_.messages(); return foldingContext_.messages();
} }
template<typename... A> parser::Message *Say(A &&... args) { template <typename... A> parser::Message *Say(A &&... args) {
return GetContextualMessages().Say(std::forward<A>(args)...); return GetContextualMessages().Say(std::forward<A>(args)...);
} }
template<typename T, typename... A> template <typename T, typename... A>
parser::Message *SayAt(const T &parsed, A &&... args) { parser::Message *SayAt(const T &parsed, A &&... args) {
return Say(parser::FindSourceLocation(parsed), std::forward<A>(args)...); return Say(parser::FindSourceLocation(parsed), std::forward<A>(args)...);
} }
@ -156,10 +156,10 @@ public:
MaybeExpr Analyze(const parser::Variable &); MaybeExpr Analyze(const parser::Variable &);
MaybeExpr Analyze(const parser::Designator &); MaybeExpr Analyze(const parser::Designator &);
template<typename A> MaybeExpr Analyze(const common::Indirection<A> &x) { template <typename A> MaybeExpr Analyze(const common::Indirection<A> &x) {
return Analyze(x.value()); return Analyze(x.value());
} }
template<typename A> MaybeExpr Analyze(const std::optional<A> &x) { template <typename A> MaybeExpr Analyze(const std::optional<A> &x) {
if (x) { if (x) {
return Analyze(*x); return Analyze(*x);
} else { } else {
@ -168,7 +168,7 @@ public:
} }
// Implement constraint-checking wrappers from the Fortran grammar. // Implement constraint-checking wrappers from the Fortran grammar.
template<typename A> MaybeExpr Analyze(const parser::Scalar<A> &x) { template <typename A> MaybeExpr Analyze(const parser::Scalar<A> &x) {
auto result{Analyze(x.thing)}; auto result{Analyze(x.thing)};
if (result) { if (result) {
if (int rank{result->Rank()}; rank != 0) { if (int rank{result->Rank()}; rank != 0) {
@ -180,13 +180,13 @@ public:
} }
return result; return result;
} }
template<typename A> MaybeExpr Analyze(const parser::Constant<A> &x) { template <typename A> MaybeExpr Analyze(const parser::Constant<A> &x) {
auto restorer{ auto restorer{
GetFoldingContext().messages().SetLocation(FindSourceLocation(x))}; GetFoldingContext().messages().SetLocation(FindSourceLocation(x))};
auto result{Analyze(x.thing)}; auto result{Analyze(x.thing)};
if (result) { if (result) {
*result = Fold(std::move(*result)); *result = Fold(std::move(*result));
if (!IsConstantExpr(*result)) { // C886, C887, C713 if (!IsConstantExpr(*result)) { // C886, C887, C713
SayAt(x, "Must be a constant value"_err_en_US); SayAt(x, "Must be a constant value"_err_en_US);
ResetExpr(x); ResetExpr(x);
return std::nullopt; return std::nullopt;
@ -197,7 +197,7 @@ public:
} }
return result; return result;
} }
template<typename A> MaybeExpr Analyze(const parser::Integer<A> &x) { template <typename A> MaybeExpr Analyze(const parser::Integer<A> &x) {
auto result{Analyze(x.thing)}; auto result{Analyze(x.thing)};
if (!EnforceTypeConstraint( if (!EnforceTypeConstraint(
parser::FindSourceLocation(x), result, TypeCategory::Integer)) { parser::FindSourceLocation(x), result, TypeCategory::Integer)) {
@ -206,7 +206,7 @@ public:
} }
return result; return result;
} }
template<typename A> MaybeExpr Analyze(const parser::Logical<A> &x) { template <typename A> MaybeExpr Analyze(const parser::Logical<A> &x) {
auto result{Analyze(x.thing)}; auto result{Analyze(x.thing)};
if (!EnforceTypeConstraint( if (!EnforceTypeConstraint(
parser::FindSourceLocation(x), result, TypeCategory::Logical)) { parser::FindSourceLocation(x), result, TypeCategory::Logical)) {
@ -215,7 +215,7 @@ public:
} }
return result; return result;
} }
template<typename A> MaybeExpr Analyze(const parser::DefaultChar<A> &x) { template <typename A> MaybeExpr Analyze(const parser::DefaultChar<A> &x) {
auto result{Analyze(x.thing)}; auto result{Analyze(x.thing)};
if (!EnforceTypeConstraint(parser::FindSourceLocation(x), result, if (!EnforceTypeConstraint(parser::FindSourceLocation(x), result,
TypeCategory::Character, true /* default kind */)) { TypeCategory::Character, true /* default kind */)) {
@ -283,10 +283,10 @@ private:
MaybeExpr Analyze(const parser::Expr::EQV &); MaybeExpr Analyze(const parser::Expr::EQV &);
MaybeExpr Analyze(const parser::Expr::NEQV &); MaybeExpr Analyze(const parser::Expr::NEQV &);
MaybeExpr Analyze(const parser::Expr::DefinedBinary &); MaybeExpr Analyze(const parser::Expr::DefinedBinary &);
template<typename A> MaybeExpr Analyze(const A &x) { template <typename A> MaybeExpr Analyze(const A &x) {
return Analyze(x.u); // default case return Analyze(x.u); // default case
} }
template<typename... As> MaybeExpr Analyze(const std::variant<As...> &u) { template <typename... As> MaybeExpr Analyze(const std::variant<As...> &u) {
return std::visit( return std::visit(
[&](const auto &x) { [&](const auto &x) {
using Ty = std::decay_t<decltype(x)>; using Ty = std::decay_t<decltype(x)>;
@ -321,8 +321,8 @@ private:
// Analysis subroutines // Analysis subroutines
int AnalyzeKindParam( int AnalyzeKindParam(
const std::optional<parser::KindParam> &, int defaultKind); const std::optional<parser::KindParam> &, int defaultKind);
template<typename PARSED> MaybeExpr ExprOrVariable(const PARSED &); template <typename PARSED> MaybeExpr ExprOrVariable(const PARSED &);
template<typename PARSED> MaybeExpr IntLiteralConstant(const PARSED &); template <typename PARSED> MaybeExpr IntLiteralConstant(const PARSED &);
MaybeExpr AnalyzeString(std::string &&, int kind); MaybeExpr AnalyzeString(std::string &&, int kind);
std::optional<Expr<SubscriptInteger>> AsSubscript(MaybeExpr &&); std::optional<Expr<SubscriptInteger>> AsSubscript(MaybeExpr &&);
std::optional<Expr<SubscriptInteger>> TripletPart( std::optional<Expr<SubscriptInteger>> TripletPart(
@ -370,13 +370,13 @@ private:
MaybeExpr MakeFunctionRef( MaybeExpr MakeFunctionRef(
parser::CharBlock, ProcedureDesignator &&, ActualArguments &&); parser::CharBlock, ProcedureDesignator &&, ActualArguments &&);
MaybeExpr MakeFunctionRef(parser::CharBlock intrinsic, ActualArguments &&); MaybeExpr MakeFunctionRef(parser::CharBlock intrinsic, ActualArguments &&);
template<typename T> T Fold(T &&expr) { template <typename T> T Fold(T &&expr) {
return evaluate::Fold(foldingContext_, std::move(expr)); return evaluate::Fold(foldingContext_, std::move(expr));
} }
semantics::SemanticsContext &context_; semantics::SemanticsContext &context_;
FoldingContext &foldingContext_{context_.foldingContext()}; FoldingContext &foldingContext_{context_.foldingContext()};
std::map<parser::CharBlock, int> acImpliedDos_; // values are INTEGER kinds std::map<parser::CharBlock, int> acImpliedDos_; // values are INTEGER kinds
bool fatalErrors_{false}; bool fatalErrors_{false};
friend class ArgumentAnalyzer; friend class ArgumentAnalyzer;
}; };
@ -385,12 +385,12 @@ inline bool AreConformable(int leftRank, int rightRank) {
return leftRank == 0 || rightRank == 0 || leftRank == rightRank; return leftRank == 0 || rightRank == 0 || leftRank == rightRank;
} }
template<typename L, typename R> template <typename L, typename R>
bool AreConformable(const L &left, const R &right) { bool AreConformable(const L &left, const R &right) {
return AreConformable(left.Rank(), right.Rank()); return AreConformable(left.Rank(), right.Rank());
} }
template<typename L, typename R> template <typename L, typename R>
void ConformabilityCheck( void ConformabilityCheck(
parser::ContextualMessages &context, const L &left, const R &right) { parser::ContextualMessages &context, const L &left, const R &right) {
if (!AreConformable(left, right)) { if (!AreConformable(left, right)) {
@ -398,12 +398,12 @@ void ConformabilityCheck(
left.Rank(), right.Rank()); left.Rank(), right.Rank());
} }
} }
} // namespace Fortran::evaluate } // namespace Fortran::evaluate
namespace Fortran::semantics { namespace Fortran::semantics {
// Semantic analysis of one expression, variable, or designator. // Semantic analysis of one expression, variable, or designator.
template<typename A> template <typename A>
std::optional<evaluate::Expr<evaluate::SomeType>> AnalyzeExpr( std::optional<evaluate::Expr<evaluate::SomeType>> AnalyzeExpr(
SemanticsContext &context, const A &expr) { SemanticsContext &context, const A &expr) {
return evaluate::ExpressionAnalyzer{context}.Analyze(expr); return evaluate::ExpressionAnalyzer{context}.Analyze(expr);
@ -426,8 +426,8 @@ class ExprChecker {
public: public:
explicit ExprChecker(SemanticsContext &); explicit ExprChecker(SemanticsContext &);
template<typename A> bool Pre(const A &) { return true; } template <typename A> bool Pre(const A &) { return true; }
template<typename A> void Post(const A &) {} template <typename A> void Post(const A &) {}
bool Walk(const parser::Program &); bool Walk(const parser::Program &);
bool Pre(const parser::Expr &x) { bool Pre(const parser::Expr &x) {
@ -452,23 +452,23 @@ public:
} }
bool Pre(const parser::DataStmtConstant &); bool Pre(const parser::DataStmtConstant &);
template<typename A> bool Pre(const parser::Scalar<A> &x) { template <typename A> bool Pre(const parser::Scalar<A> &x) {
AnalyzeExpr(context_, x); AnalyzeExpr(context_, x);
return false; return false;
} }
template<typename A> bool Pre(const parser::Constant<A> &x) { template <typename A> bool Pre(const parser::Constant<A> &x) {
AnalyzeExpr(context_, x); AnalyzeExpr(context_, x);
return false; return false;
} }
template<typename A> bool Pre(const parser::Integer<A> &x) { template <typename A> bool Pre(const parser::Integer<A> &x) {
AnalyzeExpr(context_, x); AnalyzeExpr(context_, x);
return false; return false;
} }
template<typename A> bool Pre(const parser::Logical<A> &x) { template <typename A> bool Pre(const parser::Logical<A> &x) {
AnalyzeExpr(context_, x); AnalyzeExpr(context_, x);
return false; return false;
} }
template<typename A> bool Pre(const parser::DefaultChar<A> &x) { template <typename A> bool Pre(const parser::DefaultChar<A> &x) {
AnalyzeExpr(context_, x); AnalyzeExpr(context_, x);
return false; return false;
} }
@ -476,5 +476,5 @@ public:
private: private:
SemanticsContext &context_; SemanticsContext &context_;
}; };
} // namespace Fortran::semantics } // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_EXPRESSION_H_ #endif // FORTRAN_SEMANTICS_EXPRESSION_H_

View File

@ -39,13 +39,14 @@ class SemanticsContext;
struct EquivalenceObject { struct EquivalenceObject {
EquivalenceObject(Symbol &symbol, std::vector<ConstantSubscript> subscripts, EquivalenceObject(Symbol &symbol, std::vector<ConstantSubscript> subscripts,
std::optional<ConstantSubscript> substringStart) std::optional<ConstantSubscript> substringStart)
: symbol{symbol}, subscripts{subscripts}, substringStart{substringStart} {} : symbol{symbol}, subscripts{subscripts}, substringStart{substringStart} {
}
bool operator==(const EquivalenceObject &) const; bool operator==(const EquivalenceObject &) const;
bool operator<(const EquivalenceObject &) const; bool operator<(const EquivalenceObject &) const;
std::string AsFortran() const; std::string AsFortran() const;
Symbol &symbol; Symbol &symbol;
std::vector<ConstantSubscript> subscripts; // for array elem std::vector<ConstantSubscript> subscripts; // for array elem
std::optional<ConstantSubscript> substringStart; std::optional<ConstantSubscript> substringStart;
}; };
using EquivalenceSet = std::vector<EquivalenceObject>; using EquivalenceSet = std::vector<EquivalenceObject>;
@ -61,7 +62,7 @@ public:
// Create the Global scope -- the root of the scope tree // Create the Global scope -- the root of the scope tree
Scope() : Scope{*this, Kind::Global, nullptr} {} Scope() : Scope{*this, Kind::Global, nullptr} {}
Scope(Scope &parent, Kind kind, Symbol *symbol) Scope(Scope &parent, Kind kind, Symbol *symbol)
: parent_{parent}, kind_{kind}, symbol_{symbol} { : parent_{parent}, kind_{kind}, symbol_{symbol} {
if (symbol) { if (symbol) {
symbol->set_scope(this); symbol->set_scope(this);
} }
@ -81,7 +82,7 @@ public:
} }
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
bool IsGlobal() const { return kind_ == Kind::Global; } bool IsGlobal() const { return kind_ == Kind::Global; }
bool IsModule() const; // only module, not submodule bool IsModule() const; // only module, not submodule
bool IsSubmodule() const; bool IsSubmodule() const;
bool IsDerivedType() const { return kind_ == Kind::DerivedType; } bool IsDerivedType() const { return kind_ == Kind::DerivedType; }
bool IsParameterizedDerivedType() const; bool IsParameterizedDerivedType() const;
@ -127,13 +128,13 @@ public:
return try_emplace(name, attrs, UnknownDetails()); return try_emplace(name, attrs, UnknownDetails());
} }
/// Make a Symbol with provided details. /// Make a Symbol with provided details.
template<typename D> template <typename D>
common::IfNoLvalue<std::pair<iterator, bool>, D> try_emplace( common::IfNoLvalue<std::pair<iterator, bool>, D> try_emplace(
const SourceName &name, D &&details) { const SourceName &name, D &&details) {
return try_emplace(name, Attrs(), std::move(details)); return try_emplace(name, Attrs(), std::move(details));
} }
/// Make a Symbol with attrs and details /// Make a Symbol with attrs and details
template<typename D> template <typename D>
common::IfNoLvalue<std::pair<iterator, bool>, D> try_emplace( common::IfNoLvalue<std::pair<iterator, bool>, D> try_emplace(
const SourceName &name, Attrs attrs, D &&details) { const SourceName &name, Attrs attrs, D &&details) {
Symbol &symbol{MakeSymbol(name, attrs, std::move(details))}; Symbol &symbol{MakeSymbol(name, attrs, std::move(details))};
@ -153,7 +154,7 @@ public:
Symbol *FindCommonBlock(const SourceName &); Symbol *FindCommonBlock(const SourceName &);
/// Make a Symbol but don't add it to the scope. /// Make a Symbol but don't add it to the scope.
template<typename D> template <typename D>
common::IfNoLvalue<Symbol &, D> MakeSymbol( common::IfNoLvalue<Symbol &, D> MakeSymbol(
const SourceName &name, Attrs attrs, D &&details) { const SourceName &name, Attrs attrs, D &&details) {
return allSymbols.Make(*this, name, attrs, std::move(details)); return allSymbols.Make(*this, name, attrs, std::move(details));
@ -213,10 +214,10 @@ public:
void InstantiateDerivedTypes(SemanticsContext &); void InstantiateDerivedTypes(SemanticsContext &);
private: private:
Scope &parent_; // this is enclosing scope, not extended derived type base Scope &parent_; // this is enclosing scope, not extended derived type base
const Kind kind_; const Kind kind_;
parser::CharBlock sourceRange_; parser::CharBlock sourceRange_;
Symbol *const symbol_; // if not null, symbol_->scope() == this Symbol *const symbol_; // if not null, symbol_->scope() == this
std::list<Scope> children_; std::list<Scope> children_;
mapType symbols_; mapType symbols_;
mapType commonBlocks_; mapType commonBlocks_;
@ -227,7 +228,7 @@ private:
std::string chars_; std::string chars_;
std::optional<ImportKind> importKind_; std::optional<ImportKind> importKind_;
std::set<SourceName> importNames_; std::set<SourceName> importNames_;
DerivedTypeSpec *derivedTypeSpec_{nullptr}; // dTS->scope() == this DerivedTypeSpec *derivedTypeSpec_{nullptr}; // dTS->scope() == this
// When additional data members are added to Scope, remember to // When additional data members are added to Scope, remember to
// copy them, if appropriate, in InstantiateDerivedType(). // copy them, if appropriate, in InstantiateDerivedType().
@ -240,5 +241,5 @@ private:
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Scope &); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Scope &);
}; };
} } // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_SCOPE_H_ #endif // FORTRAN_SEMANTICS_SCOPE_H_

View File

@ -43,7 +43,7 @@ struct SelectRankConstruct;
struct SelectTypeConstruct; struct SelectTypeConstruct;
struct Variable; struct Variable;
struct WhereConstruct; struct WhereConstruct;
} } // namespace Fortran::parser
namespace Fortran::semantics { namespace Fortran::semantics {
@ -133,18 +133,18 @@ public:
bool HasError(const parser::Name &); bool HasError(const parser::Name &);
void SetError(Symbol &, bool = true); void SetError(Symbol &, bool = true);
template<typename... A> parser::Message &Say(A &&... args) { template <typename... A> parser::Message &Say(A &&... args) {
CHECK(location_); CHECK(location_);
return messages_.Say(*location_, std::forward<A>(args)...); return messages_.Say(*location_, std::forward<A>(args)...);
} }
template<typename... A> template <typename... A>
parser::Message &Say(parser::CharBlock at, A &&... args) { parser::Message &Say(parser::CharBlock at, A &&... args) {
return messages_.Say(at, std::forward<A>(args)...); return messages_.Say(at, std::forward<A>(args)...);
} }
parser::Message &Say(parser::Message &&msg) { parser::Message &Say(parser::Message &&msg) {
return messages_.Say(std::move(msg)); return messages_.Say(std::move(msg));
} }
template<typename... A> template <typename... A>
void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at, void SayWithDecl(const Symbol &symbol, const parser::CharBlock &at,
parser::MessageFixedText &&msg, A &&... args) { parser::MessageFixedText &&msg, A &&... args) {
auto &message{Say(at, std::move(msg), args...)}; auto &message{Say(at, std::move(msg), args...)};
@ -155,7 +155,7 @@ public:
Scope &FindScope(parser::CharBlock); Scope &FindScope(parser::CharBlock);
const ConstructStack &constructStack() const { return constructStack_; } const ConstructStack &constructStack() const { return constructStack_; }
template<typename N> void PushConstruct(const N &node) { template <typename N> void PushConstruct(const N &node) {
constructStack_.emplace_back(&node); constructStack_.emplace_back(&node);
} }
void PopConstruct(); void PopConstruct();
@ -202,7 +202,7 @@ class Semantics {
public: public:
explicit Semantics(SemanticsContext &context, parser::Program &program, explicit Semantics(SemanticsContext &context, parser::Program &program,
parser::CookedSource &cooked, bool debugModuleWriter = false) parser::CookedSource &cooked, bool debugModuleWriter = false)
: context_{context}, program_{program}, cooked_{cooked} { : context_{context}, program_{program}, cooked_{cooked} {
context.set_debugModuleWriter(debugModuleWriter); context.set_debugModuleWriter(debugModuleWriter);
context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()}); context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()});
} }
@ -225,8 +225,8 @@ private:
// Base class for semantics checkers. // Base class for semantics checkers.
struct BaseChecker { struct BaseChecker {
template<typename N> void Enter(const N &) {} template <typename N> void Enter(const N &) {}
template<typename N> void Leave(const N &) {} template <typename N> void Leave(const N &) {}
}; };
} } // namespace Fortran::semantics
#endif #endif

View File

@ -42,8 +42,8 @@ public:
ModuleDetails(bool isSubmodule = false) : isSubmodule_{isSubmodule} {} ModuleDetails(bool isSubmodule = false) : isSubmodule_{isSubmodule} {}
bool isSubmodule() const { return isSubmodule_; } bool isSubmodule() const { return isSubmodule_; }
const Scope *scope() const { return scope_; } const Scope *scope() const { return scope_; }
const Scope *ancestor() const; // for submodule; nullptr for module const Scope *ancestor() const; // for submodule; nullptr for module
const Scope *parent() const; // for submodule; nullptr for module const Scope *parent() const; // for submodule; nullptr for module
void set_scope(const Scope *); void set_scope(const Scope *);
private: private:
@ -81,11 +81,11 @@ public:
void set_stmtFunction(SomeExpr &&expr) { stmtFunction_ = std::move(expr); } void set_stmtFunction(SomeExpr &&expr) { stmtFunction_ = std::move(expr); }
private: private:
bool isInterface_{false}; // true if this represents an interface-body bool isInterface_{false}; // true if this represents an interface-body
MaybeExpr bindName_; MaybeExpr bindName_;
std::vector<Symbol *> dummyArgs_; // nullptr -> alternate return indicator std::vector<Symbol *> dummyArgs_; // nullptr -> alternate return indicator
Symbol *result_{nullptr}; Symbol *result_{nullptr};
Scope *entryScope_{nullptr}; // if ENTRY, points to subprogram's scope Scope *entryScope_{nullptr}; // if ENTRY, points to subprogram's scope
MaybeExpr stmtFunction_; MaybeExpr stmtFunction_;
friend llvm::raw_ostream &operator<<( friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const SubprogramDetails &); llvm::raw_ostream &, const SubprogramDetails &);
@ -102,7 +102,7 @@ ENUM_CLASS(SubprogramKind, Module, Internal)
class SubprogramNameDetails { class SubprogramNameDetails {
public: public:
SubprogramNameDetails(SubprogramKind kind, ProgramTree &node) SubprogramNameDetails(SubprogramKind kind, ProgramTree &node)
: kind_{kind}, node_{node} {} : kind_{kind}, node_{node} {}
SubprogramNameDetails() = delete; SubprogramNameDetails() = delete;
SubprogramKind kind() const { return kind_; } SubprogramKind kind() const { return kind_; }
ProgramTree &node() const { return *node_; } ProgramTree &node() const { return *node_; }
@ -186,7 +186,7 @@ private:
bool initWasValidated_{false}; bool initWasValidated_{false};
ArraySpec shape_; ArraySpec shape_;
ArraySpec coshape_; ArraySpec coshape_;
const Symbol *commonBlock_{nullptr}; // common block this object is in const Symbol *commonBlock_{nullptr}; // common block this object is in
friend llvm::raw_ostream &operator<<( friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const ObjectEntityDetails &); llvm::raw_ostream &, const ObjectEntityDetails &);
}; };
@ -282,7 +282,7 @@ public:
const Symbol &symbol() const { return symbol_; } const Symbol &symbol() const { return symbol_; }
private: private:
SymbolRef symbol_; // procedure bound to; may be forward SymbolRef symbol_; // procedure bound to; may be forward
}; };
class NamelistDetails { class NamelistDetails {
@ -309,7 +309,7 @@ private:
MaybeExpr bindName_; MaybeExpr bindName_;
}; };
class FinalProcDetails {}; // TODO class FinalProcDetails {}; // TODO
class MiscDetails { class MiscDetails {
public: public:
@ -346,7 +346,7 @@ private:
class UseDetails { class UseDetails {
public: public:
UseDetails(const SourceName &location, const Symbol &symbol) UseDetails(const SourceName &location, const Symbol &symbol)
: location_{location}, symbol_{symbol} {} : location_{location}, symbol_{symbol} {}
const SourceName &location() const { return location_; } const SourceName &location() const { return location_; }
const Symbol &symbol() const { return symbol_; } const Symbol &symbol() const { return symbol_; }
const Symbol &module() const; const Symbol &module() const;
@ -383,10 +383,10 @@ private:
// defined assignment, intrinsic operator, or defined I/O. // defined assignment, intrinsic operator, or defined I/O.
struct GenericKind { struct GenericKind {
ENUM_CLASS(OtherKind, Name, DefinedOp, Assignment, Concat) ENUM_CLASS(OtherKind, Name, DefinedOp, Assignment, Concat)
ENUM_CLASS(DefinedIo, // defined io ENUM_CLASS(DefinedIo, // defined io
ReadFormatted, ReadUnformatted, WriteFormatted, WriteUnformatted) ReadFormatted, ReadUnformatted, WriteFormatted, WriteUnformatted)
GenericKind() : u{OtherKind::Name} {} GenericKind() : u{OtherKind::Name} {}
template<typename T> GenericKind(const T &x) { u = x; } template <typename T> GenericKind(const T &x) { u = x; }
bool IsName() const { return Is(OtherKind::Name); } bool IsName() const { return Is(OtherKind::Name); }
bool IsAssignment() const { return Is(OtherKind::Assignment); } bool IsAssignment() const { return Is(OtherKind::Assignment); }
bool IsDefinedOperator() const { return Is(OtherKind::DefinedOp); } bool IsDefinedOperator() const { return Is(OtherKind::DefinedOp); }
@ -398,7 +398,9 @@ struct GenericKind {
u; u;
private: private:
template<typename T> bool Has() const { return std::holds_alternative<T>(u); } template <typename T> bool Has() const {
return std::holds_alternative<T>(u);
}
bool Is(OtherKind) const; bool Is(OtherKind) const;
}; };
@ -463,17 +465,17 @@ std::string DetailsToString(const Details &);
class Symbol { class Symbol {
public: public:
ENUM_CLASS(Flag, ENUM_CLASS(Flag,
Error, // an error has been reported on this symbol Error, // an error has been reported on this symbol
Function, // symbol is a function Function, // symbol is a function
Subroutine, // symbol is a subroutine Subroutine, // symbol is a subroutine
Implicit, // symbol is implicitly typed Implicit, // symbol is implicitly typed
ModFile, // symbol came from .mod file ModFile, // symbol came from .mod file
ParentComp, // symbol is the "parent component" of an extended type ParentComp, // symbol is the "parent component" of an extended type
CrayPointer, CrayPointee, CrayPointer, CrayPointee,
LocalityLocal, // named in LOCAL locality-spec LocalityLocal, // named in LOCAL locality-spec
LocalityLocalInit, // named in LOCAL_INIT locality-spec LocalityLocalInit, // named in LOCAL_INIT locality-spec
LocalityShared, // named in SHARED locality-spec LocalityShared, // named in SHARED locality-spec
InDataStmt, // initialized in a DATA statement InDataStmt, // initialized in a DATA statement
// OpenMP data-sharing attribute // OpenMP data-sharing attribute
OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate, OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
@ -501,21 +503,21 @@ public:
void ReplaceName(const SourceName &); void ReplaceName(const SourceName &);
// Does symbol have this type of details? // Does symbol have this type of details?
template<typename D> bool has() const { template <typename D> bool has() const {
return std::holds_alternative<D>(details_); return std::holds_alternative<D>(details_);
} }
// Return a non-owning pointer to details if it is type D, else nullptr. // Return a non-owning pointer to details if it is type D, else nullptr.
template<typename D> D *detailsIf() { return std::get_if<D>(&details_); } template <typename D> D *detailsIf() { return std::get_if<D>(&details_); }
template<typename D> const D *detailsIf() const { template <typename D> const D *detailsIf() const {
return std::get_if<D>(&details_); return std::get_if<D>(&details_);
} }
// Return a reference to the details which must be of type D. // Return a reference to the details which must be of type D.
template<typename D> D &get() { template <typename D> D &get() {
return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>()); return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>());
} }
template<typename D> const D &get() const { template <typename D> const D &get() const {
const auto *p{detailsIf<D>()}; const auto *p{detailsIf<D>()};
CHECK(p); CHECK(p);
return *p; return *p;
@ -582,24 +584,24 @@ public:
bool IsSubprogram() const; bool IsSubprogram() const;
bool IsFromModFile() const; bool IsFromModFile() const;
bool HasExplicitInterface() const { bool HasExplicitInterface() const {
return std::visit( return std::visit(common::visitors{
common::visitors{ [](const SubprogramDetails &) { return true; },
[](const SubprogramDetails &) { return true; }, [](const SubprogramNameDetails &) { return true; },
[](const SubprogramNameDetails &) { return true; }, [&](const ProcEntityDetails &x) {
[&](const ProcEntityDetails &x) { return attrs_.test(Attr::INTRINSIC) ||
return attrs_.test(Attr::INTRINSIC) || x.HasExplicitInterface(); x.HasExplicitInterface();
}, },
[](const ProcBindingDetails &x) { [](const ProcBindingDetails &x) {
return x.symbol().HasExplicitInterface(); return x.symbol().HasExplicitInterface();
}, },
[](const UseDetails &x) { [](const UseDetails &x) {
return x.symbol().HasExplicitInterface(); return x.symbol().HasExplicitInterface();
}, },
[](const HostAssocDetails &x) { [](const HostAssocDetails &x) {
return x.symbol().HasExplicitInterface(); return x.symbol().HasExplicitInterface();
}, },
[](const auto &) { return false; }, [](const auto &) { return false; },
}, },
details_); details_);
} }
@ -668,7 +670,7 @@ private:
Scope *scope_{nullptr}; Scope *scope_{nullptr};
Details details_; Details details_;
Symbol() {} // only created in class Symbols Symbol() {} // only created in class Symbols
const std::string GetDetailsName() const; const std::string GetDetailsName() const;
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Symbol &);
friend llvm::raw_ostream &DumpForUnparse( friend llvm::raw_ostream &DumpForUnparse(
@ -679,8 +681,8 @@ private:
// can be overridden. // can be overridden.
const Symbol *GetParentComponent(const Scope * = nullptr) const; const Symbol *GetParentComponent(const Scope * = nullptr) const;
template<std::size_t> friend class Symbols; template <std::size_t> friend class Symbols;
template<class, std::size_t> friend struct std::array; template <class, std::size_t> friend struct std::array;
}; };
llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag); llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag);
@ -688,7 +690,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, Symbol::Flag);
// Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated. // Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated.
// Make() returns a reference to the next available one. They are never // Make() returns a reference to the next available one. They are never
// deleted. // deleted.
template<std::size_t BLOCK_SIZE> class Symbols { template <std::size_t BLOCK_SIZE> class Symbols {
public: public:
Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs, Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs,
Details &&details) { Details &&details) {
@ -713,7 +715,7 @@ private:
} }
Symbol &result = (*currBlock_)[nextIndex_]; Symbol &result = (*currBlock_)[nextIndex_];
if (++nextIndex_ >= BLOCK_SIZE) { if (++nextIndex_ >= BLOCK_SIZE) {
nextIndex_ = 0; // allocate a new block next time nextIndex_ = 0; // allocate a new block next time
} }
return result; return result;
} }
@ -733,5 +735,5 @@ inline bool ProcEntityDetails::HasExplicitInterface() const {
inline bool operator<(SymbolRef x, SymbolRef y) { return *x < *y; } inline bool operator<(SymbolRef x, SymbolRef y) { return *x < *y; }
using SymbolSet = std::set<SymbolRef>; using SymbolSet = std::set<SymbolRef>;
} } // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_SYMBOL_H_ #endif // FORTRAN_SEMANTICS_SYMBOL_H_

View File

@ -90,8 +90,8 @@ bool IsPureProcedure(const Scope &);
bool IsBindCProcedure(const Symbol &); bool IsBindCProcedure(const Symbol &);
bool IsBindCProcedure(const Scope &); bool IsBindCProcedure(const Scope &);
bool IsProcedure(const Symbol &); bool IsProcedure(const Symbol &);
bool IsProcName(const Symbol &symbol); // proc-name bool IsProcName(const Symbol &symbol); // proc-name
bool IsVariableName(const Symbol &symbol); // variable-name bool IsVariableName(const Symbol &symbol); // variable-name
bool IsProcedurePointer(const Symbol &); bool IsProcedurePointer(const Symbol &);
bool IsFunctionResult(const Symbol &); bool IsFunctionResult(const Symbol &);
bool IsFunctionResultWithSameNameAsFunction(const Symbol &); bool IsFunctionResultWithSameNameAsFunction(const Symbol &);
@ -211,12 +211,12 @@ const Symbol *FindSeparateModuleSubprogramInterface(const Symbol *);
// diagnostic purposes if so. // diagnostic purposes if so.
const Symbol *FindExternallyVisibleObject(const Symbol &, const Scope &); const Symbol *FindExternallyVisibleObject(const Symbol &, const Scope &);
template<typename A> template <typename A>
const Symbol *FindExternallyVisibleObject(const A &, const Scope &) { const Symbol *FindExternallyVisibleObject(const A &, const Scope &) {
return nullptr; // default base case return nullptr; // default base case
} }
template<typename T> template <typename T>
const Symbol *FindExternallyVisibleObject( const Symbol *FindExternallyVisibleObject(
const evaluate::Designator<T> &designator, const Scope &scope) { const evaluate::Designator<T> &designator, const Scope &scope) {
if (const Symbol * symbol{designator.GetBaseObject().symbol()}) { if (const Symbol * symbol{designator.GetBaseObject().symbol()}) {
@ -229,7 +229,7 @@ const Symbol *FindExternallyVisibleObject(
} }
} }
template<typename T> template <typename T>
const Symbol *FindExternallyVisibleObject( const Symbol *FindExternallyVisibleObject(
const evaluate::Expr<T> &expr, const Scope &scope) { const evaluate::Expr<T> &expr, const Scope &scope) {
return std::visit( return std::visit(
@ -247,13 +247,13 @@ bool ExprTypeKindIsDefault(
struct GetExprHelper { struct GetExprHelper {
const SomeExpr *Get(const parser::Expr &); const SomeExpr *Get(const parser::Expr &);
const SomeExpr *Get(const parser::Variable &); const SomeExpr *Get(const parser::Variable &);
template<typename T> const SomeExpr *Get(const common::Indirection<T> &x) { template <typename T> const SomeExpr *Get(const common::Indirection<T> &x) {
return Get(x.value()); return Get(x.value());
} }
template<typename T> const SomeExpr *Get(const std::optional<T> &x) { template <typename T> const SomeExpr *Get(const std::optional<T> &x) {
return x ? Get(*x) : nullptr; return x ? Get(*x) : nullptr;
} }
template<typename T> const SomeExpr *Get(const T &x) { template <typename T> const SomeExpr *Get(const T &x) {
if constexpr (ConstraintTrait<T>) { if constexpr (ConstraintTrait<T>) {
return Get(x.thing); return Get(x.thing);
} else if constexpr (WrapperTrait<T>) { } else if constexpr (WrapperTrait<T>) {
@ -264,7 +264,7 @@ struct GetExprHelper {
} }
}; };
template<typename T> const SomeExpr *GetExpr(const T &x) { template <typename T> const SomeExpr *GetExpr(const T &x) {
return GetExprHelper{}.Get(x); return GetExprHelper{}.Get(x);
} }
@ -272,7 +272,7 @@ const evaluate::Assignment *GetAssignment(const parser::AssignmentStmt &);
const evaluate::Assignment *GetAssignment( const evaluate::Assignment *GetAssignment(
const parser::PointerAssignmentStmt &); const parser::PointerAssignmentStmt &);
template<typename T> std::optional<std::int64_t> GetIntValue(const T &x) { template <typename T> std::optional<std::int64_t> GetIntValue(const T &x) {
if (const auto *expr{GetExpr(x)}) { if (const auto *expr{GetExpr(x)}) {
return evaluate::ToInt64(*expr); return evaluate::ToInt64(*expr);
} else { } else {
@ -280,7 +280,7 @@ template<typename T> std::optional<std::int64_t> GetIntValue(const T &x) {
} }
} }
template<typename T> bool IsZero(const T &expr) { template <typename T> bool IsZero(const T &expr) {
auto value{GetIntValue(expr)}; auto value{GetIntValue(expr)};
return value && *value == 0; return value && *value == 0;
} }
@ -347,7 +347,7 @@ template<typename T> bool IsZero(const T &expr) {
ENUM_CLASS(ComponentKind, Ordered, Direct, Ultimate, Potential, Scope) ENUM_CLASS(ComponentKind, Ordered, Direct, Ultimate, Potential, Scope)
template<ComponentKind componentKind> class ComponentIterator { template <ComponentKind componentKind> class ComponentIterator {
public: public:
ComponentIterator(const DerivedTypeSpec &derived) : derived_{derived} {} ComponentIterator(const DerivedTypeSpec &derived) : derived_{derived} {}
class const_iterator { class const_iterator {
@ -404,7 +404,7 @@ public:
class ComponentPathNode { class ComponentPathNode {
public: public:
explicit ComponentPathNode(const DerivedTypeSpec &derived) explicit ComponentPathNode(const DerivedTypeSpec &derived)
: derived_{derived} { : derived_{derived} {
if constexpr (componentKind == ComponentKind::Scope) { if constexpr (componentKind == ComponentKind::Scope) {
const Scope &scope{DEREF(derived.scope())}; const Scope &scope{DEREF(derived.scope())};
nameIterator_ = scope.cbegin(); nameIterator_ = scope.cbegin();
@ -436,7 +436,7 @@ public:
common::Reference<const DerivedTypeSpec> derived_; common::Reference<const DerivedTypeSpec> derived_;
name_iterator nameEnd_; name_iterator nameEnd_;
name_iterator nameIterator_; name_iterator nameIterator_;
const Symbol *component_{nullptr}; // until Increment() const Symbol *component_{nullptr}; // until Increment()
bool visited_{false}; bool visited_{false};
bool descended_{false}; bool descended_{false};
}; };
@ -495,16 +495,16 @@ class LabelEnforce {
public: public:
LabelEnforce(SemanticsContext &context, std::set<parser::Label> &&labels, LabelEnforce(SemanticsContext &context, std::set<parser::Label> &&labels,
parser::CharBlock constructSourcePosition, const char *construct) parser::CharBlock constructSourcePosition, const char *construct)
: context_{context}, labels_{labels}, : context_{context}, labels_{labels},
constructSourcePosition_{constructSourcePosition}, construct_{construct} { constructSourcePosition_{constructSourcePosition}, construct_{
} construct} {}
template<typename T> bool Pre(const T &) { return true; } template <typename T> bool Pre(const T &) { return true; }
template<typename T> bool Pre(const parser::Statement<T> &statement) { template <typename T> bool Pre(const parser::Statement<T> &statement) {
currentStatementSourcePosition_ = statement.source; currentStatementSourcePosition_ = statement.source;
return true; return true;
} }
template<typename T> void Post(const T &) {} template <typename T> void Post(const T &) {}
void Post(const parser::GotoStmt &gotoStmt); void Post(const parser::GotoStmt &gotoStmt);
void Post(const parser::ComputedGotoStmt &computedGotoStmt); void Post(const parser::ComputedGotoStmt &computedGotoStmt);
@ -529,5 +529,5 @@ private:
parser::CharBlock stmtLocation, parser::MessageFormattedText &&message, parser::CharBlock stmtLocation, parser::MessageFormattedText &&message,
parser::CharBlock constructLocation); parser::CharBlock constructLocation);
}; };
} } // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_TOOLS_H_ #endif // FORTRAN_SEMANTICS_TOOLS_H_

View File

@ -72,7 +72,7 @@ private:
enum class Category { Explicit, Deferred, Assumed }; enum class Category { Explicit, Deferred, Assumed };
Bound(Category category) : category_{category} {} Bound(Category category) : category_{category} {}
Bound(Category category, MaybeSubscriptIntExpr &&expr) Bound(Category category, MaybeSubscriptIntExpr &&expr)
: category_{category}, expr_{std::move(expr)} {} : category_{category}, expr_{std::move(expr)} {}
Category category_{Category::Explicit}; Category category_{Category::Explicit};
MaybeSubscriptIntExpr expr_; MaybeSubscriptIntExpr expr_;
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Bound &); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Bound &);
@ -107,7 +107,7 @@ public:
private: private:
enum class Category { Explicit, Deferred, Assumed }; enum class Category { Explicit, Deferred, Assumed };
ParamValue(Category category, common::TypeParamAttr attr) ParamValue(Category category, common::TypeParamAttr attr)
: category_{category}, attr_{attr} {} : category_{category}, attr_{attr} {}
Category category_{Category::Explicit}; Category category_{Category::Explicit};
common::TypeParamAttr attr_{common::TypeParamAttr::Kind}; common::TypeParamAttr attr_{common::TypeParamAttr::Kind};
MaybeIntExpr expr_; MaybeIntExpr expr_;
@ -130,13 +130,14 @@ protected:
private: private:
TypeCategory category_; TypeCategory category_;
KindExpr kind_; KindExpr kind_;
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const IntrinsicTypeSpec &x); friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &os, const IntrinsicTypeSpec &x);
}; };
class NumericTypeSpec : public IntrinsicTypeSpec { class NumericTypeSpec : public IntrinsicTypeSpec {
public: public:
NumericTypeSpec(TypeCategory category, KindExpr &&kind) NumericTypeSpec(TypeCategory category, KindExpr &&kind)
: IntrinsicTypeSpec(category, std::move(kind)) { : IntrinsicTypeSpec(category, std::move(kind)) {
CHECK(common::IsNumericTypeCategory(category)); CHECK(common::IsNumericTypeCategory(category));
} }
}; };
@ -144,20 +145,21 @@ public:
class LogicalTypeSpec : public IntrinsicTypeSpec { class LogicalTypeSpec : public IntrinsicTypeSpec {
public: public:
explicit LogicalTypeSpec(KindExpr &&kind) explicit LogicalTypeSpec(KindExpr &&kind)
: IntrinsicTypeSpec(TypeCategory::Logical, std::move(kind)) {} : IntrinsicTypeSpec(TypeCategory::Logical, std::move(kind)) {}
}; };
class CharacterTypeSpec : public IntrinsicTypeSpec { class CharacterTypeSpec : public IntrinsicTypeSpec {
public: public:
CharacterTypeSpec(ParamValue &&length, KindExpr &&kind) CharacterTypeSpec(ParamValue &&length, KindExpr &&kind)
: IntrinsicTypeSpec(TypeCategory::Character, std::move(kind)), : IntrinsicTypeSpec(TypeCategory::Character, std::move(kind)),
length_{std::move(length)} {} length_{std::move(length)} {}
const ParamValue &length() const { return length_; } const ParamValue &length() const { return length_; }
std::string AsFortran() const; std::string AsFortran() const;
private: private:
ParamValue length_; ParamValue length_;
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const CharacterTypeSpec &x); friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &os, const CharacterTypeSpec &x);
}; };
class ShapeSpec { class ShapeSpec {
@ -224,7 +226,7 @@ struct ArraySpec : public std::vector<ShapeSpec> {
private: private:
// Check non-empty and predicate is true for each element. // Check non-empty and predicate is true for each element.
template<typename P> bool CheckAll(P predicate) const { template <typename P> bool CheckAll(P predicate) const {
return !empty() && std::all_of(begin(), end(), predicate); return !empty() && std::all_of(begin(), end(), predicate);
} }
}; };
@ -287,13 +289,14 @@ public:
private: private:
SourceName name_; SourceName name_;
const Symbol &typeSymbol_; const Symbol &typeSymbol_;
const Scope *scope_{nullptr}; // same as typeSymbol_.scope() unless PDT const Scope *scope_{nullptr}; // same as typeSymbol_.scope() unless PDT
bool cooked_{false}; bool cooked_{false};
bool evaluated_{false}; bool evaluated_{false};
bool instantiated_{false}; bool instantiated_{false};
RawParameters rawParameters_; RawParameters rawParameters_;
ParameterMapType parameters_; ParameterMapType parameters_;
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const DerivedTypeSpec &); friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const DerivedTypeSpec &);
}; };
class DeclTypeSpec { class DeclTypeSpec {
@ -351,18 +354,24 @@ public:
IntrinsicTypeSpec *AsIntrinsic(); IntrinsicTypeSpec *AsIntrinsic();
const IntrinsicTypeSpec *AsIntrinsic() const { const IntrinsicTypeSpec *AsIntrinsic() const {
switch (category_) { switch (category_) {
case Numeric: return &std::get<NumericTypeSpec>(typeSpec_); case Numeric:
case Logical: return &std::get<LogicalTypeSpec>(typeSpec_); return &std::get<NumericTypeSpec>(typeSpec_);
case Character: return &std::get<CharacterTypeSpec>(typeSpec_); case Logical:
default: return nullptr; return &std::get<LogicalTypeSpec>(typeSpec_);
case Character:
return &std::get<CharacterTypeSpec>(typeSpec_);
default:
return nullptr;
} }
} }
const DerivedTypeSpec *AsDerived() const { const DerivedTypeSpec *AsDerived() const {
switch (category_) { switch (category_) {
case TypeDerived: case TypeDerived:
case ClassDerived: return &std::get<DerivedTypeSpec>(typeSpec_); case ClassDerived:
default: return nullptr; return &std::get<DerivedTypeSpec>(typeSpec_);
default:
return nullptr;
} }
} }
@ -390,5 +399,5 @@ private:
const Symbol *symbol_{nullptr}; const Symbol *symbol_{nullptr};
const DeclTypeSpec *type_{nullptr}; const DeclTypeSpec *type_{nullptr};
}; };
} } // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_TYPE_H_ #endif // FORTRAN_SEMANTICS_TYPE_H_

View File

@ -25,4 +25,4 @@ void UnparseWithSymbols(llvm::raw_ostream &, const parser::Program &,
parser::Encoding encoding = parser::Encoding::UTF_8); parser::Encoding encoding = parser::Encoding::UTF_8);
} }
#endif // FORTRAN_SEMANTICS_UNPARSE_WITH_SYMBOLS_H_ #endif // FORTRAN_SEMANTICS_UNPARSE_WITH_SYMBOLS_H_

View File

@ -22,15 +22,22 @@ std::vector<const char *> LanguageFeatureControl::GetNames(
if (IsEnabled(LanguageFeature::LogicalAbbreviations)) { if (IsEnabled(LanguageFeature::LogicalAbbreviations)) {
switch (opr) { switch (opr) {
SWITCH_COVERS_ALL_CASES SWITCH_COVERS_ALL_CASES
case LogicalOperator::And: result.push_back(".a."); break; case LogicalOperator::And:
case LogicalOperator::Or: result.push_back(".o."); break; result.push_back(".a.");
case LogicalOperator::Not: result.push_back(".n."); break; break;
case LogicalOperator::Or:
result.push_back(".o.");
break;
case LogicalOperator::Not:
result.push_back(".n.");
break;
case LogicalOperator::Neqv: case LogicalOperator::Neqv:
if (IsEnabled(LanguageFeature::XOROperator)) { if (IsEnabled(LanguageFeature::XOROperator)) {
result.push_back(".x."); result.push_back(".x.");
} }
break; break;
case LogicalOperator::Eqv: break; case LogicalOperator::Eqv:
break;
} }
} }
return result; return result;
@ -40,11 +47,16 @@ std::vector<const char *> LanguageFeatureControl::GetNames(
RelationalOperator opr) const { RelationalOperator opr) const {
switch (opr) { switch (opr) {
SWITCH_COVERS_ALL_CASES SWITCH_COVERS_ALL_CASES
case RelationalOperator::LT: return {".lt.", "<"}; case RelationalOperator::LT:
case RelationalOperator::LE: return {".le.", "<="}; return {".lt.", "<"};
case RelationalOperator::EQ: return {".eq.", "=="}; case RelationalOperator::LE:
case RelationalOperator::GE: return {".ge.", ">="}; return {".le.", "<="};
case RelationalOperator::GT: return {".gt.", ">"}; case RelationalOperator::EQ:
return {".eq.", "=="};
case RelationalOperator::GE:
return {".ge.", ">="};
case RelationalOperator::GT:
return {".gt.", ">"};
case RelationalOperator::NE: case RelationalOperator::NE:
if (IsEnabled(LanguageFeature::AlternativeNE)) { if (IsEnabled(LanguageFeature::AlternativeNE)) {
return {".ne.", "/=", "<>"}; return {".ne.", "/=", "<>"};
@ -54,4 +66,4 @@ std::vector<const char *> LanguageFeatureControl::GetNames(
} }
} }
} } // namespace Fortran::common

View File

@ -13,35 +13,51 @@ namespace Fortran::common {
const char *AsFortran(NumericOperator opr) { const char *AsFortran(NumericOperator opr) {
switch (opr) { switch (opr) {
SWITCH_COVERS_ALL_CASES SWITCH_COVERS_ALL_CASES
case NumericOperator::Power: return "**"; case NumericOperator::Power:
case NumericOperator::Multiply: return "*"; return "**";
case NumericOperator::Divide: return "/"; case NumericOperator::Multiply:
case NumericOperator::Add: return "+"; return "*";
case NumericOperator::Subtract: return "-"; case NumericOperator::Divide:
return "/";
case NumericOperator::Add:
return "+";
case NumericOperator::Subtract:
return "-";
} }
} }
const char *AsFortran(LogicalOperator opr) { const char *AsFortran(LogicalOperator opr) {
switch (opr) { switch (opr) {
SWITCH_COVERS_ALL_CASES SWITCH_COVERS_ALL_CASES
case LogicalOperator::And: return ".and."; case LogicalOperator::And:
case LogicalOperator::Or: return ".or."; return ".and.";
case LogicalOperator::Eqv: return ".eqv."; case LogicalOperator::Or:
case LogicalOperator::Neqv: return ".neqv."; return ".or.";
case LogicalOperator::Not: return ".not."; case LogicalOperator::Eqv:
return ".eqv.";
case LogicalOperator::Neqv:
return ".neqv.";
case LogicalOperator::Not:
return ".not.";
} }
} }
const char *AsFortran(RelationalOperator opr) { const char *AsFortran(RelationalOperator opr) {
switch (opr) { switch (opr) {
SWITCH_COVERS_ALL_CASES SWITCH_COVERS_ALL_CASES
case RelationalOperator::LT: return "<"; case RelationalOperator::LT:
case RelationalOperator::LE: return "<="; return "<";
case RelationalOperator::EQ: return "=="; case RelationalOperator::LE:
case RelationalOperator::NE: return "/="; return "<=";
case RelationalOperator::GE: return ">="; case RelationalOperator::EQ:
case RelationalOperator::GT: return ">"; return "==";
case RelationalOperator::NE:
return "/=";
case RelationalOperator::GE:
return ">=";
case RelationalOperator::GT:
return ">";
} }
} }
} } // namespace Fortran::common

View File

@ -67,12 +67,18 @@ IntrinsicTypeDefaultKinds &IntrinsicTypeDefaultKinds::set_defaultLogicalKind(
int IntrinsicTypeDefaultKinds::GetDefaultKind(TypeCategory category) const { int IntrinsicTypeDefaultKinds::GetDefaultKind(TypeCategory category) const {
switch (category) { switch (category) {
case TypeCategory::Integer: return defaultIntegerKind_; case TypeCategory::Integer:
return defaultIntegerKind_;
case TypeCategory::Real: case TypeCategory::Real:
case TypeCategory::Complex: return defaultRealKind_; case TypeCategory::Complex:
case TypeCategory::Character: return defaultCharacterKind_; return defaultRealKind_;
case TypeCategory::Logical: return defaultLogicalKind_; case TypeCategory::Character:
default: CRASH_NO_CASE; return 0; return defaultCharacterKind_;
case TypeCategory::Logical:
return defaultLogicalKind_;
default:
CRASH_NO_CASE;
return 0;
} }
} }
} } // namespace Fortran::common

View File

@ -40,4 +40,4 @@ std::string EnumIndexToString(int index, const char *enumNames) {
} }
return std::string(p, q - p); return std::string(p, q - p);
} }
} } // namespace Fortran::common

View File

@ -40,7 +40,7 @@ static constexpr std::uint64_t TenToThe(int power) {
// 10**(LOG10RADIX + 3) must be < 2**wordbits, and LOG10RADIX must be // 10**(LOG10RADIX + 3) must be < 2**wordbits, and LOG10RADIX must be
// even, so that pairs of decimal digits do not straddle Digits. // even, so that pairs of decimal digits do not straddle Digits.
// So LOG10RADIX must be 16 or 6. // So LOG10RADIX must be 16 or 6.
template<int PREC, int LOG10RADIX = 16> class BigRadixFloatingPointNumber { template <int PREC, int LOG10RADIX = 16> class BigRadixFloatingPointNumber {
public: public:
using Real = BinaryFloatingPointNumber<PREC>; using Real = BinaryFloatingPointNumber<PREC>;
static constexpr int log10Radix{LOG10RADIX}; static constexpr int log10Radix{LOG10RADIX};
@ -67,7 +67,7 @@ private:
public: public:
explicit BigRadixFloatingPointNumber( explicit BigRadixFloatingPointNumber(
enum FortranRounding rounding = RoundDefault) enum FortranRounding rounding = RoundDefault)
: rounding_{rounding} {} : rounding_{rounding} {}
// Converts a binary floating point value. // Converts a binary floating point value.
explicit BigRadixFloatingPointNumber( explicit BigRadixFloatingPointNumber(
@ -113,8 +113,8 @@ public:
private: private:
BigRadixFloatingPointNumber(const BigRadixFloatingPointNumber &that) BigRadixFloatingPointNumber(const BigRadixFloatingPointNumber &that)
: digits_{that.digits_}, exponent_{that.exponent_}, : digits_{that.digits_}, exponent_{that.exponent_},
isNegative_{that.isNegative_}, rounding_{that.rounding_} { isNegative_{that.isNegative_}, rounding_{that.rounding_} {
for (int j{0}; j < digits_; ++j) { for (int j{0}; j < digits_; ++j) {
digit_[j] = that.digit_[j]; digit_[j] = that.digit_[j];
} }
@ -140,7 +140,7 @@ private:
// Sets *this to an unsigned integer value. // Sets *this to an unsigned integer value.
// Returns any remainder. // Returns any remainder.
template<typename UINT> UINT SetTo(UINT n) { template <typename UINT> UINT SetTo(UINT n) {
static_assert( static_assert(
std::is_same_v<UINT, common::uint128_t> || std::is_unsigned_v<UINT>); std::is_same_v<UINT, common::uint128_t> || std::is_unsigned_v<UINT>);
SetToZero(); SetToZero();
@ -198,12 +198,12 @@ private:
// This limited divisibility test only works for even divisors of the radix, // This limited divisibility test only works for even divisors of the radix,
// which is fine since it's only ever used with 2 and 5. // which is fine since it's only ever used with 2 and 5.
template<int N> bool IsDivisibleBy() const { template <int N> bool IsDivisibleBy() const {
static_assert(N > 1 && radix % N == 0, "bad modulus"); static_assert(N > 1 && radix % N == 0, "bad modulus");
return digits_ == 0 || (digit_[0] % N) == 0; return digits_ == 0 || (digit_[0] % N) == 0;
} }
template<unsigned DIVISOR> int DivideBy() { template <unsigned DIVISOR> int DivideBy() {
Digit remainder{0}; Digit remainder{0};
for (int j{digits_ - 1}; j >= 0; --j) { for (int j{digits_ - 1}; j >= 0; --j) {
Digit q{common::DivideUnsignedBy<Digit, DIVISOR>(digit_[j])}; Digit q{common::DivideUnsignedBy<Digit, DIVISOR>(digit_[j])};
@ -214,7 +214,7 @@ private:
return remainder; return remainder;
} }
int DivideByPowerOfTwo(int twoPow) { // twoPow <= LOG10RADIX int DivideByPowerOfTwo(int twoPow) { // twoPow <= LOG10RADIX
int remainder{0}; int remainder{0};
for (int j{digits_ - 1}; j >= 0; --j) { for (int j{digits_ - 1}; j >= 0; --j) {
Digit q{digit_[j] >> twoPow}; Digit q{digit_[j] >> twoPow};
@ -253,16 +253,16 @@ private:
} }
} }
template<int N> int MultiplyByHelper(int carry = 0) { template <int N> int MultiplyByHelper(int carry = 0) {
for (int j{0}; j < digits_; ++j) { for (int j{0}; j < digits_; ++j) {
auto v{N * digit_[j] + carry}; auto v{N * digit_[j] + carry};
carry = common::DivideUnsignedBy<Digit, radix>(v); carry = common::DivideUnsignedBy<Digit, radix>(v);
digit_[j] = v - carry * radix; // i.e., v % radix digit_[j] = v - carry * radix; // i.e., v % radix
} }
return carry; return carry;
} }
template<int N> int MultiplyBy(int carry = 0) { template <int N> int MultiplyBy(int carry = 0) {
if (int newCarry{MultiplyByHelper<N>(carry)}) { if (int newCarry{MultiplyByHelper<N>(carry)}) {
return AddCarry(digits_, newCarry); return AddCarry(digits_, newCarry);
} else { } else {
@ -270,7 +270,7 @@ private:
} }
} }
template<int N> int MultiplyWithoutNormalization() { template <int N> int MultiplyWithoutNormalization() {
if (int carry{MultiplyByHelper<N>(0)}) { if (int carry{MultiplyByHelper<N>(0)}) {
if (digits_ < digitLimit_) { if (digits_ < digitLimit_) {
digit_[digits_++] = carry; digit_[digits_++] = carry;
@ -283,7 +283,7 @@ private:
} }
} }
template<int N> void MultiplyByRounded() { template <int N> void MultiplyByRounded() {
if (int carry{MultiplyBy<N>()}) { if (int carry{MultiplyBy<N>()}) {
LoseLeastSignificantDigit(); LoseLeastSignificantDigit();
digit_[digits_ - 1] += carry; digit_[digits_ - 1] += carry;
@ -291,7 +291,7 @@ private:
} }
} }
void LoseLeastSignificantDigit(); // with rounding void LoseLeastSignificantDigit(); // with rounding
void PushCarry(int carry) { void PushCarry(int carry) {
if (digits_ == maxDigits && RemoveLeastOrderZeroDigits() == 0) { if (digits_ == maxDigits && RemoveLeastOrderZeroDigits() == 0) {
@ -319,12 +319,12 @@ private:
(Raw{1} << (Real::significandBits - 2)); (Raw{1} << (Real::significandBits - 2));
} }
Digit digit_[maxDigits]; // in little-endian order: digit_[0] is LSD Digit digit_[maxDigits]; // in little-endian order: digit_[0] is LSD
int digits_{0}; // # of elements in digit_[] array; zero when zero int digits_{0}; // # of elements in digit_[] array; zero when zero
int digitLimit_{maxDigits}; // precision clamp int digitLimit_{maxDigits}; // precision clamp
int exponent_{0}; // signed power of ten int exponent_{0}; // signed power of ten
bool isNegative_{false}; bool isNegative_{false};
enum FortranRounding rounding_ { RoundDefault }; enum FortranRounding rounding_ { RoundDefault };
}; };
} } // namespace Fortran::decimal
#endif #endif

View File

@ -11,10 +11,10 @@
namespace Fortran::decimal { namespace Fortran::decimal {
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
BigRadixFloatingPointNumber<PREC, LOG10RADIX>::BigRadixFloatingPointNumber( BigRadixFloatingPointNumber<PREC, LOG10RADIX>::BigRadixFloatingPointNumber(
BinaryFloatingPointNumber<PREC> x, enum FortranRounding rounding) BinaryFloatingPointNumber<PREC> x, enum FortranRounding rounding)
: rounding_{rounding} { : rounding_{rounding} {
bool negative{x.IsNegative()}; bool negative{x.IsNegative()};
if (x.IsZero()) { if (x.IsZero()) {
isNegative_ = negative; isNegative_ = negative;
@ -104,7 +104,7 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::BigRadixFloatingPointNumber(
Normalize(); Normalize();
} }
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
ConversionToDecimalResult ConversionToDecimalResult
BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToDecimal(char *buffer, BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToDecimal(char *buffer,
std::size_t n, enum DecimalConversionFlags flags, int maxDigits) const { std::size_t n, enum DecimalConversionFlags flags, int maxDigits) const {
@ -176,10 +176,17 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToDecimal(char *buffer,
incr = *end > '5' || incr = *end > '5' ||
(*end == '5' && (p > end + 1 || ((end[-1] - '0') & 1) != 0)); (*end == '5' && (p > end + 1 || ((end[-1] - '0') & 1) != 0));
break; break;
case RoundUp: incr = !isNegative_; break; case RoundUp:
case RoundDown: incr = isNegative_; break; incr = !isNegative_;
case RoundToZero: break; break;
case RoundCompatible: incr = *end >= '5'; break; case RoundDown:
incr = isNegative_;
break;
case RoundToZero:
break;
case RoundCompatible:
incr = *end >= '5';
break;
} }
p = end; p = end;
if (incr) { if (incr) {
@ -199,7 +206,7 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToDecimal(char *buffer,
} }
} }
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Mean( bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Mean(
const BigRadixFloatingPointNumber &that) { const BigRadixFloatingPointNumber &that) {
while (digits_ < that.digits_) { while (digits_ < that.digits_) {
@ -222,7 +229,7 @@ bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Mean(
return DivideBy<2>() != 0; return DivideBy<2>() != 0;
} }
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
void BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Minimize( void BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Minimize(
BigRadixFloatingPointNumber &&less, BigRadixFloatingPointNumber &&more) { BigRadixFloatingPointNumber &&less, BigRadixFloatingPointNumber &&more) {
int leastExponent{exponent_}; int leastExponent{exponent_};
@ -245,10 +252,10 @@ void BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Minimize(
more.MultiplyBy<10>(); more.MultiplyBy<10>();
} }
if (less.Mean(*this)) { if (less.Mean(*this)) {
less.AddCarry(); // round up less.AddCarry(); // round up
} }
if (!more.Mean(*this)) { if (!more.Mean(*this)) {
more.Decrement(); // round down more.Decrement(); // round down
} }
while (less.digits_ < more.digits_) { while (less.digits_ < more.digits_) {
less.digit_[less.digits_++] = 0; less.digit_[less.digits_++] = 0;
@ -292,7 +299,7 @@ void BigRadixFloatingPointNumber<PREC, LOG10RADIX>::Minimize(
Normalize(); Normalize();
} }
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
void BigRadixFloatingPointNumber<PREC, void BigRadixFloatingPointNumber<PREC,
LOG10RADIX>::LoseLeastSignificantDigit() { LOG10RADIX>::LoseLeastSignificantDigit() {
Digit LSD{digit_[0]}; Digit LSD{digit_[0]};
@ -306,17 +313,24 @@ void BigRadixFloatingPointNumber<PREC,
case RoundDefault: case RoundDefault:
incr = LSD > radix / 2 || (LSD == radix / 2 && digit_[0] % 2 != 0); incr = LSD > radix / 2 || (LSD == radix / 2 && digit_[0] % 2 != 0);
break; break;
case RoundUp: incr = LSD > 0 && !isNegative_; break; case RoundUp:
case RoundDown: incr = LSD > 0 && isNegative_; break; incr = LSD > 0 && !isNegative_;
case RoundToZero: break; break;
case RoundCompatible: incr = LSD >= radix / 2; break; case RoundDown:
incr = LSD > 0 && isNegative_;
break;
case RoundToZero:
break;
case RoundCompatible:
incr = LSD >= radix / 2;
break;
} }
for (int j{0}; (digit_[j] += incr) == radix; ++j) { for (int j{0}; (digit_[j] += incr) == radix; ++j) {
digit_[j] = 0; digit_[j] = 0;
} }
} }
template<int PREC> template <int PREC>
ConversionToDecimalResult ConvertToDecimal(char *buffer, std::size_t size, ConversionToDecimalResult ConvertToDecimal(char *buffer, std::size_t size,
enum DecimalConversionFlags flags, int digits, enum DecimalConversionFlags flags, int digits,
enum FortranRounding rounding, BinaryFloatingPointNumber<PREC> x) { enum FortranRounding rounding, BinaryFloatingPointNumber<PREC> x) {
@ -398,4 +412,4 @@ ConversionToDecimalResult ConvertLongDoubleToDecimal(char *buffer,
} }
#endif #endif
} }
} } // namespace Fortran::decimal

View File

@ -17,7 +17,7 @@
namespace Fortran::decimal { namespace Fortran::decimal {
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber( bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
const char *&p, bool &inexact) { const char *&p, bool &inexact) {
SetToZero(); SetToZero();
@ -43,7 +43,7 @@ bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
} }
} }
if (q == start || (q == start + 1 && *start == '.')) { if (q == start || (q == start + 1 && *start == '.')) {
return false; // require at least one digit return false; // require at least one digit
} }
// There's a valid number here; set the reference argument to point to // There's a valid number here; set the reference argument to point to
// the first character afterward. // the first character afterward.
@ -81,7 +81,7 @@ bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
exponent_ -= static_cast<int>(q - point - 1); exponent_ -= static_cast<int>(q - point - 1);
} }
if (q == first) { if (q == first) {
exponent_ = 0; // all zeros exponent_ = 0; // all zeros
} }
// Rack the decimal digits up into big Digits. // Rack the decimal digits up into big Digits.
for (auto times{radix}; q-- > first;) { for (auto times{radix}; q-- > first;) {
@ -125,7 +125,7 @@ bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
expo = 10 * Real::decimalRange; expo = 10 * Real::decimalRange;
exponent_ = 0; exponent_ = 0;
} }
p = q; // exponent was valid p = q; // exponent was valid
if (negExpo) { if (negExpo) {
exponent_ -= expo; exponent_ -= expo;
} else { } else {
@ -133,7 +133,8 @@ bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
} }
} }
} break; } break;
default: break; default:
break;
} }
return true; return true;
} }
@ -142,7 +143,7 @@ bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
// binary floating-point value with an unbiased (i.e., signed) // binary floating-point value with an unbiased (i.e., signed)
// binary exponent, an integer value (not a fraction) with an implied // binary exponent, an integer value (not a fraction) with an implied
// binary point to its *right*, and some guard bits for rounding. // binary point to its *right*, and some guard bits for rounding.
template<int PREC> class IntermediateFloat { template <int PREC> class IntermediateFloat {
public: public:
static constexpr int precision{PREC}; static constexpr int precision{PREC};
using IntType = common::HostUnsignedIntType<precision>; using IntType = common::HostUnsignedIntType<precision>;
@ -154,7 +155,7 @@ public:
// Assumes that exponent_ is valid on entry, and may increment it. // Assumes that exponent_ is valid on entry, and may increment it.
// Returns the number of guard_ bits that have been determined. // Returns the number of guard_ bits that have been determined.
template<typename UINT> bool SetTo(UINT n) { template <typename UINT> bool SetTo(UINT n) {
static constexpr int nBits{CHAR_BIT * sizeof n}; static constexpr int nBits{CHAR_BIT * sizeof n};
if constexpr (precision >= nBits) { if constexpr (precision >= nBits) {
value_ = n; value_ = n;
@ -187,7 +188,7 @@ public:
bool isNegative, FortranRounding) const; bool isNegative, FortranRounding) const;
private: private:
static constexpr int guardBits{3}; // guard, round, sticky static constexpr int guardBits{3}; // guard, round, sticky
using GuardType = int; using GuardType = int;
static constexpr GuardType oneHalf{GuardType{1} << (guardBits - 1)}; static constexpr GuardType oneHalf{GuardType{1} << (guardBits - 1)};
@ -196,7 +197,7 @@ private:
int exponent_{0}; int exponent_{0};
}; };
template<int PREC> template <int PREC>
ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary( ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary(
bool isNegative, FortranRounding rounding) const { bool isNegative, FortranRounding rounding) const {
using Binary = BinaryFloatingPointNumber<PREC>; using Binary = BinaryFloatingPointNumber<PREC>;
@ -231,10 +232,17 @@ ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary(
case RoundDefault: case RoundDefault:
incr = guard > oneHalf || (guard == oneHalf && (fraction & 1)); incr = guard > oneHalf || (guard == oneHalf && (fraction & 1));
break; break;
case RoundUp: incr = guard != 0 && !isNegative; break; case RoundUp:
case RoundDown: incr = guard != 0 && isNegative; break; incr = guard != 0 && !isNegative;
case RoundToZero: break; break;
case RoundCompatible: incr = guard >= oneHalf; break; case RoundDown:
incr = guard != 0 && isNegative;
break;
case RoundToZero:
break;
case RoundCompatible:
incr = guard >= oneHalf;
break;
} }
if (incr) { if (incr) {
if (fraction == mask) { if (fraction == mask) {
@ -246,10 +254,10 @@ ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary(
} }
} }
if (expo == 1 && fraction < topBit) { if (expo == 1 && fraction < topBit) {
expo = 0; // subnormal expo = 0; // subnormal
} }
if (expo >= Binary::maxExponent) { if (expo >= Binary::maxExponent) {
expo = Binary::maxExponent; // Inf expo = Binary::maxExponent; // Inf
flags |= Overflow; flags |= Overflow;
fraction = 0; fraction = 0;
} }
@ -263,14 +271,14 @@ ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary(
return {Binary(raw), static_cast<enum ConversionResultFlags>(flags)}; return {Binary(raw), static_cast<enum ConversionResultFlags>(flags)};
} }
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
ConversionToBinaryResult<PREC> ConversionToBinaryResult<PREC>
BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() { BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() {
// On entry, *this holds a multi-precision integer value in a radix of a // On entry, *this holds a multi-precision integer value in a radix of a
// large power of ten. Its radix point is defined to be to the right of its // large power of ten. Its radix point is defined to be to the right of its
// digits, and "exponent_" is the power of ten by which it is to be scaled. // digits, and "exponent_" is the power of ten by which it is to be scaled.
Normalize(); Normalize();
if (digits_ == 0) { // zero value if (digits_ == 0) { // zero value
return {Real{SignBit()}}; return {Real{SignBit()}};
} }
// The value is not zero: x = D. * 10.**E // The value is not zero: x = D. * 10.**E
@ -279,9 +287,9 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() {
exponent_ += digits_ * log10Radix; exponent_ += digits_ * log10Radix;
// Sanity checks for ridiculous exponents // Sanity checks for ridiculous exponents
static constexpr int crazy{2 * Real::decimalRange + log10Radix}; static constexpr int crazy{2 * Real::decimalRange + log10Radix};
if (exponent_ < -crazy) { // underflow to +/-0. if (exponent_ < -crazy) { // underflow to +/-0.
return {Real{SignBit()}, Inexact}; return {Real{SignBit()}, Inexact};
} else if (exponent_ > crazy) { // overflow to +/-Inf. } else if (exponent_ > crazy) { // overflow to +/-Inf.
return {Real{Infinity()}, Overflow}; return {Real{Infinity()}, Overflow};
} }
// Apply any negative decimal exponent by multiplication // Apply any negative decimal exponent by multiplication
@ -346,7 +354,7 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() {
return f.ToBinary(isNegative_, rounding_); return f.ToBinary(isNegative_, rounding_);
} }
template<int PREC, int LOG10RADIX> template <int PREC, int LOG10RADIX>
ConversionToBinaryResult<PREC> ConversionToBinaryResult<PREC>
BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary(const char *&p) { BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary(const char *&p) {
bool inexact{false}; bool inexact{false};
@ -383,7 +391,7 @@ BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary(const char *&p) {
} }
} }
template<int PREC> template <int PREC>
ConversionToBinaryResult<PREC> ConvertToBinary( ConversionToBinaryResult<PREC> ConvertToBinary(
const char *&p, enum FortranRounding rounding) { const char *&p, enum FortranRounding rounding) {
return BigRadixFloatingPointNumber<PREC>{rounding}.ConvertToBinary(p); return BigRadixFloatingPointNumber<PREC>{rounding}.ConvertToBinary(p);
@ -427,4 +435,4 @@ enum ConversionResultFlags ConvertDecimalToLongDouble(
} }
#endif #endif
} }
} } // namespace Fortran::decimal

View File

@ -18,12 +18,12 @@ namespace Fortran::evaluate {
DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ActualArgument) DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ActualArgument)
ActualArgument::ActualArgument(Expr<SomeType> &&x) : u_{std::move(x)} {} ActualArgument::ActualArgument(Expr<SomeType> &&x) : u_{std::move(x)} {}
ActualArgument::ActualArgument(common::CopyableIndirection<Expr<SomeType>> &&v) ActualArgument::ActualArgument(common::CopyableIndirection<Expr<SomeType>> &&v)
: u_{std::move(v)} {} : u_{std::move(v)} {}
ActualArgument::ActualArgument(AssumedType x) : u_{x} {} ActualArgument::ActualArgument(AssumedType x) : u_{x} {}
ActualArgument::~ActualArgument() {} ActualArgument::~ActualArgument() {}
ActualArgument::AssumedType::AssumedType(const Symbol &symbol) ActualArgument::AssumedType::AssumedType(const Symbol &symbol)
: symbol_{symbol} { : symbol_{symbol} {
const semantics::DeclTypeSpec *type{symbol.GetType()}; const semantics::DeclTypeSpec *type{symbol.GetType()};
CHECK(type && type->category() == semantics::DeclTypeSpec::TypeStar); CHECK(type && type->category() == semantics::DeclTypeSpec::TypeStar);
} }
@ -65,8 +65,8 @@ void ActualArgument::Parenthesize() {
SpecificIntrinsic::SpecificIntrinsic( SpecificIntrinsic::SpecificIntrinsic(
IntrinsicProcedure n, characteristics::Procedure &&chars) IntrinsicProcedure n, characteristics::Procedure &&chars)
: name{n}, characteristics{new characteristics::Procedure{std::move(chars)}} { : name{n}, characteristics{
} new characteristics::Procedure{std::move(chars)}} {}
DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(SpecificIntrinsic) DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(SpecificIntrinsic)
@ -77,7 +77,7 @@ bool SpecificIntrinsic::operator==(const SpecificIntrinsic &that) const {
} }
ProcedureDesignator::ProcedureDesignator(Component &&c) ProcedureDesignator::ProcedureDesignator(Component &&c)
: u{common::CopyableIndirection<Component>::Make(std::move(c))} {} : u{common::CopyableIndirection<Component>::Make(std::move(c))} {}
bool ProcedureDesignator::operator==(const ProcedureDesignator &that) const { bool ProcedureDesignator::operator==(const ProcedureDesignator &that) const {
return u == that.u; return u == that.u;
@ -150,14 +150,13 @@ const Component *ProcedureDesignator::GetComponent() const {
} }
const Symbol *ProcedureDesignator::GetSymbol() const { const Symbol *ProcedureDesignator::GetSymbol() const {
return std::visit( return std::visit(common::visitors{
common::visitors{ [](SymbolRef symbol) { return &*symbol; },
[](SymbolRef symbol) { return &*symbol; }, [](const common::CopyableIndirection<Component> &c) {
[](const common::CopyableIndirection<Component> &c) { return &c.value().GetLastSymbol();
return &c.value().GetLastSymbol(); },
}, [](const auto &) -> const Symbol * { return nullptr; },
[](const auto &) -> const Symbol * { return nullptr; }, },
},
u); u);
} }
@ -213,5 +212,5 @@ int ProcedureRef::Rank() const {
ProcedureRef::~ProcedureRef() {} ProcedureRef::~ProcedureRef() {}
FOR_EACH_SPECIFIC_TYPE(template class FunctionRef, ) FOR_EACH_SPECIFIC_TYPE(template class FunctionRef, )
} } // namespace Fortran::evaluate
DEFINE_DELETER(Fortran::evaluate::ProcedureRef) DEFINE_DELETER(Fortran::evaluate::ProcedureRef)

View File

@ -19,7 +19,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> class CharacterUtils { template <int KIND> class CharacterUtils {
using Character = Scalar<Type<TypeCategory::Character, KIND>>; using Character = Scalar<Type<TypeCategory::Character, KIND>>;
using CharT = typename Character::value_type; using CharT = typename Character::value_type;
@ -117,6 +117,6 @@ private:
static constexpr CharT NewLine() { return 0x0a; } static constexpr CharT NewLine() { return 0x0a; }
}; };
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_CHARACTER_H_ #endif // FORTRAN_EVALUATE_CHARACTER_H_

View File

@ -24,7 +24,7 @@ using namespace Fortran::parser::literals;
namespace Fortran::evaluate::characteristics { namespace Fortran::evaluate::characteristics {
// Copy attributes from a symbol to dst based on the mapping in pairs. // Copy attributes from a symbol to dst based on the mapping in pairs.
template<typename A, typename B> template <typename A, typename B>
static void CopyAttrs(const semantics::Symbol &src, A &dst, static void CopyAttrs(const semantics::Symbol &src, A &dst,
const std::initializer_list<std::pair<semantics::Attr, B>> &pairs) { const std::initializer_list<std::pair<semantics::Attr, B>> &pairs) {
for (const auto &pair : pairs) { for (const auto &pair : pairs) {
@ -245,17 +245,17 @@ bool DummyDataObject::CanBePassedViaImplicitInterface() const {
Attrs{Attr::Allocatable, Attr::Asynchronous, Attr::Optional, Attrs{Attr::Allocatable, Attr::Asynchronous, Attr::Optional,
Attr::Pointer, Attr::Target, Attr::Value, Attr::Volatile}) Attr::Pointer, Attr::Target, Attr::Value, Attr::Volatile})
.any()) { .any()) {
return false; // 15.4.2.2(3)(a) return false; // 15.4.2.2(3)(a)
} else if ((type.attrs() & } else if ((type.attrs() &
TypeAndShape::Attrs{TypeAndShape::Attr::AssumedShape, TypeAndShape::Attrs{TypeAndShape::Attr::AssumedShape,
TypeAndShape::Attr::AssumedRank, TypeAndShape::Attr::AssumedRank,
TypeAndShape::Attr::Coarray}) TypeAndShape::Attr::Coarray})
.any()) { .any()) {
return false; // 15.4.2.2(3)(b-d) return false; // 15.4.2.2(3)(b-d)
} else if (type.type().IsPolymorphic()) { } else if (type.type().IsPolymorphic()) {
return false; // 15.4.2.2(3)(f) return false; // 15.4.2.2(3)(f)
} else if (const auto *derived{GetDerivedTypeSpec(type.type())}) { } else if (const auto *derived{GetDerivedTypeSpec(type.type())}) {
return derived->parameters().empty(); // 15.4.2.2(3)(e) return derived->parameters().empty(); // 15.4.2.2(3)(e)
} else { } else {
return true; return true;
} }
@ -278,7 +278,7 @@ llvm::raw_ostream &DummyDataObject::Dump(llvm::raw_ostream &o) const {
} }
DummyProcedure::DummyProcedure(Procedure &&p) DummyProcedure::DummyProcedure(Procedure &&p)
: procedure{new Procedure{std::move(p)}} {} : procedure{new Procedure{std::move(p)}} {}
bool DummyProcedure::operator==(const DummyProcedure &that) const { bool DummyProcedure::operator==(const DummyProcedure &that) const {
return attrs == that.attrs && intent == that.intent && return attrs == that.attrs && intent == that.intent &&
@ -322,7 +322,7 @@ llvm::raw_ostream &AlternateReturn::Dump(llvm::raw_ostream &o) const {
DummyArgument::~DummyArgument() {} DummyArgument::~DummyArgument() {}
bool DummyArgument::operator==(const DummyArgument &that) const { bool DummyArgument::operator==(const DummyArgument &that) const {
return u == that.u; // name and passed-object usage are not characteristics return u == that.u; // name and passed-object usage are not characteristics
} }
std::optional<DummyArgument> DummyArgument::Characterize( std::optional<DummyArgument> DummyArgument::Characterize(
@ -398,16 +398,15 @@ bool DummyArgument::IsOptional() const {
} }
void DummyArgument::SetOptional(bool value) { void DummyArgument::SetOptional(bool value) {
std::visit( std::visit(common::visitors{
common::visitors{ [value](DummyDataObject &data) {
[value](DummyDataObject &data) { data.attrs.set(DummyDataObject::Attr::Optional, value);
data.attrs.set(DummyDataObject::Attr::Optional, value); },
}, [value](DummyProcedure &proc) {
[value](DummyProcedure &proc) { proc.attrs.set(DummyProcedure::Attr::Optional, value);
proc.attrs.set(DummyProcedure::Attr::Optional, value); },
}, [](AlternateReturn &) { DIE("cannot set optional"); },
[](AlternateReturn &) { DIE("cannot set optional"); }, },
},
u); u);
} }
@ -470,17 +469,17 @@ bool FunctionResult::IsAssumedLengthCharacter() const {
bool FunctionResult::CanBeReturnedViaImplicitInterface() const { bool FunctionResult::CanBeReturnedViaImplicitInterface() const {
if (attrs.test(Attr::Pointer) || attrs.test(Attr::Allocatable)) { if (attrs.test(Attr::Pointer) || attrs.test(Attr::Allocatable)) {
return false; // 15.4.2.2(4)(b) return false; // 15.4.2.2(4)(b)
} else if (const auto *typeAndShape{GetTypeAndShape()}) { } else if (const auto *typeAndShape{GetTypeAndShape()}) {
if (typeAndShape->Rank() > 0) { if (typeAndShape->Rank() > 0) {
return false; // 15.4.2.2(4)(a) return false; // 15.4.2.2(4)(a)
} else { } else {
const DynamicType &type{typeAndShape->type()}; const DynamicType &type{typeAndShape->type()};
switch (type.category()) { switch (type.category()) {
case TypeCategory::Character: case TypeCategory::Character:
if (const auto *param{type.charLength()}) { if (const auto *param{type.charLength()}) {
if (const auto &expr{param->GetExplicit()}) { if (const auto &expr{param->GetExplicit()}) {
return IsConstantExpr(*expr); // 15.4.2.2(4)(c) return IsConstantExpr(*expr); // 15.4.2.2(4)(c)
} }
} }
return false; return false;
@ -490,38 +489,39 @@ bool FunctionResult::CanBeReturnedViaImplicitInterface() const {
for (const auto &pair : spec.parameters()) { for (const auto &pair : spec.parameters()) {
if (const auto &expr{pair.second.GetExplicit()}) { if (const auto &expr{pair.second.GetExplicit()}) {
if (!IsConstantExpr(*expr)) { if (!IsConstantExpr(*expr)) {
return false; // 15.4.2.2(4)(c) return false; // 15.4.2.2(4)(c)
} }
} }
} }
return true; return true;
} }
return false; return false;
default: return true; default:
return true;
} }
} }
} else { } else {
return false; // 15.4.2.2(4)(b) - procedure pointer return false; // 15.4.2.2(4)(b) - procedure pointer
} }
} }
llvm::raw_ostream &FunctionResult::Dump(llvm::raw_ostream &o) const { llvm::raw_ostream &FunctionResult::Dump(llvm::raw_ostream &o) const {
attrs.Dump(o, EnumToString); attrs.Dump(o, EnumToString);
std::visit( std::visit(common::visitors{
common::visitors{ [&](const TypeAndShape &ts) { ts.Dump(o); },
[&](const TypeAndShape &ts) { ts.Dump(o); }, [&](const CopyableIndirection<Procedure> &p) {
[&](const CopyableIndirection<Procedure> &p) { p.value().Dump(o << " procedure(") << ')';
p.value().Dump(o << " procedure(") << ')'; },
}, },
},
u); u);
return o; return o;
} }
Procedure::Procedure(FunctionResult &&fr, DummyArguments &&args, Attrs a) Procedure::Procedure(FunctionResult &&fr, DummyArguments &&args, Attrs a)
: functionResult{std::move(fr)}, dummyArguments{std::move(args)}, attrs{a} {} : functionResult{std::move(fr)}, dummyArguments{std::move(args)}, attrs{a} {
}
Procedure::Procedure(DummyArguments &&args, Attrs a) Procedure::Procedure(DummyArguments &&args, Attrs a)
: dummyArguments{std::move(args)}, attrs{a} {} : dummyArguments{std::move(args)}, attrs{a} {}
Procedure::~Procedure() {} Procedure::~Procedure() {}
bool Procedure::operator==(const Procedure &that) const { bool Procedure::operator==(const Procedure &that) const {
@ -573,7 +573,7 @@ std::optional<Procedure> Procedure::Characterize(
}); });
if (result.attrs.test(Attr::Elemental) && if (result.attrs.test(Attr::Elemental) &&
!symbol.attrs().test(semantics::Attr::IMPURE)) { !symbol.attrs().test(semantics::Attr::IMPURE)) {
result.attrs.set(Attr::Pure); // explicitly flag pure procedures result.attrs.set(Attr::Pure); // explicitly flag pure procedures
} }
return std::visit( return std::visit(
common::visitors{ common::visitors{
@ -686,7 +686,7 @@ std::optional<Procedure> Procedure::Characterize(
bool Procedure::CanBeCalledViaImplicitInterface() const { bool Procedure::CanBeCalledViaImplicitInterface() const {
if (attrs.test(Attr::Elemental) || attrs.test(Attr::BindC)) { if (attrs.test(Attr::Elemental) || attrs.test(Attr::BindC)) {
return false; // 15.4.2.2(5,6) return false; // 15.4.2.2(5,6)
} else if (IsFunction() && } else if (IsFunction() &&
!functionResult->CanBeReturnedViaImplicitInterface()) { !functionResult->CanBeReturnedViaImplicitInterface()) {
return false; return false;
@ -765,11 +765,11 @@ bool DistinguishUtils::DistinguishableOpOrAssign(
auto &args1{proc1.dummyArguments}; auto &args1{proc1.dummyArguments};
auto &args2{proc2.dummyArguments}; auto &args2{proc2.dummyArguments};
if (args1.size() != args2.size()) { if (args1.size() != args2.size()) {
return true; // C1511: distinguishable based on number of arguments return true; // C1511: distinguishable based on number of arguments
} }
for (std::size_t i{0}; i < args1.size(); ++i) { for (std::size_t i{0}; i < args1.size(); ++i) {
if (Distinguishable(args1[i], args2[i])) { if (Distinguishable(args1[i], args2[i])) {
return true; // C1511, C1512: distinguishable based on this arg return true; // C1511, C1512: distinguishable based on this arg
} }
} }
return false; return false;
@ -782,23 +782,23 @@ bool DistinguishUtils::Distinguishable(
auto count1{CountDummyProcedures(args1)}; auto count1{CountDummyProcedures(args1)};
auto count2{CountDummyProcedures(args2)}; auto count2{CountDummyProcedures(args2)};
if (count1.notOptional > count2.total || count2.notOptional > count1.total) { if (count1.notOptional > count2.total || count2.notOptional > count1.total) {
return true; // distinguishable based on C1514 rule 2 return true; // distinguishable based on C1514 rule 2
} }
if (Rule3Distinguishable(proc1, proc2)) { if (Rule3Distinguishable(proc1, proc2)) {
return true; // distinguishable based on C1514 rule 3 return true; // distinguishable based on C1514 rule 3
} }
if (Rule1DistinguishingArg(args1, args2)) { if (Rule1DistinguishingArg(args1, args2)) {
return true; // distinguishable based on C1514 rule 1 return true; // distinguishable based on C1514 rule 1
} }
int pos1{FindFirstToDistinguishByPosition(args1, args2)}; int pos1{FindFirstToDistinguishByPosition(args1, args2)};
int name1{FindLastToDistinguishByName(args1, args2)}; int name1{FindLastToDistinguishByName(args1, args2)};
if (pos1 >= 0 && pos1 <= name1) { if (pos1 >= 0 && pos1 <= name1) {
return true; // distinguishable based on C1514 rule 4 return true; // distinguishable based on C1514 rule 4
} }
int pos2{FindFirstToDistinguishByPosition(args2, args1)}; int pos2{FindFirstToDistinguishByPosition(args2, args1)};
int name2{FindLastToDistinguishByName(args2, args1)}; int name2{FindLastToDistinguishByName(args2, args1)};
if (pos2 >= 0 && pos2 <= name2) { if (pos2 >= 0 && pos2 <= name2) {
return true; // distinguishable based on C1514 rule 4 return true; // distinguishable based on C1514 rule 4
} }
return false; return false;
} }
@ -843,7 +843,7 @@ const DummyArgument *DistinguishUtils::Rule1DistinguishingArg(
// - the dummy argument at that position is distinguishable from it // - the dummy argument at that position is distinguishable from it
int DistinguishUtils::FindFirstToDistinguishByPosition( int DistinguishUtils::FindFirstToDistinguishByPosition(
const DummyArguments &args1, const DummyArguments &args2) { const DummyArguments &args1, const DummyArguments &args2) {
int effective{0}; // position of arg1 in list, ignoring passed arg int effective{0}; // position of arg1 in list, ignoring passed arg
for (std::size_t i{0}; i < args1.size(); ++i) { for (std::size_t i{0}; i < args1.size(); ++i) {
const DummyArgument &arg1{args1.at(i)}; const DummyArgument &arg1{args1.at(i)};
if (!arg1.pass && !arg1.IsOptional()) { if (!arg1.pass && !arg1.IsOptional()) {
@ -901,7 +901,7 @@ int DistinguishUtils::CountNotDistinguishableFrom(
bool DistinguishUtils::Distinguishable( bool DistinguishUtils::Distinguishable(
const DummyArgument &x, const DummyArgument &y) { const DummyArgument &x, const DummyArgument &y) {
if (x.u.index() != y.u.index()) { if (x.u.index() != y.u.index()) {
return true; // different kind: data/proc/alt-return return true; // different kind: data/proc/alt-return
} }
return std::visit( return std::visit(
common::visitors{ common::visitors{
@ -949,7 +949,7 @@ bool DistinguishUtils::Distinguishable(
bool DistinguishUtils::Distinguishable( bool DistinguishUtils::Distinguishable(
const FunctionResult &x, const FunctionResult &y) { const FunctionResult &x, const FunctionResult &y) {
if (x.u.index() != y.u.index()) { if (x.u.index() != y.u.index()) {
return true; // one is data object, one is procedure return true; // one is data object, one is procedure
} }
return std::visit( return std::visit(
common::visitors{ common::visitors{
@ -1020,7 +1020,7 @@ DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyArgument)
DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyProcedure) DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyProcedure)
DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(FunctionResult) DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(FunctionResult)
DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure) DEFINE_DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure)
} } // namespace Fortran::evaluate::characteristics
template class Fortran::common::Indirection< template class Fortran::common::Indirection<
Fortran::evaluate::characteristics::Procedure, true>; Fortran::evaluate::characteristics::Procedure, true>;

View File

@ -26,7 +26,7 @@ public:
IsConstantExprHelper() : Base{*this} {} IsConstantExprHelper() : Base{*this} {}
using Base::operator(); using Base::operator();
template<int KIND> bool operator()(const TypeParamInquiry<KIND> &inq) const { template <int KIND> bool operator()(const TypeParamInquiry<KIND> &inq) const {
return IsKindTypeParameter(inq.parameter()); return IsKindTypeParameter(inq.parameter());
} }
bool operator()(const semantics::Symbol &symbol) const { bool operator()(const semantics::Symbol &symbol) const {
@ -36,7 +36,7 @@ public:
bool operator()(const semantics::ParamValue &param) const { bool operator()(const semantics::ParamValue &param) const {
return param.isExplicit() && (*this)(param.GetExplicit()); return param.isExplicit() && (*this)(param.GetExplicit());
} }
template<typename T> bool operator()(const FunctionRef<T> &call) const { template <typename T> bool operator()(const FunctionRef<T> &call) const {
if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&call.proc().u)}) { if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&call.proc().u)}) {
return intrinsic->name == "kind"; return intrinsic->name == "kind";
// TODO: other inquiry intrinsics // TODO: other inquiry intrinsics
@ -46,7 +46,7 @@ public:
} }
// Forbid integer division by zero in constants. // Forbid integer division by zero in constants.
template<int KIND> template <int KIND>
bool operator()( bool operator()(
const Divide<Type<TypeCategory::Integer, KIND>> &division) const { const Divide<Type<TypeCategory::Integer, KIND>> &division) const {
using T = Type<TypeCategory::Integer, KIND>; using T = Type<TypeCategory::Integer, KIND>;
@ -58,7 +58,7 @@ public:
} }
}; };
template<typename A> bool IsConstantExpr(const A &x) { template <typename A> bool IsConstantExpr(const A &x) {
return IsConstantExprHelper{}(x); return IsConstantExprHelper{}(x);
} }
template bool IsConstantExpr(const Expr<SomeType> &); template bool IsConstantExpr(const Expr<SomeType> &);
@ -69,15 +69,15 @@ template bool IsConstantExpr(const Expr<SubscriptInteger> &);
// This code determines whether an expression is allowable as the static // This code determines whether an expression is allowable as the static
// data address used to initialize a pointer with "=> x". See C765. // data address used to initialize a pointer with "=> x". See C765.
struct IsInitialDataTargetHelper struct IsInitialDataTargetHelper
: public AllTraverse<IsInitialDataTargetHelper, true> { : public AllTraverse<IsInitialDataTargetHelper, true> {
using Base = AllTraverse<IsInitialDataTargetHelper, true>; using Base = AllTraverse<IsInitialDataTargetHelper, true>;
using Base::operator(); using Base::operator();
explicit IsInitialDataTargetHelper(parser::ContextualMessages &m) explicit IsInitialDataTargetHelper(parser::ContextualMessages &m)
: Base{*this}, messages_{m} {} : Base{*this}, messages_{m} {}
bool operator()(const BOZLiteralConstant &) const { return false; } bool operator()(const BOZLiteralConstant &) const { return false; }
bool operator()(const NullPointer &) const { return true; } bool operator()(const NullPointer &) const { return true; }
template<typename T> bool operator()(const Constant<T> &) const { template <typename T> bool operator()(const Constant<T> &) const {
return false; return false;
} }
bool operator()(const semantics::Symbol &symbol) const { bool operator()(const semantics::Symbol &symbol) const {
@ -102,7 +102,7 @@ struct IsInitialDataTargetHelper
return true; return true;
} }
bool operator()(const StaticDataObject &) const { return false; } bool operator()(const StaticDataObject &) const { return false; }
template<int KIND> bool operator()(const TypeParamInquiry<KIND> &) const { template <int KIND> bool operator()(const TypeParamInquiry<KIND> &) const {
return false; return false;
} }
bool operator()(const Triplet &x) const { bool operator()(const Triplet &x) const {
@ -110,13 +110,13 @@ struct IsInitialDataTargetHelper
IsConstantExpr(x.stride()); IsConstantExpr(x.stride());
} }
bool operator()(const Subscript &x) const { bool operator()(const Subscript &x) const {
return std::visit( return std::visit(common::visitors{
common::visitors{ [&](const Triplet &t) { return (*this)(t); },
[&](const Triplet &t) { return (*this)(t); }, [&](const auto &y) {
[&](const auto &y) { return y.value().Rank() == 0 &&
return y.value().Rank() == 0 && IsConstantExpr(y.value()); IsConstantExpr(y.value());
}, },
}, },
x.u); x.u);
} }
bool operator()(const CoarrayRef &) const { return false; } bool operator()(const CoarrayRef &) const { return false; }
@ -125,16 +125,18 @@ struct IsInitialDataTargetHelper
(*this)(x.parent()); (*this)(x.parent());
} }
bool operator()(const DescriptorInquiry &) const { return false; } bool operator()(const DescriptorInquiry &) const { return false; }
template<typename T> bool operator()(const ArrayConstructor<T> &) const { template <typename T> bool operator()(const ArrayConstructor<T> &) const {
return false; return false;
} }
bool operator()(const StructureConstructor &) const { return false; } bool operator()(const StructureConstructor &) const { return false; }
template<typename T> bool operator()(const FunctionRef<T> &) { return false; } template <typename T> bool operator()(const FunctionRef<T> &) {
template<typename D, typename R, typename... O> return false;
}
template <typename D, typename R, typename... O>
bool operator()(const Operation<D, R, O...> &) const { bool operator()(const Operation<D, R, O...> &) const {
return false; return false;
} }
template<typename T> bool operator()(const Parentheses<T> &x) const { template <typename T> bool operator()(const Parentheses<T> &x) const {
return (*this)(x.left()); return (*this)(x.left());
} }
bool operator()(const Relational<SomeType> &) const { return false; } bool operator()(const Relational<SomeType> &) const { return false; }
@ -150,13 +152,13 @@ bool IsInitialDataTarget(
// Specification expression validation (10.1.11(2), C1010) // Specification expression validation (10.1.11(2), C1010)
class CheckSpecificationExprHelper class CheckSpecificationExprHelper
: public AnyTraverse<CheckSpecificationExprHelper, : public AnyTraverse<CheckSpecificationExprHelper,
std::optional<std::string>> { std::optional<std::string>> {
public: public:
using Result = std::optional<std::string>; using Result = std::optional<std::string>;
using Base = AnyTraverse<CheckSpecificationExprHelper, Result>; using Base = AnyTraverse<CheckSpecificationExprHelper, Result>;
explicit CheckSpecificationExprHelper(const semantics::Scope &s) explicit CheckSpecificationExprHelper(const semantics::Scope &s)
: Base{*this}, scope_{s} {} : Base{*this}, scope_{s} {}
using Base::operator(); using Base::operator();
Result operator()(const ProcedureDesignator &) const { Result operator()(const ProcedureDesignator &) const {
@ -211,7 +213,7 @@ public:
return std::nullopt; return std::nullopt;
} }
template<typename T> Result operator()(const FunctionRef<T> &x) const { template <typename T> Result operator()(const FunctionRef<T> &x) const {
if (const auto *symbol{x.proc().GetSymbol()}) { if (const auto *symbol{x.proc().GetSymbol()}) {
if (!semantics::IsPureProcedure(*symbol)) { if (!semantics::IsPureProcedure(*symbol)) {
return "reference to impure function '"s + symbol->name().ToString() + return "reference to impure function '"s + symbol->name().ToString() +
@ -221,7 +223,7 @@ public:
} else { } else {
const SpecificIntrinsic &intrin{DEREF(x.proc().GetSpecificIntrinsic())}; const SpecificIntrinsic &intrin{DEREF(x.proc().GetSpecificIntrinsic())};
if (intrin.name == "present") { if (intrin.name == "present") {
return std::nullopt; // no need to check argument(s) return std::nullopt; // no need to check argument(s)
} }
if (IsConstantExpr(x)) { if (IsConstantExpr(x)) {
// inquiry functions may not need to check argument(s) // inquiry functions may not need to check argument(s)
@ -235,7 +237,7 @@ private:
const semantics::Scope &scope_; const semantics::Scope &scope_;
}; };
template<typename A> template <typename A>
void CheckSpecificationExpr(const A &x, parser::ContextualMessages &messages, void CheckSpecificationExpr(const A &x, parser::ContextualMessages &messages,
const semantics::Scope &scope) { const semantics::Scope &scope) {
if (auto why{CheckSpecificationExprHelper{scope}(x)}) { if (auto why{CheckSpecificationExprHelper{scope}(x)}) {
@ -259,12 +261,12 @@ template void CheckSpecificationExpr(
// IsSimplyContiguous() -- 9.5.4 // IsSimplyContiguous() -- 9.5.4
class IsSimplyContiguousHelper class IsSimplyContiguousHelper
: public AnyTraverse<IsSimplyContiguousHelper, std::optional<bool>> { : public AnyTraverse<IsSimplyContiguousHelper, std::optional<bool>> {
public: public:
using Result = std::optional<bool>; // tri-state using Result = std::optional<bool>; // tri-state
using Base = AnyTraverse<IsSimplyContiguousHelper, Result>; using Base = AnyTraverse<IsSimplyContiguousHelper, Result>;
explicit IsSimplyContiguousHelper(const IntrinsicProcTable &t) explicit IsSimplyContiguousHelper(const IntrinsicProcTable &t)
: Base{*this}, table_{t} {} : Base{*this}, table_{t} {}
using Base::operator(); using Base::operator();
Result operator()(const semantics::Symbol &symbol) const { Result operator()(const semantics::Symbol &symbol) const {
@ -303,7 +305,7 @@ public:
Result operator()(const ComplexPart &) const { return false; } Result operator()(const ComplexPart &) const { return false; }
Result operator()(const Substring &) const { return false; } Result operator()(const Substring &) const { return false; }
template<typename T> Result operator()(const FunctionRef<T> &x) const { template <typename T> Result operator()(const FunctionRef<T> &x) const {
if (auto chars{ if (auto chars{
characteristics::Procedure::Characterize(x.proc(), table_)}) { characteristics::Procedure::Characterize(x.proc(), table_)}) {
if (chars->functionResult) { if (chars->functionResult) {
@ -347,17 +349,17 @@ private:
const IntrinsicProcTable &table_; const IntrinsicProcTable &table_;
}; };
template<typename A> template <typename A>
bool IsSimplyContiguous(const A &x, const IntrinsicProcTable &table) { bool IsSimplyContiguous(const A &x, const IntrinsicProcTable &table) {
if (IsVariable(x)) { if (IsVariable(x)) {
auto known{IsSimplyContiguousHelper{table}(x)}; auto known{IsSimplyContiguousHelper{table}(x)};
return known && *known; return known && *known;
} else { } else {
return true; // not a variable return true; // not a variable
} }
} }
template bool IsSimplyContiguous( template bool IsSimplyContiguous(
const Expr<SomeType> &, const IntrinsicProcTable &); const Expr<SomeType> &, const IntrinsicProcTable &);
} } // namespace Fortran::evaluate

View File

@ -51,4 +51,4 @@ void FoldingContext::EndImpliedDo(parser::CharBlock name) {
impliedDos_.erase(iter); impliedDos_.erase(iter);
} }
} }
} } // namespace Fortran::evaluate

View File

@ -11,7 +11,7 @@
namespace Fortran::evaluate::value { namespace Fortran::evaluate::value {
template<typename R> template <typename R>
ValueWithRealFlags<Complex<R>> Complex<R>::Add( ValueWithRealFlags<Complex<R>> Complex<R>::Add(
const Complex &that, Rounding rounding) const { const Complex &that, Rounding rounding) const {
RealFlags flags; RealFlags flags;
@ -20,7 +20,7 @@ ValueWithRealFlags<Complex<R>> Complex<R>::Add(
return {Complex{reSum, imSum}, flags}; return {Complex{reSum, imSum}, flags};
} }
template<typename R> template <typename R>
ValueWithRealFlags<Complex<R>> Complex<R>::Subtract( ValueWithRealFlags<Complex<R>> Complex<R>::Subtract(
const Complex &that, Rounding rounding) const { const Complex &that, Rounding rounding) const {
RealFlags flags; RealFlags flags;
@ -29,7 +29,7 @@ ValueWithRealFlags<Complex<R>> Complex<R>::Subtract(
return {Complex{reDiff, imDiff}, flags}; return {Complex{reDiff, imDiff}, flags};
} }
template<typename R> template <typename R>
ValueWithRealFlags<Complex<R>> Complex<R>::Multiply( ValueWithRealFlags<Complex<R>> Complex<R>::Multiply(
const Complex &that, Rounding rounding) const { const Complex &that, Rounding rounding) const {
// (a + ib)*(c + id) -> ac - bd + i(ad + bc) // (a + ib)*(c + id) -> ac - bd + i(ad + bc)
@ -43,14 +43,14 @@ ValueWithRealFlags<Complex<R>> Complex<R>::Multiply(
return {Complex{acbd, adbc}, flags}; return {Complex{acbd, adbc}, flags};
} }
template<typename R> template <typename R>
ValueWithRealFlags<Complex<R>> Complex<R>::Divide( ValueWithRealFlags<Complex<R>> Complex<R>::Divide(
const Complex &that, Rounding rounding) const { const Complex &that, Rounding rounding) const {
// (a + ib)/(c + id) -> [(a+ib)*(c-id)] / [(c+id)*(c-id)] // (a + ib)/(c + id) -> [(a+ib)*(c-id)] / [(c+id)*(c-id)]
// -> [ac+bd+i(bc-ad)] / (cc+dd) // -> [ac+bd+i(bc-ad)] / (cc+dd)
// -> ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) // -> ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
// but to avoid overflows, scale by d/c if c>=d, else c/d // but to avoid overflows, scale by d/c if c>=d, else c/d
Part scale; // <= 1.0 Part scale; // <= 1.0
RealFlags flags; RealFlags flags;
bool cGEd{that.re_.ABS().Compare(that.im_.ABS()) != Relation::Less}; bool cGEd{that.re_.ABS().Compare(that.im_.ABS()) != Relation::Less};
if (cGEd) { if (cGEd) {
@ -81,7 +81,7 @@ ValueWithRealFlags<Complex<R>> Complex<R>::Divide(
return {Complex{re, im}, flags}; return {Complex{re, im}, flags};
} }
template<typename R> std::string Complex<R>::DumpHexadecimal() const { template <typename R> std::string Complex<R>::DumpHexadecimal() const {
std::string result{'('}; std::string result{'('};
result += re_.DumpHexadecimal(); result += re_.DumpHexadecimal();
result += ','; result += ',';
@ -90,7 +90,7 @@ template<typename R> std::string Complex<R>::DumpHexadecimal() const {
return result; return result;
} }
template<typename R> template <typename R>
llvm::raw_ostream &Complex<R>::AsFortran(llvm::raw_ostream &o, int kind) const { llvm::raw_ostream &Complex<R>::AsFortran(llvm::raw_ostream &o, int kind) const {
re_.AsFortran(o << '(', kind); re_.AsFortran(o << '(', kind);
im_.AsFortran(o << ',', kind); im_.AsFortran(o << ',', kind);
@ -103,4 +103,4 @@ template class Complex<Real<Integer<32>, 24>>;
template class Complex<Real<Integer<64>, 53>>; template class Complex<Real<Integer<64>, 53>>;
template class Complex<Real<Integer<80>, 64>>; template class Complex<Real<Integer<80>, 64>>;
template class Complex<Real<Integer<128>, 113>>; template class Complex<Real<Integer<128>, 113>>;
} } // namespace Fortran::evaluate::value

View File

@ -24,10 +24,10 @@ std::size_t TotalElementCount(const ConstantSubscripts &shape) {
} }
ConstantBounds::ConstantBounds(const ConstantSubscripts &shape) ConstantBounds::ConstantBounds(const ConstantSubscripts &shape)
: shape_(shape), lbounds_(shape_.size(), 1) {} : shape_(shape), lbounds_(shape_.size(), 1) {}
ConstantBounds::ConstantBounds(ConstantSubscripts &&shape) ConstantBounds::ConstantBounds(ConstantSubscripts &&shape)
: shape_(std::move(shape)), lbounds_(shape_.size(), 1) {} : shape_(std::move(shape)), lbounds_(shape_.size(), 1) {}
ConstantBounds::~ConstantBounds() = default; ConstantBounds::~ConstantBounds() = default;
@ -71,7 +71,7 @@ bool ConstantBounds::IncrementSubscripts(
indices[k] = lb; indices[k] = lb;
} }
} }
return false; // all done return false; // all done
} }
std::optional<std::vector<int>> ValidateDimensionOrder( std::optional<std::vector<int>> ValidateDimensionOrder(
@ -102,22 +102,22 @@ bool IsValidShape(const ConstantSubscripts &shape) {
return shape.size() <= common::maxRank; return shape.size() <= common::maxRank;
} }
template<typename RESULT, typename ELEMENT> template <typename RESULT, typename ELEMENT>
ConstantBase<RESULT, ELEMENT>::ConstantBase( ConstantBase<RESULT, ELEMENT>::ConstantBase(
std::vector<Element> &&x, ConstantSubscripts &&sh, Result res) std::vector<Element> &&x, ConstantSubscripts &&sh, Result res)
: ConstantBounds(std::move(sh)), result_{res}, values_(std::move(x)) { : ConstantBounds(std::move(sh)), result_{res}, values_(std::move(x)) {
CHECK(size() == TotalElementCount(shape())); CHECK(size() == TotalElementCount(shape()));
} }
template<typename RESULT, typename ELEMENT> template <typename RESULT, typename ELEMENT>
ConstantBase<RESULT, ELEMENT>::~ConstantBase() {} ConstantBase<RESULT, ELEMENT>::~ConstantBase() {}
template<typename RESULT, typename ELEMENT> template <typename RESULT, typename ELEMENT>
bool ConstantBase<RESULT, ELEMENT>::operator==(const ConstantBase &that) const { bool ConstantBase<RESULT, ELEMENT>::operator==(const ConstantBase &that) const {
return shape() == that.shape() && values_ == that.values_; return shape() == that.shape() && values_ == that.values_;
} }
template<typename RESULT, typename ELEMENT> template <typename RESULT, typename ELEMENT>
auto ConstantBase<RESULT, ELEMENT>::Reshape( auto ConstantBase<RESULT, ELEMENT>::Reshape(
const ConstantSubscripts &dims) const -> std::vector<Element> { const ConstantSubscripts &dims) const -> std::vector<Element> {
std::size_t n{TotalElementCount(dims)}; std::size_t n{TotalElementCount(dims)};
@ -133,7 +133,7 @@ auto ConstantBase<RESULT, ELEMENT>::Reshape(
return elements; return elements;
} }
template<typename RESULT, typename ELEMENT> template <typename RESULT, typename ELEMENT>
std::size_t ConstantBase<RESULT, ELEMENT>::CopyFrom( std::size_t ConstantBase<RESULT, ELEMENT>::CopyFrom(
const ConstantBase<RESULT, ELEMENT> &source, std::size_t count, const ConstantBase<RESULT, ELEMENT> &source, std::size_t count,
ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) { ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) {
@ -149,37 +149,37 @@ std::size_t ConstantBase<RESULT, ELEMENT>::CopyFrom(
return copied; return copied;
} }
template<typename T> template <typename T>
auto Constant<T>::At(const ConstantSubscripts &index) const -> Element { auto Constant<T>::At(const ConstantSubscripts &index) const -> Element {
return Base::values_.at(Base::SubscriptsToOffset(index)); return Base::values_.at(Base::SubscriptsToOffset(index));
} }
template<typename T> template <typename T>
auto Constant<T>::Reshape(ConstantSubscripts &&dims) const -> Constant { auto Constant<T>::Reshape(ConstantSubscripts &&dims) const -> Constant {
return {Base::Reshape(dims), std::move(dims)}; return {Base::Reshape(dims), std::move(dims)};
} }
template<typename T> template <typename T>
std::size_t Constant<T>::CopyFrom(const Constant<T> &source, std::size_t count, std::size_t Constant<T>::CopyFrom(const Constant<T> &source, std::size_t count,
ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) { ConstantSubscripts &resultSubscripts, const std::vector<int> *dimOrder) {
return Base::CopyFrom(source, count, resultSubscripts, dimOrder); return Base::CopyFrom(source, count, resultSubscripts, dimOrder);
} }
// Constant<Type<TypeCategory::Character, KIND> specializations // Constant<Type<TypeCategory::Character, KIND> specializations
template<int KIND> template <int KIND>
Constant<Type<TypeCategory::Character, KIND>>::Constant( Constant<Type<TypeCategory::Character, KIND>>::Constant(
const Scalar<Result> &str) const Scalar<Result> &str)
: values_{str}, length_{static_cast<ConstantSubscript>(values_.size())} {} : values_{str}, length_{static_cast<ConstantSubscript>(values_.size())} {}
template<int KIND> template <int KIND>
Constant<Type<TypeCategory::Character, KIND>>::Constant(Scalar<Result> &&str) Constant<Type<TypeCategory::Character, KIND>>::Constant(Scalar<Result> &&str)
: values_{std::move(str)}, length_{static_cast<ConstantSubscript>( : values_{std::move(str)}, length_{static_cast<ConstantSubscript>(
values_.size())} {} values_.size())} {}
template<int KIND> template <int KIND>
Constant<Type<TypeCategory::Character, KIND>>::Constant(ConstantSubscript len, Constant<Type<TypeCategory::Character, KIND>>::Constant(ConstantSubscript len,
std::vector<Scalar<Result>> &&strings, ConstantSubscripts &&sh) std::vector<Scalar<Result>> &&strings, ConstantSubscripts &&sh)
: ConstantBounds(std::move(sh)), length_{len} { : ConstantBounds(std::move(sh)), length_{len} {
CHECK(strings.size() == TotalElementCount(shape())); CHECK(strings.size() == TotalElementCount(shape()));
values_.assign(strings.size() * length_, values_.assign(strings.size() * length_,
static_cast<typename Scalar<Result>::value_type>(' ')); static_cast<typename Scalar<Result>::value_type>(' '));
@ -196,14 +196,15 @@ Constant<Type<TypeCategory::Character, KIND>>::Constant(ConstantSubscript len,
CHECK(at == static_cast<ConstantSubscript>(values_.size())); CHECK(at == static_cast<ConstantSubscript>(values_.size()));
} }
template<int KIND> Constant<Type<TypeCategory::Character, KIND>>::~Constant() {} template <int KIND>
Constant<Type<TypeCategory::Character, KIND>>::~Constant() {}
template<int KIND> template <int KIND>
bool Constant<Type<TypeCategory::Character, KIND>>::empty() const { bool Constant<Type<TypeCategory::Character, KIND>>::empty() const {
return size() == 0; return size() == 0;
} }
template<int KIND> template <int KIND>
std::size_t Constant<Type<TypeCategory::Character, KIND>>::size() const { std::size_t Constant<Type<TypeCategory::Character, KIND>>::size() const {
if (length_ == 0) { if (length_ == 0) {
return TotalElementCount(shape()); return TotalElementCount(shape());
@ -212,14 +213,14 @@ std::size_t Constant<Type<TypeCategory::Character, KIND>>::size() const {
} }
} }
template<int KIND> template <int KIND>
auto Constant<Type<TypeCategory::Character, KIND>>::At( auto Constant<Type<TypeCategory::Character, KIND>>::At(
const ConstantSubscripts &index) const -> Scalar<Result> { const ConstantSubscripts &index) const -> Scalar<Result> {
auto offset{SubscriptsToOffset(index)}; auto offset{SubscriptsToOffset(index)};
return values_.substr(offset * length_, length_); return values_.substr(offset * length_, length_);
} }
template<int KIND> template <int KIND>
auto Constant<Type<TypeCategory::Character, KIND>>::Reshape( auto Constant<Type<TypeCategory::Character, KIND>>::Reshape(
ConstantSubscripts &&dims) const -> Constant<Result> { ConstantSubscripts &&dims) const -> Constant<Result> {
std::size_t n{TotalElementCount(dims)}; std::size_t n{TotalElementCount(dims)};
@ -230,14 +231,14 @@ auto Constant<Type<TypeCategory::Character, KIND>>::Reshape(
while (n-- > 0) { while (n-- > 0) {
elements.push_back(values_.substr(at, length_)); elements.push_back(values_.substr(at, length_));
at += length_; at += length_;
if (at == limit) { // subtle: at > limit somehow? substr() will catch it if (at == limit) { // subtle: at > limit somehow? substr() will catch it
at = 0; at = 0;
} }
} }
return {length_, std::move(elements), std::move(dims)}; return {length_, std::move(elements), std::move(dims)};
} }
template<int KIND> template <int KIND>
std::size_t Constant<Type<TypeCategory::Character, KIND>>::CopyFrom( std::size_t Constant<Type<TypeCategory::Character, KIND>>::CopyFrom(
const Constant<Type<TypeCategory::Character, KIND>> &source, const Constant<Type<TypeCategory::Character, KIND>> &source,
std::size_t count, ConstantSubscripts &resultSubscripts, std::size_t count, ConstantSubscripts &resultSubscripts,
@ -260,14 +261,14 @@ std::size_t Constant<Type<TypeCategory::Character, KIND>>::CopyFrom(
// Constant<SomeDerived> specialization // Constant<SomeDerived> specialization
Constant<SomeDerived>::Constant(const StructureConstructor &x) Constant<SomeDerived>::Constant(const StructureConstructor &x)
: Base{x.values(), Result{x.derivedTypeSpec()}} {} : Base{x.values(), Result{x.derivedTypeSpec()}} {}
Constant<SomeDerived>::Constant(StructureConstructor &&x) Constant<SomeDerived>::Constant(StructureConstructor &&x)
: Base{std::move(x.values()), Result{x.derivedTypeSpec()}} {} : Base{std::move(x.values()), Result{x.derivedTypeSpec()}} {}
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec, Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
std::vector<StructureConstructorValues> &&x, ConstantSubscripts &&s) std::vector<StructureConstructorValues> &&x, ConstantSubscripts &&s)
: Base{std::move(x), std::move(s), Result{spec}} {} : Base{std::move(x), std::move(s), Result{spec}} {}
static std::vector<StructureConstructorValues> AcquireValues( static std::vector<StructureConstructorValues> AcquireValues(
std::vector<StructureConstructor> &&x) { std::vector<StructureConstructor> &&x) {
@ -280,7 +281,7 @@ static std::vector<StructureConstructorValues> AcquireValues(
Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec, Constant<SomeDerived>::Constant(const semantics::DerivedTypeSpec &spec,
std::vector<StructureConstructor> &&x, ConstantSubscripts &&shape) std::vector<StructureConstructor> &&x, ConstantSubscripts &&shape)
: Base{AcquireValues(std::move(x)), std::move(shape), Result{spec}} {} : Base{AcquireValues(std::move(x)), std::move(shape), Result{spec}} {}
std::optional<StructureConstructor> std::optional<StructureConstructor>
Constant<SomeDerived>::GetScalarValue() const { Constant<SomeDerived>::GetScalarValue() const {
@ -308,4 +309,4 @@ std::size_t Constant<SomeDerived>::CopyFrom(const Constant<SomeDerived> &source,
} }
INSTANTIATE_CONSTANT_TEMPLATES INSTANTIATE_CONSTANT_TEMPLATES
} } // namespace Fortran::evaluate

View File

@ -21,7 +21,7 @@ using namespace Fortran::parser::literals;
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> template <int KIND>
std::optional<Expr<SubscriptInteger>> std::optional<Expr<SubscriptInteger>>
Expr<Type<TypeCategory::Character, KIND>>::LEN() const { Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
using T = std::optional<Expr<SubscriptInteger>>; using T = std::optional<Expr<SubscriptInteger>>;
@ -63,18 +63,18 @@ Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
Expr<SomeType>::~Expr() = default; Expr<SomeType>::~Expr() = default;
#if defined(__APPLE__) && defined(__GNUC__) #if defined(__APPLE__) && defined(__GNUC__)
template<typename A> template <typename A>
typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() { typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() {
return *static_cast<Derived *>(this); return *static_cast<Derived *>(this);
} }
template<typename A> template <typename A>
const typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() const { const typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() const {
return *static_cast<const Derived *>(this); return *static_cast<const Derived *>(this);
} }
#endif #endif
template<typename A> template <typename A>
std::optional<DynamicType> ExpressionBase<A>::GetType() const { std::optional<DynamicType> ExpressionBase<A>::GetType() const {
if constexpr (IsLengthlessIntrinsicType<Result>) { if constexpr (IsLengthlessIntrinsicType<Result>) {
return Result::GetType(); return Result::GetType();
@ -84,13 +84,13 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
if constexpr (!common::HasMember<decltype(x), TypelessExpression>) { if constexpr (!common::HasMember<decltype(x), TypelessExpression>) {
return x.GetType(); return x.GetType();
} }
return std::nullopt; // w/o "else" to dodge bogus g++ 8.1 warning return std::nullopt; // w/o "else" to dodge bogus g++ 8.1 warning
}, },
derived().u); derived().u);
} }
} }
template<typename A> int ExpressionBase<A>::Rank() const { template <typename A> int ExpressionBase<A>::Rank() const {
return std::visit( return std::visit(
[](const auto &x) { [](const auto &x) {
if constexpr (common::HasMember<decltype(x), TypelessExpression>) { if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
@ -108,26 +108,26 @@ bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const {
return name == that.name; return name == that.name;
} }
template<typename T> template <typename T>
bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const { bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const {
return name_ == that.name_ && lower_ == that.lower_ && return name_ == that.name_ && lower_ == that.lower_ &&
upper_ == that.upper_ && stride_ == that.stride_ && upper_ == that.upper_ && stride_ == that.stride_ &&
values_ == that.values_; values_ == that.values_;
} }
template<typename T> template <typename T>
bool ArrayConstructorValue<T>::operator==( bool ArrayConstructorValue<T>::operator==(
const ArrayConstructorValue<T> &that) const { const ArrayConstructorValue<T> &that) const {
return u == that.u; return u == that.u;
} }
template<typename R> template <typename R>
bool ArrayConstructorValues<R>::operator==( bool ArrayConstructorValues<R>::operator==(
const ArrayConstructorValues<R> &that) const { const ArrayConstructorValues<R> &that) const {
return values_ == that.values_; return values_ == that.values_;
} }
template<int KIND> template <int KIND>
bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==( bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==(
const ArrayConstructor &that) const { const ArrayConstructor &that) const {
return length_ == that.length_ && return length_ == that.length_ &&
@ -144,10 +144,10 @@ bool ArrayConstructor<SomeDerived>::operator==(
StructureConstructor::StructureConstructor( StructureConstructor::StructureConstructor(
const semantics::DerivedTypeSpec &spec, const semantics::DerivedTypeSpec &spec,
const StructureConstructorValues &values) const StructureConstructorValues &values)
: result_{spec}, values_{values} {} : result_{spec}, values_{values} {}
StructureConstructor::StructureConstructor( StructureConstructor::StructureConstructor(
const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values) const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values)
: result_{spec}, values_{std::move(values)} {} : result_{spec}, values_{std::move(values)} {}
bool StructureConstructor::operator==(const StructureConstructor &that) const { bool StructureConstructor::operator==(const StructureConstructor &that) const {
return result_ == that.result_ && values_ == that.values_; return result_ == that.result_ && values_ == that.values_;
@ -157,37 +157,37 @@ bool Relational<SomeType>::operator==(const Relational<SomeType> &that) const {
return u == that.u; return u == that.u;
} }
template<int KIND> template <int KIND>
bool Expr<Type<TypeCategory::Integer, KIND>>::operator==( bool Expr<Type<TypeCategory::Integer, KIND>>::operator==(
const Expr<Type<TypeCategory::Integer, KIND>> &that) const { const Expr<Type<TypeCategory::Integer, KIND>> &that) const {
return u == that.u; return u == that.u;
} }
template<int KIND> template <int KIND>
bool Expr<Type<TypeCategory::Real, KIND>>::operator==( bool Expr<Type<TypeCategory::Real, KIND>>::operator==(
const Expr<Type<TypeCategory::Real, KIND>> &that) const { const Expr<Type<TypeCategory::Real, KIND>> &that) const {
return u == that.u; return u == that.u;
} }
template<int KIND> template <int KIND>
bool Expr<Type<TypeCategory::Complex, KIND>>::operator==( bool Expr<Type<TypeCategory::Complex, KIND>>::operator==(
const Expr<Type<TypeCategory::Complex, KIND>> &that) const { const Expr<Type<TypeCategory::Complex, KIND>> &that) const {
return u == that.u; return u == that.u;
} }
template<int KIND> template <int KIND>
bool Expr<Type<TypeCategory::Logical, KIND>>::operator==( bool Expr<Type<TypeCategory::Logical, KIND>>::operator==(
const Expr<Type<TypeCategory::Logical, KIND>> &that) const { const Expr<Type<TypeCategory::Logical, KIND>> &that) const {
return u == that.u; return u == that.u;
} }
template<int KIND> template <int KIND>
bool Expr<Type<TypeCategory::Character, KIND>>::operator==( bool Expr<Type<TypeCategory::Character, KIND>>::operator==(
const Expr<Type<TypeCategory::Character, KIND>> &that) const { const Expr<Type<TypeCategory::Character, KIND>> &that) const {
return u == that.u; return u == that.u;
} }
template<TypeCategory CAT> template <TypeCategory CAT>
bool Expr<SomeKind<CAT>>::operator==(const Expr<SomeKind<CAT>> &that) const { bool Expr<SomeKind<CAT>>::operator==(const Expr<SomeKind<CAT>> &that) const {
return u == that.u; return u == that.u;
} }
@ -225,7 +225,7 @@ GenericExprWrapper::~GenericExprWrapper() {}
GenericAssignmentWrapper::~GenericAssignmentWrapper() {} GenericAssignmentWrapper::~GenericAssignmentWrapper() {}
template<TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const { template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
return std::visit( return std::visit(
[](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; }, [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
u); u);
@ -242,6 +242,6 @@ std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
} }
INSTANTIATE_EXPRESSION_TEMPLATES INSTANTIATE_EXPRESSION_TEMPLATES
} } // namespace Fortran::evaluate
DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper) DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper) DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)

View File

@ -10,7 +10,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Character, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Character, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FoldingContext &context,
FunctionRef<Type<TypeCategory::Character, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Character, KIND>> &&funcRef) {
@ -38,14 +38,14 @@ Expr<Type<TypeCategory::Character, KIND>> FoldIntrinsicFunction(
return FoldMINorMAX(context, std::move(funcRef), Ordering::Less); return FoldMINorMAX(context, std::move(funcRef), Ordering::Less);
} else if (name == "new_line") { } else if (name == "new_line") {
return Expr<T>{Constant<T>{CharacterUtils<KIND>::NEW_LINE()}}; return Expr<T>{Constant<T>{CharacterUtils<KIND>::NEW_LINE()}};
} else if (name == "repeat") { // not elemental } else if (name == "repeat") { // not elemental
if (auto scalars{GetScalarConstantArguments<T, SubscriptInteger>( if (auto scalars{GetScalarConstantArguments<T, SubscriptInteger>(
context, funcRef.arguments())}) { context, funcRef.arguments())}) {
return Expr<T>{Constant<T>{ return Expr<T>{Constant<T>{
CharacterUtils<KIND>::REPEAT(std::get<Scalar<T>>(*scalars), CharacterUtils<KIND>::REPEAT(std::get<Scalar<T>>(*scalars),
std::get<Scalar<SubscriptInteger>>(*scalars).ToInt64())}}; std::get<Scalar<SubscriptInteger>>(*scalars).ToInt64())}};
} }
} else if (name == "trim") { // not elemental } else if (name == "trim") { // not elemental
if (auto scalar{ if (auto scalar{
GetScalarConstantArguments<T>(context, funcRef.arguments())}) { GetScalarConstantArguments<T>(context, funcRef.arguments())}) {
return Expr<T>{Constant<T>{ return Expr<T>{Constant<T>{
@ -57,7 +57,7 @@ Expr<Type<TypeCategory::Character, KIND>> FoldIntrinsicFunction(
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Character, KIND>> FoldOperation( Expr<Type<TypeCategory::Character, KIND>> FoldOperation(
FoldingContext &context, Concat<KIND> &&x) { FoldingContext &context, Concat<KIND> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
@ -70,7 +70,7 @@ Expr<Type<TypeCategory::Character, KIND>> FoldOperation(
return Expr<Result>{std::move(x)}; return Expr<Result>{std::move(x)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Character, KIND>> FoldOperation( Expr<Type<TypeCategory::Character, KIND>> FoldOperation(
FoldingContext &context, SetLength<KIND> &&x) { FoldingContext &context, SetLength<KIND> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
@ -93,4 +93,4 @@ Expr<Type<TypeCategory::Character, KIND>> FoldOperation(
FOR_EACH_CHARACTER_KIND(template class ExpressionBase, ) FOR_EACH_CHARACTER_KIND(template class ExpressionBase, )
template class ExpressionBase<SomeCharacter>; template class ExpressionBase<SomeCharacter>;
} } // namespace Fortran::evaluate

View File

@ -10,7 +10,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FoldingContext &context,
FunctionRef<Type<TypeCategory::Complex, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Complex, KIND>> &&funcRef) {
@ -61,7 +61,7 @@ Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction(
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Complex, KIND>> FoldOperation( Expr<Type<TypeCategory::Complex, KIND>> FoldOperation(
FoldingContext &context, ComplexConstructor<KIND> &&x) { FoldingContext &context, ComplexConstructor<KIND> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
@ -77,4 +77,4 @@ Expr<Type<TypeCategory::Complex, KIND>> FoldOperation(
FOR_EACH_COMPLEX_KIND(template class ExpressionBase, ) FOR_EACH_COMPLEX_KIND(template class ExpressionBase, )
template class ExpressionBase<SomeComplex>; template class ExpressionBase<SomeComplex>;
} } // namespace Fortran::evaluate

View File

@ -45,7 +45,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
// Utilities // Utilities
template<typename T> class Folder { template <typename T> class Folder {
public: public:
explicit Folder(FoldingContext &c) : context_{c} {} explicit Folder(FoldingContext &c) : context_{c} {}
std::optional<Expr<T>> GetNamedConstantValue(const Symbol &); std::optional<Expr<T>> GetNamedConstantValue(const Symbol &);
@ -76,7 +76,7 @@ std::optional<Constant<SubscriptInteger>> GetConstantSubscript(
// specific type. // specific type.
// no-op base case // no-op base case
template<typename A> template <typename A>
common::IfNoLvalue<Expr<ResultType<A>>, A> FoldOperation( common::IfNoLvalue<Expr<ResultType<A>>, A> FoldOperation(
FoldingContext &, A &&x) { FoldingContext &, A &&x) {
static_assert(!std::is_same_v<A, Expr<ResultType<A>>>, static_assert(!std::is_same_v<A, Expr<ResultType<A>>>,
@ -94,36 +94,36 @@ DataRef FoldOperation(FoldingContext &, DataRef &&);
Substring FoldOperation(FoldingContext &, Substring &&); Substring FoldOperation(FoldingContext &, Substring &&);
ComplexPart FoldOperation(FoldingContext &, ComplexPart &&); ComplexPart FoldOperation(FoldingContext &, ComplexPart &&);
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, FunctionRef<T> &&); Expr<T> FoldOperation(FoldingContext &context, FunctionRef<T> &&);
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FunctionRef<Type<TypeCategory::Integer, KIND>> &&); FoldingContext &context, FunctionRef<Type<TypeCategory::Integer, KIND>> &&);
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FunctionRef<Type<TypeCategory::Real, KIND>> &&); FoldingContext &context, FunctionRef<Type<TypeCategory::Real, KIND>> &&);
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FunctionRef<Type<TypeCategory::Complex, KIND>> &&); FoldingContext &context, FunctionRef<Type<TypeCategory::Complex, KIND>> &&);
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FunctionRef<Type<TypeCategory::Logical, KIND>> &&); FoldingContext &context, FunctionRef<Type<TypeCategory::Logical, KIND>> &&);
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Designator<T> &&designator) { Expr<T> FoldOperation(FoldingContext &context, Designator<T> &&designator) {
return Folder<T>{context}.Folding(std::move(designator)); return Folder<T>{context}.Folding(std::move(designator));
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> FoldOperation( Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
FoldingContext &, TypeParamInquiry<KIND> &&); FoldingContext &, TypeParamInquiry<KIND> &&);
Expr<ImpliedDoIndex::Result> FoldOperation( Expr<ImpliedDoIndex::Result> FoldOperation(
FoldingContext &context, ImpliedDoIndex &&); FoldingContext &context, ImpliedDoIndex &&);
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &, ArrayConstructor<T> &&); Expr<T> FoldOperation(FoldingContext &, ArrayConstructor<T> &&);
Expr<SomeDerived> FoldOperation(FoldingContext &, StructureConstructor &&); Expr<SomeDerived> FoldOperation(FoldingContext &, StructureConstructor &&);
template<typename T> template <typename T>
std::optional<Expr<T>> Folder<T>::GetNamedConstantValue(const Symbol &symbol0) { std::optional<Expr<T>> Folder<T>::GetNamedConstantValue(const Symbol &symbol0) {
const Symbol &symbol{ResolveAssociations(symbol0)}; const Symbol &symbol{ResolveAssociations(symbol0)};
if (IsNamedConstant(symbol)) { if (IsNamedConstant(symbol)) {
@ -200,7 +200,7 @@ std::optional<Expr<T>> Folder<T>::GetNamedConstantValue(const Symbol &symbol0) {
return std::nullopt; return std::nullopt;
} }
template<typename T> template <typename T>
std::optional<Constant<T>> Folder<T>::GetFoldedNamedConstantValue( std::optional<Constant<T>> Folder<T>::GetFoldedNamedConstantValue(
const Symbol &symbol) { const Symbol &symbol) {
if (auto value{GetNamedConstantValue(symbol)}) { if (auto value{GetNamedConstantValue(symbol)}) {
@ -212,7 +212,7 @@ std::optional<Constant<T>> Folder<T>::GetFoldedNamedConstantValue(
return std::nullopt; return std::nullopt;
} }
template<typename T> template <typename T>
std::optional<Constant<T>> Folder<T>::Folding(ArrayRef &aRef) { std::optional<Constant<T>> Folder<T>::Folding(ArrayRef &aRef) {
std::vector<Constant<SubscriptInteger>> subscripts; std::vector<Constant<SubscriptInteger>> subscripts;
int dim{0}; int dim{0};
@ -233,7 +233,7 @@ std::optional<Constant<T>> Folder<T>::Folding(ArrayRef &aRef) {
} }
} }
template<typename T> template <typename T>
std::optional<Constant<T>> Folder<T>::ApplySubscripts(const Constant<T> &array, std::optional<Constant<T>> Folder<T>::ApplySubscripts(const Constant<T> &array,
const std::vector<Constant<SubscriptInteger>> &subscripts) { const std::vector<Constant<SubscriptInteger>> &subscripts) {
const auto &shape{array.shape()}; const auto &shape{array.shape()};
@ -293,7 +293,7 @@ std::optional<Constant<T>> Folder<T>::ApplySubscripts(const Constant<T> &array,
} }
} }
template<typename T> template <typename T>
std::optional<Constant<T>> Folder<T>::ApplyComponent( std::optional<Constant<T>> Folder<T>::ApplyComponent(
Constant<SomeDerived> &&structures, const Symbol &component, Constant<SomeDerived> &&structures, const Symbol &component,
const std::vector<Constant<SubscriptInteger>> *subscripts) { const std::vector<Constant<SubscriptInteger>> *subscripts) {
@ -351,7 +351,7 @@ std::optional<Constant<T>> Folder<T>::ApplyComponent(
return std::nullopt; return std::nullopt;
} }
template<typename T> template <typename T>
std::optional<Constant<T>> Folder<T>::GetConstantComponent(Component &component, std::optional<Constant<T>> Folder<T>::GetConstantComponent(Component &component,
const std::vector<Constant<SubscriptInteger>> *subscripts) { const std::vector<Constant<SubscriptInteger>> *subscripts) {
if (std::optional<Constant<SomeDerived>> structures{std::visit( if (std::optional<Constant<SomeDerived>> structures{std::visit(
@ -378,7 +378,7 @@ std::optional<Constant<T>> Folder<T>::GetConstantComponent(Component &component,
} }
} }
template<typename T> Expr<T> Folder<T>::Folding(Designator<T> &&designator) { template <typename T> Expr<T> Folder<T>::Folding(Designator<T> &&designator) {
if constexpr (T::category == TypeCategory::Character) { if constexpr (T::category == TypeCategory::Character) {
if (auto *substring{common::Unwrap<Substring>(designator.u)}) { if (auto *substring{common::Unwrap<Substring>(designator.u)}) {
if (std::optional<Expr<SomeCharacter>> folded{ if (std::optional<Expr<SomeCharacter>> folded{
@ -428,7 +428,7 @@ template<typename T> Expr<T> Folder<T>::Folding(Designator<T> &&designator) {
// Apply type conversion and re-folding if necessary. // Apply type conversion and re-folding if necessary.
// This is where BOZ arguments are converted. // This is where BOZ arguments are converted.
template<typename T> template <typename T>
Constant<T> *Folder<T>::Folding(std::optional<ActualArgument> &arg) { Constant<T> *Folder<T>::Folding(std::optional<ActualArgument> &arg) {
if (auto *expr{UnwrapExpr<Expr<SomeType>>(arg)}) { if (auto *expr{UnwrapExpr<Expr<SomeType>>(arg)}) {
if (!UnwrapExpr<Expr<T>>(*expr)) { if (!UnwrapExpr<Expr<T>>(*expr)) {
@ -441,12 +441,12 @@ Constant<T> *Folder<T>::Folding(std::optional<ActualArgument> &arg) {
return nullptr; return nullptr;
} }
template<typename... A, std::size_t... I> template <typename... A, std::size_t... I>
std::optional<std::tuple<const Constant<A> *...>> GetConstantArgumentsHelper( std::optional<std::tuple<const Constant<A> *...>> GetConstantArgumentsHelper(
FoldingContext &context, ActualArguments &arguments, FoldingContext &context, ActualArguments &arguments,
std::index_sequence<I...>) { std::index_sequence<I...>) {
static_assert( static_assert(
(... && IsSpecificIntrinsicType<A>)); // TODO derived types for MERGE? (... && IsSpecificIntrinsicType<A>)); // TODO derived types for MERGE?
static_assert(sizeof...(A) > 0); static_assert(sizeof...(A) > 0);
std::tuple<const Constant<A> *...> args{ std::tuple<const Constant<A> *...> args{
Folder<A>{context}.Folding(arguments.at(I))...}; Folder<A>{context}.Folding(arguments.at(I))...};
@ -457,14 +457,14 @@ std::optional<std::tuple<const Constant<A> *...>> GetConstantArgumentsHelper(
} }
} }
template<typename... A> template <typename... A>
std::optional<std::tuple<const Constant<A> *...>> GetConstantArguments( std::optional<std::tuple<const Constant<A> *...>> GetConstantArguments(
FoldingContext &context, ActualArguments &args) { FoldingContext &context, ActualArguments &args) {
return GetConstantArgumentsHelper<A...>( return GetConstantArgumentsHelper<A...>(
context, args, std::index_sequence_for<A...>{}); context, args, std::index_sequence_for<A...>{});
} }
template<typename... A, std::size_t... I> template <typename... A, std::size_t... I>
std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArgumentsHelper( std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArgumentsHelper(
FoldingContext &context, ActualArguments &args, std::index_sequence<I...>) { FoldingContext &context, ActualArguments &args, std::index_sequence<I...>) {
if (auto constArgs{GetConstantArguments<A...>(context, args)}) { if (auto constArgs{GetConstantArguments<A...>(context, args)}) {
@ -475,7 +475,7 @@ std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArgumentsHelper(
} }
} }
template<typename... A> template <typename... A>
std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArguments( std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArguments(
FoldingContext &context, ActualArguments &args) { FoldingContext &context, ActualArguments &args) {
return GetScalarConstantArgumentsHelper<A...>( return GetScalarConstantArgumentsHelper<A...>(
@ -486,13 +486,13 @@ std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArguments(
// Define callable types used in a common utility that // Define callable types used in a common utility that
// takes care of array and cast/conversion aspects for elemental intrinsics // takes care of array and cast/conversion aspects for elemental intrinsics
template<typename TR, typename... TArgs> template <typename TR, typename... TArgs>
using ScalarFunc = std::function<Scalar<TR>(const Scalar<TArgs> &...)>; using ScalarFunc = std::function<Scalar<TR>(const Scalar<TArgs> &...)>;
template<typename TR, typename... TArgs> template <typename TR, typename... TArgs>
using ScalarFuncWithContext = using ScalarFuncWithContext =
std::function<Scalar<TR>(FoldingContext &, const Scalar<TArgs> &...)>; std::function<Scalar<TR>(FoldingContext &, const Scalar<TArgs> &...)>;
template<template<typename, typename...> typename WrapperType, typename TR, template <template <typename, typename...> typename WrapperType, typename TR,
typename... TA, std::size_t... I> typename... TA, std::size_t... I>
Expr<TR> FoldElementalIntrinsicHelper(FoldingContext &context, Expr<TR> FoldElementalIntrinsicHelper(FoldingContext &context,
FunctionRef<TR> &&funcRef, WrapperType<TR, TA...> func, FunctionRef<TR> &&funcRef, WrapperType<TR, TA...> func,
@ -556,13 +556,13 @@ Expr<TR> FoldElementalIntrinsicHelper(FoldingContext &context,
return Expr<TR>{std::move(funcRef)}; return Expr<TR>{std::move(funcRef)};
} }
template<typename TR, typename... TA> template <typename TR, typename... TA>
Expr<TR> FoldElementalIntrinsic(FoldingContext &context, Expr<TR> FoldElementalIntrinsic(FoldingContext &context,
FunctionRef<TR> &&funcRef, ScalarFunc<TR, TA...> func) { FunctionRef<TR> &&funcRef, ScalarFunc<TR, TA...> func) {
return FoldElementalIntrinsicHelper<ScalarFunc, TR, TA...>( return FoldElementalIntrinsicHelper<ScalarFunc, TR, TA...>(
context, std::move(funcRef), func, std::index_sequence_for<TA...>{}); context, std::move(funcRef), func, std::index_sequence_for<TA...>{});
} }
template<typename TR, typename... TA> template <typename TR, typename... TA>
Expr<TR> FoldElementalIntrinsic(FoldingContext &context, Expr<TR> FoldElementalIntrinsic(FoldingContext &context,
FunctionRef<TR> &&funcRef, ScalarFuncWithContext<TR, TA...> func) { FunctionRef<TR> &&funcRef, ScalarFuncWithContext<TR, TA...> func) {
return FoldElementalIntrinsicHelper<ScalarFuncWithContext, TR, TA...>( return FoldElementalIntrinsicHelper<ScalarFuncWithContext, TR, TA...>(
@ -573,7 +573,7 @@ std::optional<std::int64_t> GetInt64Arg(const std::optional<ActualArgument> &);
std::optional<std::int64_t> GetInt64ArgOr( std::optional<std::int64_t> GetInt64ArgOr(
const std::optional<ActualArgument> &, std::int64_t defaultValue); const std::optional<ActualArgument> &, std::int64_t defaultValue);
template<typename A, typename B> template <typename A, typename B>
std::optional<std::vector<A>> GetIntegerVector(const B &x) { std::optional<std::vector<A>> GetIntegerVector(const B &x) {
static_assert(std::is_integral_v<A>); static_assert(std::is_integral_v<A>);
if (const auto *someInteger{UnwrapExpr<Expr<SomeInteger>>(x)}) { if (const auto *someInteger{UnwrapExpr<Expr<SomeInteger>>(x)}) {
@ -600,14 +600,14 @@ std::optional<std::vector<A>> GetIntegerVector(const B &x) {
// into an intrinsic with the same characteristic but the "invalid" name. // into an intrinsic with the same characteristic but the "invalid" name.
// This to prevent generating warnings over and over if the expression // This to prevent generating warnings over and over if the expression
// gets re-folded. // gets re-folded.
template<typename T> Expr<T> MakeInvalidIntrinsic(FunctionRef<T> &&funcRef) { template <typename T> Expr<T> MakeInvalidIntrinsic(FunctionRef<T> &&funcRef) {
SpecificIntrinsic invalid{std::get<SpecificIntrinsic>(funcRef.proc().u)}; SpecificIntrinsic invalid{std::get<SpecificIntrinsic>(funcRef.proc().u)};
invalid.name = "(invalid intrinsic function call)"; invalid.name = "(invalid intrinsic function call)";
return Expr<T>{FunctionRef<T>{ProcedureDesignator{std::move(invalid)}, return Expr<T>{FunctionRef<T>{ProcedureDesignator{std::move(invalid)},
ActualArguments{ActualArgument{AsGenericExpr(std::move(funcRef))}}}}; ActualArguments{ActualArgument{AsGenericExpr(std::move(funcRef))}}}};
} }
template<typename T> Expr<T> Folder<T>::Reshape(FunctionRef<T> &&funcRef) { template <typename T> Expr<T> Folder<T>::Reshape(FunctionRef<T> &&funcRef) {
auto args{funcRef.arguments()}; auto args{funcRef.arguments()};
CHECK(args.size() == 4); CHECK(args.size() == 4);
const auto *source{UnwrapConstantValue<T>(args[0])}; const auto *source{UnwrapConstantValue<T>(args[0])};
@ -616,7 +616,7 @@ template<typename T> Expr<T> Folder<T>::Reshape(FunctionRef<T> &&funcRef) {
GetIntegerVector<ConstantSubscript>(args[1])}; GetIntegerVector<ConstantSubscript>(args[1])};
std::optional<std::vector<int>> order{GetIntegerVector<int>(args[3])}; std::optional<std::vector<int>> order{GetIntegerVector<int>(args[3])};
if (!source || !shape || (args[2] && !pad) || (args[3] && !order)) { if (!source || !shape || (args[2] && !pad) || (args[3] && !order)) {
return Expr<T>{std::move(funcRef)}; // Non-constant arguments return Expr<T>{std::move(funcRef)}; // Non-constant arguments
} else if (!IsValidShape(shape.value())) { } else if (!IsValidShape(shape.value())) {
context_.messages().Say("Invalid SHAPE in RESHAPE"_en_US); context_.messages().Say("Invalid SHAPE in RESHAPE"_en_US);
} else { } else {
@ -652,7 +652,7 @@ template<typename T> Expr<T> Folder<T>::Reshape(FunctionRef<T> &&funcRef) {
return MakeInvalidIntrinsic(std::move(funcRef)); return MakeInvalidIntrinsic(std::move(funcRef));
} }
template<typename T> template <typename T>
Expr<T> FoldMINorMAX( Expr<T> FoldMINorMAX(
FoldingContext &context, FunctionRef<T> &&funcRef, Ordering order) { FoldingContext &context, FunctionRef<T> &&funcRef, Ordering order) {
std::vector<Constant<T> *> constantArgs; std::vector<Constant<T> *> constantArgs;
@ -672,7 +672,7 @@ Expr<T> FoldMINorMAX(
return result; return result;
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, FunctionRef<T> &&funcRef) { Expr<T> FoldOperation(FoldingContext &context, FunctionRef<T> &&funcRef) {
ActualArguments &args{funcRef.arguments()}; ActualArguments &args{funcRef.arguments()};
for (std::optional<ActualArgument> &arg : args) { for (std::optional<ActualArgument> &arg : args) {
@ -693,7 +693,7 @@ Expr<T> FoldOperation(FoldingContext &context, FunctionRef<T> &&funcRef) {
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<typename T> template <typename T>
Expr<T> FoldMerge(FoldingContext &context, FunctionRef<T> &&funcRef) { Expr<T> FoldMerge(FoldingContext &context, FunctionRef<T> &&funcRef) {
return FoldElementalIntrinsic<T, T, T, LogicalResult>(context, return FoldElementalIntrinsic<T, T, T, LogicalResult>(context,
std::move(funcRef), std::move(funcRef),
@ -707,7 +707,7 @@ Expr<T> FoldMerge(FoldingContext &context, FunctionRef<T> &&funcRef) {
Expr<ImpliedDoIndex::Result> FoldOperation(FoldingContext &, ImpliedDoIndex &&); Expr<ImpliedDoIndex::Result> FoldOperation(FoldingContext &, ImpliedDoIndex &&);
// Array constructor folding // Array constructor folding
template<typename T> class ArrayConstructorFolder { template <typename T> class ArrayConstructorFolder {
public: public:
explicit ArrayConstructorFolder(const FoldingContext &c) : context_{c} {} explicit ArrayConstructorFolder(const FoldingContext &c) : context_{c} {}
@ -797,7 +797,7 @@ private:
std::vector<Scalar<T>> elements_; std::vector<Scalar<T>> elements_;
}; };
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, ArrayConstructor<T> &&array) { Expr<T> FoldOperation(FoldingContext &context, ArrayConstructor<T> &&array) {
return ArrayConstructorFolder<T>{context}.FoldArray(std::move(array)); return ArrayConstructorFolder<T>{context}.FoldArray(std::move(array));
} }
@ -810,7 +810,7 @@ Expr<T> FoldOperation(FoldingContext &context, ArrayConstructor<T> &&array) {
// If possible, restructures an array expression into an array constructor // If possible, restructures an array expression into an array constructor
// that comprises a "flat" ArrayConstructorValues with no implied DO loops. // that comprises a "flat" ArrayConstructorValues with no implied DO loops.
template<typename T> template <typename T>
bool ArrayConstructorIsFlat(const ArrayConstructorValues<T> &values) { bool ArrayConstructorIsFlat(const ArrayConstructorValues<T> &values) {
for (const ArrayConstructorValue<T> &x : values) { for (const ArrayConstructorValue<T> &x : values) {
if (!std::holds_alternative<Expr<T>>(x.u)) { if (!std::holds_alternative<Expr<T>>(x.u)) {
@ -820,7 +820,7 @@ bool ArrayConstructorIsFlat(const ArrayConstructorValues<T> &values) {
return true; return true;
} }
template<typename T> template <typename T>
std::optional<Expr<T>> AsFlatArrayConstructor(const Expr<T> &expr) { std::optional<Expr<T>> AsFlatArrayConstructor(const Expr<T> &expr) {
if (const auto *c{UnwrapConstantValue<T>(expr)}) { if (const auto *c{UnwrapConstantValue<T>(expr)}) {
ArrayConstructor<T> result{expr}; ArrayConstructor<T> result{expr};
@ -841,7 +841,7 @@ std::optional<Expr<T>> AsFlatArrayConstructor(const Expr<T> &expr) {
return std::nullopt; return std::nullopt;
} }
template<TypeCategory CAT> template <TypeCategory CAT>
std::enable_if_t<CAT != TypeCategory::Derived, std::enable_if_t<CAT != TypeCategory::Derived,
std::optional<Expr<SomeKind<CAT>>>> std::optional<Expr<SomeKind<CAT>>>>
AsFlatArrayConstructor(const Expr<SomeKind<CAT>> &expr) { AsFlatArrayConstructor(const Expr<SomeKind<CAT>> &expr) {
@ -860,7 +860,7 @@ AsFlatArrayConstructor(const Expr<SomeKind<CAT>> &expr) {
// Given a flat ArrayConstructor<T> and a shape, it wraps the array // Given a flat ArrayConstructor<T> and a shape, it wraps the array
// into an Expr<T>, folds it, and returns the resulting wrapped // into an Expr<T>, folds it, and returns the resulting wrapped
// array constructor or constant array value. // array constructor or constant array value.
template<typename T> template <typename T>
Expr<T> FromArrayConstructor(FoldingContext &context, Expr<T> FromArrayConstructor(FoldingContext &context,
ArrayConstructor<T> &&values, std::optional<ConstantSubscripts> &&shape) { ArrayConstructor<T> &&values, std::optional<ConstantSubscripts> &&shape) {
Expr<T> result{Fold(context, Expr<T>{std::move(values)})}; Expr<T> result{Fold(context, Expr<T>{std::move(values)})};
@ -880,7 +880,7 @@ Expr<T> FromArrayConstructor(FoldingContext &context,
// Preserves shape. // Preserves shape.
// Unary case // Unary case
template<typename RESULT, typename OPERAND> template <typename RESULT, typename OPERAND>
Expr<RESULT> MapOperation(FoldingContext &context, Expr<RESULT> MapOperation(FoldingContext &context,
std::function<Expr<RESULT>(Expr<OPERAND> &&)> &&f, const Shape &shape, std::function<Expr<RESULT>(Expr<OPERAND> &&)> &&f, const Shape &shape,
Expr<OPERAND> &&values) { Expr<OPERAND> &&values) {
@ -908,7 +908,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
} }
// array * array case // array * array case
template<typename RESULT, typename LEFT, typename RIGHT> template <typename RESULT, typename LEFT, typename RIGHT>
Expr<RESULT> MapOperation(FoldingContext &context, Expr<RESULT> MapOperation(FoldingContext &context,
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f, std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f,
const Shape &shape, Expr<LEFT> &&leftValues, Expr<RIGHT> &&rightValues) { const Shape &shape, Expr<LEFT> &&leftValues, Expr<RIGHT> &&rightValues) {
@ -948,7 +948,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
} }
// array * scalar case // array * scalar case
template<typename RESULT, typename LEFT, typename RIGHT> template <typename RESULT, typename LEFT, typename RIGHT>
Expr<RESULT> MapOperation(FoldingContext &context, Expr<RESULT> MapOperation(FoldingContext &context,
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f, std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f,
const Shape &shape, Expr<LEFT> &&leftValues, const Shape &shape, Expr<LEFT> &&leftValues,
@ -965,7 +965,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
} }
// scalar * array case // scalar * array case
template<typename RESULT, typename LEFT, typename RIGHT> template <typename RESULT, typename LEFT, typename RIGHT>
Expr<RESULT> MapOperation(FoldingContext &context, Expr<RESULT> MapOperation(FoldingContext &context,
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f, std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f,
const Shape &shape, const Expr<LEFT> &leftScalar, const Shape &shape, const Expr<LEFT> &leftScalar,
@ -1000,7 +1000,7 @@ Expr<RESULT> MapOperation(FoldingContext &context,
// operation, then attempts to apply the operation to the (corresponding) // operation, then attempts to apply the operation to the (corresponding)
// scalar element(s) of those operands. Returns std::nullopt for scalars // scalar element(s) of those operands. Returns std::nullopt for scalars
// or unlinearizable operands. // or unlinearizable operands.
template<typename DERIVED, typename RESULT, typename OPERAND> template <typename DERIVED, typename RESULT, typename OPERAND>
auto ApplyElementwise(FoldingContext &context, auto ApplyElementwise(FoldingContext &context,
Operation<DERIVED, RESULT, OPERAND> &operation, Operation<DERIVED, RESULT, OPERAND> &operation,
std::function<Expr<RESULT>(Expr<OPERAND> &&)> &&f) std::function<Expr<RESULT>(Expr<OPERAND> &&)> &&f)
@ -1017,7 +1017,7 @@ auto ApplyElementwise(FoldingContext &context,
return std::nullopt; return std::nullopt;
} }
template<typename DERIVED, typename RESULT, typename OPERAND> template <typename DERIVED, typename RESULT, typename OPERAND>
auto ApplyElementwise( auto ApplyElementwise(
FoldingContext &context, Operation<DERIVED, RESULT, OPERAND> &operation) FoldingContext &context, Operation<DERIVED, RESULT, OPERAND> &operation)
-> std::optional<Expr<RESULT>> { -> std::optional<Expr<RESULT>> {
@ -1032,19 +1032,19 @@ auto ApplyElementwise(
// in the flattening of an array expression? // in the flattening of an array expression?
// TODO: capture such scalar expansions in temporaries, flatten everything // TODO: capture such scalar expansions in temporaries, flatten everything
struct UnexpandabilityFindingVisitor struct UnexpandabilityFindingVisitor
: public AnyTraverse<UnexpandabilityFindingVisitor> { : public AnyTraverse<UnexpandabilityFindingVisitor> {
using Base = AnyTraverse<UnexpandabilityFindingVisitor>; using Base = AnyTraverse<UnexpandabilityFindingVisitor>;
using Base::operator(); using Base::operator();
UnexpandabilityFindingVisitor() : Base{*this} {} UnexpandabilityFindingVisitor() : Base{*this} {}
template<typename T> bool operator()(const FunctionRef<T> &) { return true; } template <typename T> bool operator()(const FunctionRef<T> &) { return true; }
bool operator()(const CoarrayRef &) { return true; } bool operator()(const CoarrayRef &) { return true; }
}; };
template<typename T> bool IsExpandableScalar(const Expr<T> &expr) { template <typename T> bool IsExpandableScalar(const Expr<T> &expr) {
return !UnexpandabilityFindingVisitor{}(expr); return !UnexpandabilityFindingVisitor{}(expr);
} }
template<typename DERIVED, typename RESULT, typename LEFT, typename RIGHT> template <typename DERIVED, typename RESULT, typename LEFT, typename RIGHT>
auto ApplyElementwise(FoldingContext &context, auto ApplyElementwise(FoldingContext &context,
Operation<DERIVED, RESULT, LEFT, RIGHT> &operation, Operation<DERIVED, RESULT, LEFT, RIGHT> &operation,
std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f) std::function<Expr<RESULT>(Expr<LEFT> &&, Expr<RIGHT> &&)> &&f)
@ -1081,7 +1081,7 @@ auto ApplyElementwise(FoldingContext &context,
return std::nullopt; return std::nullopt;
} }
template<typename DERIVED, typename RESULT, typename LEFT, typename RIGHT> template <typename DERIVED, typename RESULT, typename LEFT, typename RIGHT>
auto ApplyElementwise( auto ApplyElementwise(
FoldingContext &context, Operation<DERIVED, RESULT, LEFT, RIGHT> &operation) FoldingContext &context, Operation<DERIVED, RESULT, LEFT, RIGHT> &operation)
-> std::optional<Expr<RESULT>> { -> std::optional<Expr<RESULT>> {
@ -1094,7 +1094,7 @@ auto ApplyElementwise(
// Unary operations // Unary operations
template<typename TO, typename FROM> template <typename TO, typename FROM>
common::IfNoLvalue<std::optional<TO>, FROM> ConvertString(FROM &&s) { common::IfNoLvalue<std::optional<TO>, FROM> ConvertString(FROM &&s) {
if constexpr (std::is_same_v<TO, FROM>) { if constexpr (std::is_same_v<TO, FROM>) {
return std::make_optional<TO>(std::move(s)); return std::make_optional<TO>(std::move(s));
@ -1112,7 +1112,7 @@ common::IfNoLvalue<std::optional<TO>, FROM> ConvertString(FROM &&s) {
} }
} }
template<typename TO, TypeCategory FROMCAT> template <typename TO, TypeCategory FROMCAT>
Expr<TO> FoldOperation( Expr<TO> FoldOperation(
FoldingContext &context, Convert<TO, FROMCAT> &&convert) { FoldingContext &context, Convert<TO, FROMCAT> &&convert) {
if (auto array{ApplyElementwise(context, convert)}) { if (auto array{ApplyElementwise(context, convert)}) {
@ -1178,14 +1178,14 @@ Expr<TO> FoldOperation(
} }
} else if constexpr (std::is_same_v<Operand, TO> && } else if constexpr (std::is_same_v<Operand, TO> &&
FROMCAT != TypeCategory::Character) { FROMCAT != TypeCategory::Character) {
return std::move(kindExpr); // remove needless conversion return std::move(kindExpr); // remove needless conversion
} }
return Expr<TO>{std::move(convert)}; return Expr<TO>{std::move(convert)};
}, },
convert.left().u); convert.left().u);
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Parentheses<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Parentheses<T> &&x) {
auto &operand{x.left()}; auto &operand{x.left()};
operand = Fold(context, std::move(operand)); operand = Fold(context, std::move(operand));
@ -1200,7 +1200,7 @@ Expr<T> FoldOperation(FoldingContext &context, Parentheses<T> &&x) {
} }
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Negate<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Negate<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1224,7 +1224,7 @@ Expr<T> FoldOperation(FoldingContext &context, Negate<T> &&x) {
// Binary (dyadic) operations // Binary (dyadic) operations
template<typename LEFT, typename RIGHT> template <typename LEFT, typename RIGHT>
std::optional<std::pair<Scalar<LEFT>, Scalar<RIGHT>>> OperandsAreConstants( std::optional<std::pair<Scalar<LEFT>, Scalar<RIGHT>>> OperandsAreConstants(
const Expr<LEFT> &x, const Expr<RIGHT> &y) { const Expr<LEFT> &x, const Expr<RIGHT> &y) {
if (auto xvalue{GetScalarConstantValue<LEFT>(x)}) { if (auto xvalue{GetScalarConstantValue<LEFT>(x)}) {
@ -1235,13 +1235,13 @@ std::optional<std::pair<Scalar<LEFT>, Scalar<RIGHT>>> OperandsAreConstants(
return std::nullopt; return std::nullopt;
} }
template<typename DERIVED, typename RESULT, typename LEFT, typename RIGHT> template <typename DERIVED, typename RESULT, typename LEFT, typename RIGHT>
std::optional<std::pair<Scalar<LEFT>, Scalar<RIGHT>>> OperandsAreConstants( std::optional<std::pair<Scalar<LEFT>, Scalar<RIGHT>>> OperandsAreConstants(
const Operation<DERIVED, RESULT, LEFT, RIGHT> &operation) { const Operation<DERIVED, RESULT, LEFT, RIGHT> &operation) {
return OperandsAreConstants(operation.left(), operation.right()); return OperandsAreConstants(operation.left(), operation.right());
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Add<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Add<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1266,7 +1266,7 @@ Expr<T> FoldOperation(FoldingContext &context, Add<T> &&x) {
return Expr<T>{std::move(x)}; return Expr<T>{std::move(x)};
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Subtract<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Subtract<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1292,7 +1292,7 @@ Expr<T> FoldOperation(FoldingContext &context, Subtract<T> &&x) {
return Expr<T>{std::move(x)}; return Expr<T>{std::move(x)};
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Multiply<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Multiply<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1317,7 +1317,7 @@ Expr<T> FoldOperation(FoldingContext &context, Multiply<T> &&x) {
return Expr<T>{std::move(x)}; return Expr<T>{std::move(x)};
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1346,7 +1346,7 @@ Expr<T> FoldOperation(FoldingContext &context, Divide<T> &&x) {
return Expr<T>{std::move(x)}; return Expr<T>{std::move(x)};
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Power<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Power<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1378,7 +1378,7 @@ Expr<T> FoldOperation(FoldingContext &context, Power<T> &&x) {
return Expr<T>{std::move(x)}; return Expr<T>{std::move(x)};
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
return *array; return *array;
@ -1399,7 +1399,7 @@ Expr<T> FoldOperation(FoldingContext &context, RealToIntPower<T> &&x) {
x.right().u); x.right().u);
} }
template<typename T> template <typename T>
Expr<T> FoldOperation(FoldingContext &context, Extremum<T> &&x) { Expr<T> FoldOperation(FoldingContext &context, Extremum<T> &&x) {
if (auto array{ApplyElementwise(context, x, if (auto array{ApplyElementwise(context, x,
std::function<Expr<T>(Expr<T> &&, Expr<T> &&)>{[=](Expr<T> &&l, std::function<Expr<T>(Expr<T> &&, Expr<T> &&)>{[=](Expr<T> &&l,
@ -1436,7 +1436,7 @@ Expr<T> FoldOperation(FoldingContext &context, Extremum<T> &&x) {
return Expr<T>{std::move(x)}; return Expr<T>{std::move(x)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Real, KIND>> ToReal( Expr<Type<TypeCategory::Real, KIND>> ToReal(
FoldingContext &context, Expr<SomeType> &&expr) { FoldingContext &context, Expr<SomeType> &&expr) {
using Result = Type<TypeCategory::Real, KIND>; using Result = Type<TypeCategory::Real, KIND>;
@ -1452,7 +1452,7 @@ Expr<Type<TypeCategory::Real, KIND>> ToReal(
CHECK(constant); CHECK(constant);
Scalar<Result> real{constant->GetScalarValue().value()}; Scalar<Result> real{constant->GetScalarValue().value()};
From converted{From::ConvertUnsigned(real.RawBits()).value}; From converted{From::ConvertUnsigned(real.RawBits()).value};
if (original != converted) { // C1601 if (original != converted) { // C1601
context.messages().Say( context.messages().Say(
"Nonzero bits truncated from BOZ literal constant in REAL intrinsic"_en_US); "Nonzero bits truncated from BOZ literal constant in REAL intrinsic"_en_US);
} }
@ -1466,7 +1466,7 @@ Expr<Type<TypeCategory::Real, KIND>> ToReal(
return result.value(); return result.value();
} }
template<typename T> template <typename T>
Expr<T> ExpressionBase<T>::Rewrite(FoldingContext &context, Expr<T> &&expr) { Expr<T> ExpressionBase<T>::Rewrite(FoldingContext &context, Expr<T> &&expr) {
return std::visit( return std::visit(
[&](auto &&x) -> Expr<T> { [&](auto &&x) -> Expr<T> {
@ -1486,5 +1486,5 @@ Expr<T> ExpressionBase<T>::Rewrite(FoldingContext &context, Expr<T> &&expr) {
FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, ) FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, )
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_FOLD_IMPLEMENTATION_H_ #endif // FORTRAN_EVALUATE_FOLD_IMPLEMENTATION_H_

View File

@ -10,7 +10,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context, Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) {
using T = Type<TypeCategory::Integer, KIND>; using T = Type<TypeCategory::Integer, KIND>;
@ -27,7 +27,7 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
static_cast<std::intmax_t>(*dim64), rank); static_cast<std::intmax_t>(*dim64), rank);
return MakeInvalidIntrinsic<T>(std::move(funcRef)); return MakeInvalidIntrinsic<T>(std::move(funcRef));
} else { } else {
dim = *dim64 - 1; // 1-based to 0-based dim = *dim64 - 1; // 1-based to 0-based
} }
} else { } else {
// DIM= is present but not constant // DIM= is present but not constant
@ -48,7 +48,7 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
ConvertToType<T>(Expr<ExtentType>{std::move(*extents)})); ConvertToType<T>(Expr<ExtentType>{std::move(*extents)}));
} }
} else { } else {
lowerBoundsAreOne = symbol.Rank() == 0; // LBOUND(array%component) lowerBoundsAreOne = symbol.Rank() == 0; // LBOUND(array%component)
} }
} }
if (lowerBoundsAreOne) { if (lowerBoundsAreOne) {
@ -65,7 +65,7 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context, Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) {
using T = Type<TypeCategory::Integer, KIND>; using T = Type<TypeCategory::Integer, KIND>;
@ -82,7 +82,7 @@ Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
static_cast<std::intmax_t>(*dim64), rank); static_cast<std::intmax_t>(*dim64), rank);
return MakeInvalidIntrinsic<T>(std::move(funcRef)); return MakeInvalidIntrinsic<T>(std::move(funcRef));
} else { } else {
dim = *dim64 - 1; // 1-based to 0-based dim = *dim64 - 1; // 1-based to 0-based
} }
} else { } else {
// DIM= is present but not constant // DIM= is present but not constant
@ -112,7 +112,7 @@ Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
} }
} }
} else { } else {
takeBoundsFromShape = symbol.Rank() == 0; // UBOUND(array%component) takeBoundsFromShape = symbol.Rank() == 0; // UBOUND(array%component)
} }
} }
if (takeBoundsFromShape) { if (takeBoundsFromShape) {
@ -132,7 +132,7 @@ Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FoldingContext &context,
FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) {
@ -177,7 +177,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
cx->u); cx->u);
} }
} else if (name == "count") { } else if (name == "count") {
if (!args[1]) { // TODO: COUNT(x,DIM=d) if (!args[1]) { // TODO: COUNT(x,DIM=d)
if (const auto *constant{UnwrapConstantValue<LogicalResult>(args[0])}) { if (const auto *constant{UnwrapConstantValue<LogicalResult>(args[0])}) {
std::int64_t result{0}; std::int64_t result{0};
for (const auto &element : constant->values()) { for (const auto &element : constant->values()) {
@ -260,7 +260,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
} }
} else if (name == "iand" || name == "ior" || name == "ieor") { } else if (name == "iand" || name == "ior" || name == "ieor") {
auto fptr{&Scalar<T>::IAND}; auto fptr{&Scalar<T>::IAND};
if (name == "iand") { // done in fptr declaration if (name == "iand") { // done in fptr declaration
} else if (name == "ior") { } else if (name == "ior") {
fptr = &Scalar<T>::IOR; fptr = &Scalar<T>::IOR;
} else if (name == "ieor") { } else if (name == "ieor") {
@ -275,7 +275,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
// Second argument can be of any kind. However, it must be smaller or // Second argument can be of any kind. However, it must be smaller or
// equal than BIT_SIZE. It can be converted to Int4 to simplify. // equal than BIT_SIZE. It can be converted to Int4 to simplify.
auto fptr{&Scalar<T>::IBCLR}; auto fptr{&Scalar<T>::IBCLR};
if (name == "ibclr") { // done in fprt definition if (name == "ibclr") { // done in fprt definition
} else if (name == "ibset") { } else if (name == "ibset") {
fptr = &Scalar<T>::IBSET; fptr = &Scalar<T>::IBSET;
} else if (name == "ishft") { } else if (name == "ishft") {
@ -299,7 +299,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
return std::visit( return std::visit(
[&](const auto &kch) -> Expr<T> { [&](const auto &kch) -> Expr<T> {
using TC = typename std::decay_t<decltype(kch)>::Result; using TC = typename std::decay_t<decltype(kch)>::Result;
if (UnwrapExpr<Expr<SomeLogical>>(args[2])) { // BACK= if (UnwrapExpr<Expr<SomeLogical>>(args[2])) { // BACK=
return FoldElementalIntrinsic<T, TC, TC, LogicalResult>(context, return FoldElementalIntrinsic<T, TC, TC, LogicalResult>(context,
std::move(funcRef), std::move(funcRef),
ScalarFunc<T, TC, TC, LogicalResult>{ ScalarFunc<T, TC, TC, LogicalResult>{
@ -367,7 +367,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
})); }));
} }
auto fptr{&Scalar<TI>::LEADZ}; auto fptr{&Scalar<TI>::LEADZ};
if (name == "leadz") { // done in fptr definition if (name == "leadz") { // done in fptr definition
} else if (name == "trailz") { } else if (name == "trailz") {
fptr = &Scalar<TI>::TRAILZ; fptr = &Scalar<TI>::TRAILZ;
} else if (name == "popcnt") { } else if (name == "popcnt") {
@ -562,7 +562,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
})); }));
} else if (name == "size") { } else if (name == "size") {
if (auto shape{GetShape(context, args[0])}) { if (auto shape{GetShape(context, args[0])}) {
if (auto &dimArg{args[1]}) { // DIM= is present, get one extent if (auto &dimArg{args[1]}) { // DIM= is present, get one extent
if (auto dim{GetInt64Arg(args[1])}) { if (auto dim{GetInt64Arg(args[1])}) {
int rank{GetRank(*shape)}; int rank{GetRank(*shape)};
if (*dim >= 1 && *dim <= rank) { if (*dim >= 1 && *dim <= rank) {
@ -597,7 +597,7 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
} }
// Substitute a bare type parameter reference with its value if it has one now // Substitute a bare type parameter reference with its value if it has one now
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> FoldOperation( Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
FoldingContext &context, TypeParamInquiry<KIND> &&inquiry) { FoldingContext &context, TypeParamInquiry<KIND> &&inquiry) {
using IntKIND = Type<TypeCategory::Integer, KIND>; using IntKIND = Type<TypeCategory::Integer, KIND>;
@ -644,4 +644,4 @@ std::optional<std::int64_t> ToInt64(const Expr<SomeType> &expr) {
FOR_EACH_INTEGER_KIND(template class ExpressionBase, ) FOR_EACH_INTEGER_KIND(template class ExpressionBase, )
template class ExpressionBase<SomeInteger>; template class ExpressionBase<SomeInteger>;
} } // namespace Fortran::evaluate

View File

@ -11,7 +11,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FoldingContext &context,
FunctionRef<Type<TypeCategory::Logical, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Logical, KIND>> &&funcRef) {
@ -21,7 +21,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
CHECK(intrinsic); CHECK(intrinsic);
std::string name{intrinsic->name}; std::string name{intrinsic->name};
if (name == "all") { if (name == "all") {
if (!args[1]) { // TODO: ALL(x,DIM=d) if (!args[1]) { // TODO: ALL(x,DIM=d)
if (const auto *constant{UnwrapConstantValue<T>(args[0])}) { if (const auto *constant{UnwrapConstantValue<T>(args[0])}) {
bool result{true}; bool result{true};
for (const auto &element : constant->values()) { for (const auto &element : constant->values()) {
@ -34,7 +34,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
} }
} }
} else if (name == "any") { } else if (name == "any") {
if (!args[1]) { // TODO: ANY(x,DIM=d) if (!args[1]) { // TODO: ANY(x,DIM=d)
if (const auto *constant{UnwrapConstantValue<T>(args[0])}) { if (const auto *constant{UnwrapConstantValue<T>(args[0])}) {
bool result{false}; bool result{false};
for (const auto &element : constant->values()) { for (const auto &element : constant->values()) {
@ -61,7 +61,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
} }
} }
auto fptr{&Scalar<LargestInt>::BGE}; auto fptr{&Scalar<LargestInt>::BGE};
if (name == "bge") { // done in fptr declaration if (name == "bge") { // done in fptr declaration
} else if (name == "bgt") { } else if (name == "bgt") {
fptr = &Scalar<LargestInt>::BGT; fptr = &Scalar<LargestInt>::BGT;
} else if (name == "ble") { } else if (name == "ble") {
@ -95,7 +95,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<typename T> template <typename T>
Expr<LogicalResult> FoldOperation( Expr<LogicalResult> FoldOperation(
FoldingContext &context, Relational<T> &&relation) { FoldingContext &context, Relational<T> &&relation) {
if (auto array{ApplyElementwise(context, relation, if (auto array{ApplyElementwise(context, relation,
@ -133,7 +133,7 @@ Expr<LogicalResult> FoldOperation(
std::move(relation.u)); std::move(relation.u));
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Logical, KIND>> FoldOperation( Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
FoldingContext &context, Not<KIND> &&x) { FoldingContext &context, Not<KIND> &&x) {
if (auto array{ApplyElementwise(context, x)}) { if (auto array{ApplyElementwise(context, x)}) {
@ -147,7 +147,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
return Expr<Ty>{x}; return Expr<Ty>{x};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Logical, KIND>> FoldOperation( Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
FoldingContext &context, LogicalOperation<KIND> &&operation) { FoldingContext &context, LogicalOperation<KIND> &&operation) {
using LOGICAL = Type<TypeCategory::Logical, KIND>; using LOGICAL = Type<TypeCategory::Logical, KIND>;
@ -162,11 +162,20 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
if (auto folded{OperandsAreConstants(operation)}) { if (auto folded{OperandsAreConstants(operation)}) {
bool xt{folded->first.IsTrue()}, yt{folded->second.IsTrue()}, result{}; bool xt{folded->first.IsTrue()}, yt{folded->second.IsTrue()}, result{};
switch (operation.logicalOperator) { switch (operation.logicalOperator) {
case LogicalOperator::And: result = xt && yt; break; case LogicalOperator::And:
case LogicalOperator::Or: result = xt || yt; break; result = xt && yt;
case LogicalOperator::Eqv: result = xt == yt; break; break;
case LogicalOperator::Neqv: result = xt != yt; break; case LogicalOperator::Or:
case LogicalOperator::Not: DIE("not a binary operator"); result = xt || yt;
break;
case LogicalOperator::Eqv:
result = xt == yt;
break;
case LogicalOperator::Neqv:
result = xt != yt;
break;
case LogicalOperator::Not:
DIE("not a binary operator");
} }
return Expr<LOGICAL>{Constant<LOGICAL>{result}}; return Expr<LOGICAL>{Constant<LOGICAL>{result}};
} }
@ -175,4 +184,4 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
FOR_EACH_LOGICAL_KIND(template class ExpressionBase, ) FOR_EACH_LOGICAL_KIND(template class ExpressionBase, )
template class ExpressionBase<SomeLogical>; template class ExpressionBase<SomeLogical>;
} } // namespace Fortran::evaluate

View File

@ -10,7 +10,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction( Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
FoldingContext &context, FoldingContext &context,
FunctionRef<Type<TypeCategory::Real, KIND>> &&funcRef) { FunctionRef<Type<TypeCategory::Real, KIND>> &&funcRef) {
@ -52,7 +52,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
name, KIND, KIND); name, KIND, KIND);
} }
} else if (name == "bessel_jn" || name == "bessel_yn") { } else if (name == "bessel_jn" || name == "bessel_yn") {
if (args.size() == 2) { // elemental if (args.size() == 2) { // elemental
// runtime functions use int arg // runtime functions use int arg
using Int4 = Type<TypeCategory::Integer, 4>; using Int4 = Type<TypeCategory::Integer, 4>;
if (auto callable{ if (auto callable{
@ -135,7 +135,7 @@ Expr<Type<TypeCategory::Real, KIND>> FoldIntrinsicFunction(
return Expr<T>{std::move(funcRef)}; return Expr<T>{std::move(funcRef)};
} }
template<int KIND> template <int KIND>
Expr<Type<TypeCategory::Real, KIND>> FoldOperation( Expr<Type<TypeCategory::Real, KIND>> FoldOperation(
FoldingContext &context, ComplexComponent<KIND> &&x) { FoldingContext &context, ComplexComponent<KIND> &&x) {
using Operand = Type<TypeCategory::Complex, KIND>; using Operand = Type<TypeCategory::Complex, KIND>;
@ -162,4 +162,4 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(
FOR_EACH_REAL_KIND(template class ExpressionBase, ) FOR_EACH_REAL_KIND(template class ExpressionBase, )
template class ExpressionBase<SomeReal>; template class ExpressionBase<SomeReal>;
} } // namespace Fortran::evaluate

View File

@ -85,16 +85,16 @@ Triplet FoldOperation(FoldingContext &context, Triplet &&triplet) {
} }
Subscript FoldOperation(FoldingContext &context, Subscript &&subscript) { Subscript FoldOperation(FoldingContext &context, Subscript &&subscript) {
return std::visit( return std::visit(common::visitors{
common::visitors{ [&](IndirectSubscriptIntegerExpr &&expr) {
[&](IndirectSubscriptIntegerExpr &&expr) { expr.value() = Fold(context, std::move(expr.value()));
expr.value() = Fold(context, std::move(expr.value())); return Subscript(std::move(expr));
return Subscript(std::move(expr)); },
}, [&](Triplet &&triplet) {
[&](Triplet &&triplet) { return Subscript(
return Subscript(FoldOperation(context, std::move(triplet))); FoldOperation(context, std::move(triplet)));
}, },
}, },
std::move(subscript.u)); std::move(subscript.u));
} }
@ -128,13 +128,12 @@ CoarrayRef FoldOperation(FoldingContext &context, CoarrayRef &&coarrayRef) {
} }
DataRef FoldOperation(FoldingContext &context, DataRef &&dataRef) { DataRef FoldOperation(FoldingContext &context, DataRef &&dataRef) {
return std::visit( return std::visit(common::visitors{
common::visitors{ [&](SymbolRef symbol) { return DataRef{*symbol}; },
[&](SymbolRef symbol) { return DataRef{*symbol}; }, [&](auto &&x) {
[&](auto &&x) { return DataRef{FoldOperation(context, std::move(x))};
return DataRef{FoldOperation(context, std::move(x))}; },
}, },
},
std::move(dataRef.u)); std::move(dataRef.u));
} }
@ -188,4 +187,4 @@ Expr<ImpliedDoIndex::Result> FoldOperation(
template class ExpressionBase<SomeDerived>; template class ExpressionBase<SomeDerived>;
template class ExpressionBase<SomeType>; template class ExpressionBase<SomeType>;
} } // namespace Fortran::evaluate

View File

@ -31,7 +31,7 @@ static void ShapeAsFortran(
} }
} }
template<typename RESULT, typename VALUE> template <typename RESULT, typename VALUE>
llvm::raw_ostream &ConstantBase<RESULT, VALUE>::AsFortran( llvm::raw_ostream &ConstantBase<RESULT, VALUE>::AsFortran(
llvm::raw_ostream &o) const { llvm::raw_ostream &o) const {
if (Rank() > 1) { if (Rank() > 1) {
@ -72,7 +72,7 @@ llvm::raw_ostream &ConstantBase<RESULT, VALUE>::AsFortran(
return o; return o;
} }
template<int KIND> template <int KIND>
llvm::raw_ostream &Constant<Type<TypeCategory::Character, KIND>>::AsFortran( llvm::raw_ostream &Constant<Type<TypeCategory::Character, KIND>>::AsFortran(
llvm::raw_ostream &o) const { llvm::raw_ostream &o) const {
if (Rank() > 1) { if (Rank() > 1) {
@ -146,67 +146,71 @@ llvm::raw_ostream &ProcedureRef::AsFortran(llvm::raw_ostream &o) const {
// Operator precedence formatting; insert parentheses around operands // Operator precedence formatting; insert parentheses around operands
// only when necessary. // only when necessary.
enum class Precedence { // in increasing order for sane comparisons enum class Precedence { // in increasing order for sane comparisons
DefinedBinary, DefinedBinary,
Or, Or,
And, And,
Equivalence, // .EQV., .NEQV. Equivalence, // .EQV., .NEQV.
Not, // which binds *less* tightly in Fortran than relations Not, // which binds *less* tightly in Fortran than relations
Relational, Relational,
Additive, // +, -, and (arbitrarily) // Additive, // +, -, and (arbitrarily) //
Negate, // which binds *less* tightly than *, /, ** Negate, // which binds *less* tightly than *, /, **
Multiplicative, // *, / Multiplicative, // *, /
Power, // **, which is right-associative unlike the other dyadic operators Power, // **, which is right-associative unlike the other dyadic operators
DefinedUnary, DefinedUnary,
Top, Top,
}; };
template<typename A> constexpr Precedence ToPrecedence(const A &) { template <typename A> constexpr Precedence ToPrecedence(const A &) {
return Precedence::Top; return Precedence::Top;
} }
template<int KIND> template <int KIND>
static Precedence ToPrecedence(const LogicalOperation<KIND> &x) { static Precedence ToPrecedence(const LogicalOperation<KIND> &x) {
switch (x.logicalOperator) { switch (x.logicalOperator) {
SWITCH_COVERS_ALL_CASES SWITCH_COVERS_ALL_CASES
case LogicalOperator::And: return Precedence::And; case LogicalOperator::And:
case LogicalOperator::Or: return Precedence::Or; return Precedence::And;
case LogicalOperator::Not: return Precedence::Not; case LogicalOperator::Or:
return Precedence::Or;
case LogicalOperator::Not:
return Precedence::Not;
case LogicalOperator::Eqv: case LogicalOperator::Eqv:
case LogicalOperator::Neqv: return Precedence::Equivalence; case LogicalOperator::Neqv:
return Precedence::Equivalence;
} }
} }
template<int KIND> constexpr Precedence ToPrecedence(const Not<KIND> &) { template <int KIND> constexpr Precedence ToPrecedence(const Not<KIND> &) {
return Precedence::Not; return Precedence::Not;
} }
template<typename T> constexpr Precedence ToPrecedence(const Relational<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Relational<T> &) {
return Precedence::Relational; return Precedence::Relational;
} }
template<typename T> constexpr Precedence ToPrecedence(const Add<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Add<T> &) {
return Precedence::Additive; return Precedence::Additive;
} }
template<typename T> constexpr Precedence ToPrecedence(const Subtract<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Subtract<T> &) {
return Precedence::Additive; return Precedence::Additive;
} }
template<int KIND> constexpr Precedence ToPrecedence(const Concat<KIND> &) { template <int KIND> constexpr Precedence ToPrecedence(const Concat<KIND> &) {
return Precedence::Additive; return Precedence::Additive;
} }
template<typename T> constexpr Precedence ToPrecedence(const Negate<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Negate<T> &) {
return Precedence::Negate; return Precedence::Negate;
} }
template<typename T> constexpr Precedence ToPrecedence(const Multiply<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Multiply<T> &) {
return Precedence::Multiplicative; return Precedence::Multiplicative;
} }
template<typename T> constexpr Precedence ToPrecedence(const Divide<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Divide<T> &) {
return Precedence::Multiplicative; return Precedence::Multiplicative;
} }
template<typename T> constexpr Precedence ToPrecedence(const Power<T> &) { template <typename T> constexpr Precedence ToPrecedence(const Power<T> &) {
return Precedence::Power; return Precedence::Power;
} }
template<typename T> template <typename T>
constexpr Precedence ToPrecedence(const RealToIntPower<T> &) { constexpr Precedence ToPrecedence(const RealToIntPower<T> &) {
return Precedence::Power; return Precedence::Power;
} }
template<typename T> static Precedence ToPrecedence(const Constant<T> &x) { template <typename T> static Precedence ToPrecedence(const Constant<T> &x) {
static constexpr TypeCategory cat{T::category}; static constexpr TypeCategory cat{T::category};
if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) {
if (auto n{GetScalarConstantValue<T>(x)}) { if (auto n{GetScalarConstantValue<T>(x)}) {
@ -217,11 +221,11 @@ template<typename T> static Precedence ToPrecedence(const Constant<T> &x) {
} }
return Precedence::Top; return Precedence::Top;
} }
template<typename T> static Precedence ToPrecedence(const Expr<T> &expr) { template <typename T> static Precedence ToPrecedence(const Expr<T> &expr) {
return std::visit([](const auto &x) { return ToPrecedence(x); }, expr.u); return std::visit([](const auto &x) { return ToPrecedence(x); }, expr.u);
} }
template<typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) { template <typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
static constexpr TypeCategory cat{T::category}; static constexpr TypeCategory cat{T::category};
if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) {
if (auto n{GetScalarConstantValue<T>(expr)}) { if (auto n{GetScalarConstantValue<T>(expr)}) {
@ -231,7 +235,7 @@ template<typename T> static bool IsNegatedScalarConstant(const Expr<T> &expr) {
return false; return false;
} }
template<TypeCategory CAT> template <TypeCategory CAT>
static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) { static bool IsNegatedScalarConstant(const Expr<SomeKind<CAT>> &expr) {
return std::visit( return std::visit(
[](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u); [](const auto &x) { return IsNegatedScalarConstant(x); }, expr.u);
@ -241,74 +245,75 @@ struct OperatorSpelling {
const char *prefix{""}, *infix{","}, *suffix{""}; const char *prefix{""}, *infix{","}, *suffix{""};
}; };
template<typename A> constexpr OperatorSpelling SpellOperator(const A &) { template <typename A> constexpr OperatorSpelling SpellOperator(const A &) {
return OperatorSpelling{}; return OperatorSpelling{};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const Negate<A> &) { constexpr OperatorSpelling SpellOperator(const Negate<A> &) {
return OperatorSpelling{"-", "", ""}; return OperatorSpelling{"-", "", ""};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const Parentheses<A> &) { constexpr OperatorSpelling SpellOperator(const Parentheses<A> &) {
return OperatorSpelling{"(", "", ")"}; return OperatorSpelling{"(", "", ")"};
} }
template<int KIND> template <int KIND>
static OperatorSpelling SpellOperator(const ComplexComponent<KIND> &x) { static OperatorSpelling SpellOperator(const ComplexComponent<KIND> &x) {
return {x.isImaginaryPart ? "aimag(" : "real(", "", ")"}; return {x.isImaginaryPart ? "aimag(" : "real(", "", ")"};
} }
template<int KIND> constexpr OperatorSpelling SpellOperator(const Not<KIND> &) { template <int KIND>
constexpr OperatorSpelling SpellOperator(const Not<KIND> &) {
return OperatorSpelling{".NOT.", "", ""}; return OperatorSpelling{".NOT.", "", ""};
} }
template<int KIND> template <int KIND>
constexpr OperatorSpelling SpellOperator(const SetLength<KIND> &) { constexpr OperatorSpelling SpellOperator(const SetLength<KIND> &) {
return OperatorSpelling{"%SET_LENGTH(", ",", ")"}; return OperatorSpelling{"%SET_LENGTH(", ",", ")"};
} }
template<int KIND> template <int KIND>
constexpr OperatorSpelling SpellOperator(const ComplexConstructor<KIND> &) { constexpr OperatorSpelling SpellOperator(const ComplexConstructor<KIND> &) {
return OperatorSpelling{"(", ",", ")"}; return OperatorSpelling{"(", ",", ")"};
} }
template<typename A> constexpr OperatorSpelling SpellOperator(const Add<A> &) { template <typename A> constexpr OperatorSpelling SpellOperator(const Add<A> &) {
return OperatorSpelling{"", "+", ""}; return OperatorSpelling{"", "+", ""};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const Subtract<A> &) { constexpr OperatorSpelling SpellOperator(const Subtract<A> &) {
return OperatorSpelling{"", "-", ""}; return OperatorSpelling{"", "-", ""};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const Multiply<A> &) { constexpr OperatorSpelling SpellOperator(const Multiply<A> &) {
return OperatorSpelling{"", "*", ""}; return OperatorSpelling{"", "*", ""};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const Divide<A> &) { constexpr OperatorSpelling SpellOperator(const Divide<A> &) {
return OperatorSpelling{"", "/", ""}; return OperatorSpelling{"", "/", ""};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const Power<A> &) { constexpr OperatorSpelling SpellOperator(const Power<A> &) {
return OperatorSpelling{"", "**", ""}; return OperatorSpelling{"", "**", ""};
} }
template<typename A> template <typename A>
constexpr OperatorSpelling SpellOperator(const RealToIntPower<A> &) { constexpr OperatorSpelling SpellOperator(const RealToIntPower<A> &) {
return OperatorSpelling{"", "**", ""}; return OperatorSpelling{"", "**", ""};
} }
template<typename A> template <typename A>
static OperatorSpelling SpellOperator(const Extremum<A> &x) { static OperatorSpelling SpellOperator(const Extremum<A> &x) {
return OperatorSpelling{ return OperatorSpelling{
x.ordering == Ordering::Less ? "min(" : "max(", ",", ")"}; x.ordering == Ordering::Less ? "min(" : "max(", ",", ")"};
} }
template<int KIND> template <int KIND>
constexpr OperatorSpelling SpellOperator(const Concat<KIND> &) { constexpr OperatorSpelling SpellOperator(const Concat<KIND> &) {
return OperatorSpelling{"", "//", ""}; return OperatorSpelling{"", "//", ""};
} }
template<int KIND> template <int KIND>
static OperatorSpelling SpellOperator(const LogicalOperation<KIND> &x) { static OperatorSpelling SpellOperator(const LogicalOperation<KIND> &x) {
return OperatorSpelling{"", AsFortran(x.logicalOperator), ""}; return OperatorSpelling{"", AsFortran(x.logicalOperator), ""};
} }
template<typename T> template <typename T>
static OperatorSpelling SpellOperator(const Relational<T> &x) { static OperatorSpelling SpellOperator(const Relational<T> &x) {
return OperatorSpelling{"", AsFortran(x.opr), ""}; return OperatorSpelling{"", AsFortran(x.opr), ""};
} }
template<typename D, typename R, typename... O> template <typename D, typename R, typename... O>
llvm::raw_ostream &Operation<D, R, O...>::AsFortran( llvm::raw_ostream &Operation<D, R, O...>::AsFortran(
llvm::raw_ostream &o) const { llvm::raw_ostream &o) const {
Precedence lhsPrec{ToPrecedence(left())}; Precedence lhsPrec{ToPrecedence(left())};
@ -340,7 +345,7 @@ llvm::raw_ostream &Operation<D, R, O...>::AsFortran(
return o << spelling.suffix; return o << spelling.suffix;
} }
template<typename TO, TypeCategory FROMCAT> template <typename TO, TypeCategory FROMCAT>
llvm::raw_ostream &Convert<TO, FROMCAT>::AsFortran(llvm::raw_ostream &o) const { llvm::raw_ostream &Convert<TO, FROMCAT>::AsFortran(llvm::raw_ostream &o) const {
static_assert(TO::category == TypeCategory::Integer || static_assert(TO::category == TypeCategory::Integer ||
TO::category == TypeCategory::Real || TO::category == TypeCategory::Real ||
@ -364,16 +369,16 @@ llvm::raw_ostream &Relational<SomeType>::AsFortran(llvm::raw_ostream &o) const {
return o; return o;
} }
template<typename T> template <typename T>
llvm::raw_ostream &EmitArray(llvm::raw_ostream &o, const Expr<T> &expr) { llvm::raw_ostream &EmitArray(llvm::raw_ostream &o, const Expr<T> &expr) {
return expr.AsFortran(o); return expr.AsFortran(o);
} }
template<typename T> template <typename T>
llvm::raw_ostream &EmitArray( llvm::raw_ostream &EmitArray(
llvm::raw_ostream &, const ArrayConstructorValues<T> &); llvm::raw_ostream &, const ArrayConstructorValues<T> &);
template<typename T> template <typename T>
llvm::raw_ostream &EmitArray(llvm::raw_ostream &o, const ImpliedDo<T> &implDo) { llvm::raw_ostream &EmitArray(llvm::raw_ostream &o, const ImpliedDo<T> &implDo) {
o << '('; o << '(';
EmitArray(o, implDo.values()); EmitArray(o, implDo.values());
@ -385,7 +390,7 @@ llvm::raw_ostream &EmitArray(llvm::raw_ostream &o, const ImpliedDo<T> &implDo) {
return o; return o;
} }
template<typename T> template <typename T>
llvm::raw_ostream &EmitArray( llvm::raw_ostream &EmitArray(
llvm::raw_ostream &o, const ArrayConstructorValues<T> &values) { llvm::raw_ostream &o, const ArrayConstructorValues<T> &values) {
const char *sep{""}; const char *sep{""};
@ -397,14 +402,14 @@ llvm::raw_ostream &EmitArray(
return o; return o;
} }
template<typename T> template <typename T>
llvm::raw_ostream &ArrayConstructor<T>::AsFortran(llvm::raw_ostream &o) const { llvm::raw_ostream &ArrayConstructor<T>::AsFortran(llvm::raw_ostream &o) const {
o << '[' << GetType().AsFortran() << "::"; o << '[' << GetType().AsFortran() << "::";
EmitArray(o, *this); EmitArray(o, *this);
return o << ']'; return o << ']';
} }
template<int KIND> template <int KIND>
llvm::raw_ostream & llvm::raw_ostream &
ArrayConstructor<Type<TypeCategory::Character, KIND>>::AsFortran( ArrayConstructor<Type<TypeCategory::Character, KIND>>::AsFortran(
llvm::raw_ostream &o) const { llvm::raw_ostream &o) const {
@ -420,7 +425,7 @@ llvm::raw_ostream &ArrayConstructor<SomeDerived>::AsFortran(
return o << ']'; return o << ']';
} }
template<typename RESULT> template <typename RESULT>
std::string ExpressionBase<RESULT>::AsFortran() const { std::string ExpressionBase<RESULT>::AsFortran() const {
std::string buf; std::string buf;
llvm::raw_string_ostream ss{buf}; llvm::raw_string_ostream ss{buf};
@ -428,21 +433,20 @@ std::string ExpressionBase<RESULT>::AsFortran() const {
return ss.str(); return ss.str();
} }
template<typename RESULT> template <typename RESULT>
llvm::raw_ostream &ExpressionBase<RESULT>::AsFortran( llvm::raw_ostream &ExpressionBase<RESULT>::AsFortran(
llvm::raw_ostream &o) const { llvm::raw_ostream &o) const {
std::visit( std::visit(common::visitors{
common::visitors{ [&](const BOZLiteralConstant &x) {
[&](const BOZLiteralConstant &x) { o << "z'" << x.Hexadecimal() << "'";
o << "z'" << x.Hexadecimal() << "'"; },
}, [&](const NullPointer &) { o << "NULL()"; },
[&](const NullPointer &) { o << "NULL()"; }, [&](const common::CopyableIndirection<Substring> &s) {
[&](const common::CopyableIndirection<Substring> &s) { s.value().AsFortran(o);
s.value().AsFortran(o); },
}, [&](const ImpliedDoIndex &i) { o << i.name.ToString(); },
[&](const ImpliedDoIndex &i) { o << i.name.ToString(); }, [&](const auto &x) { x.AsFortran(o); },
[&](const auto &x) { x.AsFortran(o); }, },
},
derived().u); derived().u);
return o; return o;
} }
@ -542,17 +546,17 @@ llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::u32string &lit) {
return o << parser::QuoteCharacterLiteral(lit); return o << parser::QuoteCharacterLiteral(lit);
} }
template<typename A> template <typename A>
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const A &x) { llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const A &x) {
return x.AsFortran(o); return x.AsFortran(o);
} }
template<typename A> template <typename A>
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, common::Reference<A> x) { llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, common::Reference<A> x) {
return EmitVar(o, *x); return EmitVar(o, *x);
} }
template<typename A> template <typename A>
llvm::raw_ostream &EmitVar( llvm::raw_ostream &EmitVar(
llvm::raw_ostream &o, const A *p, const char *kw = nullptr) { llvm::raw_ostream &o, const A *p, const char *kw = nullptr) {
if (p) { if (p) {
@ -564,7 +568,7 @@ llvm::raw_ostream &EmitVar(
return o; return o;
} }
template<typename A> template <typename A>
llvm::raw_ostream &EmitVar( llvm::raw_ostream &EmitVar(
llvm::raw_ostream &o, const std::optional<A> &x, const char *kw = nullptr) { llvm::raw_ostream &o, const std::optional<A> &x, const char *kw = nullptr) {
if (x) { if (x) {
@ -576,7 +580,7 @@ llvm::raw_ostream &EmitVar(
return o; return o;
} }
template<typename A, bool COPY> template <typename A, bool COPY>
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, llvm::raw_ostream &EmitVar(llvm::raw_ostream &o,
const common::Indirection<A, COPY> &p, const char *kw = nullptr) { const common::Indirection<A, COPY> &p, const char *kw = nullptr) {
if (kw) { if (kw) {
@ -586,13 +590,13 @@ llvm::raw_ostream &EmitVar(llvm::raw_ostream &o,
return o; return o;
} }
template<typename A> template <typename A>
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::shared_ptr<A> &p) { llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::shared_ptr<A> &p) {
CHECK(p); CHECK(p);
return EmitVar(o, *p); return EmitVar(o, *p);
} }
template<typename... A> template <typename... A>
llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::variant<A...> &u) { llvm::raw_ostream &EmitVar(llvm::raw_ostream &o, const std::variant<A...> &u) {
std::visit([&](const auto &x) { EmitVar(o, x); }, u); std::visit([&](const auto &x) { EmitVar(o, x); }, u);
return o; return o;
@ -602,7 +606,7 @@ llvm::raw_ostream &BaseObject::AsFortran(llvm::raw_ostream &o) const {
return EmitVar(o, u); return EmitVar(o, u);
} }
template<int KIND> template <int KIND>
llvm::raw_ostream &TypeParamInquiry<KIND>::AsFortran( llvm::raw_ostream &TypeParamInquiry<KIND>::AsFortran(
llvm::raw_ostream &o) const { llvm::raw_ostream &o) const {
if (base_) { if (base_) {
@ -617,11 +621,10 @@ llvm::raw_ostream &Component::AsFortran(llvm::raw_ostream &o) const {
} }
llvm::raw_ostream &NamedEntity::AsFortran(llvm::raw_ostream &o) const { llvm::raw_ostream &NamedEntity::AsFortran(llvm::raw_ostream &o) const {
std::visit( std::visit(common::visitors{
common::visitors{ [&](SymbolRef s) { EmitVar(o, s); },
[&](SymbolRef s) { EmitVar(o, s); }, [&](const Component &c) { c.AsFortran(o); },
[&](const Component &c) { c.AsFortran(o); }, },
},
u_); u_);
return o; return o;
} }
@ -699,24 +702,32 @@ llvm::raw_ostream &ProcedureDesignator::AsFortran(llvm::raw_ostream &o) const {
return EmitVar(o, u); return EmitVar(o, u);
} }
template<typename T> template <typename T>
llvm::raw_ostream &Designator<T>::AsFortran(llvm::raw_ostream &o) const { llvm::raw_ostream &Designator<T>::AsFortran(llvm::raw_ostream &o) const {
std::visit( std::visit(common::visitors{
common::visitors{ [&](SymbolRef symbol) { EmitVar(o, symbol); },
[&](SymbolRef symbol) { EmitVar(o, symbol); }, [&](const auto &x) { x.AsFortran(o); },
[&](const auto &x) { x.AsFortran(o); }, },
},
u); u);
return o; return o;
} }
llvm::raw_ostream &DescriptorInquiry::AsFortran(llvm::raw_ostream &o) const { llvm::raw_ostream &DescriptorInquiry::AsFortran(llvm::raw_ostream &o) const {
switch (field_) { switch (field_) {
case Field::LowerBound: o << "lbound("; break; case Field::LowerBound:
case Field::Extent: o << "size("; break; o << "lbound(";
case Field::Stride: o << "%STRIDE("; break; break;
case Field::Rank: o << "rank("; break; case Field::Extent:
case Field::Len: break; o << "size(";
break;
case Field::Stride:
o << "%STRIDE(";
break;
case Field::Rank:
o << "rank(";
break;
case Field::Len:
break;
} }
base_.AsFortran(o); base_.AsFortran(o);
if (field_ == Field::Len) { if (field_ == Field::Len) {
@ -769,4 +780,4 @@ llvm::raw_ostream &Assignment::AsFortran(llvm::raw_ostream &o) const {
INSTANTIATE_CONSTANT_TEMPLATES INSTANTIATE_CONSTANT_TEMPLATES
INSTANTIATE_EXPRESSION_TEMPLATES INSTANTIATE_EXPRESSION_TEMPLATES
INSTANTIATE_VARIABLE_TEMPLATES INSTANTIATE_VARIABLE_TEMPLATES
} } // namespace Fortran::evaluate

View File

@ -31,26 +31,26 @@ void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment(
#if __x86_64__ #if __x86_64__
hasSubnormalFlushingHardwareControl_ = true; hasSubnormalFlushingHardwareControl_ = true;
if (context.flushSubnormalsToZero()) { if (context.flushSubnormalsToZero()) {
currentFenv_.__mxcsr |= 0x8000; // result currentFenv_.__mxcsr |= 0x8000; // result
currentFenv_.__mxcsr |= 0x0040; // operands currentFenv_.__mxcsr |= 0x0040; // operands
} else { } else {
currentFenv_.__mxcsr &= ~0x8000; // result currentFenv_.__mxcsr &= ~0x8000; // result
currentFenv_.__mxcsr &= ~0x0040; // operands currentFenv_.__mxcsr &= ~0x0040; // operands
} }
#elif defined(__aarch64__) #elif defined(__aarch64__)
#if defined(__GNU_LIBRARY__) #if defined(__GNU_LIBRARY__)
hasSubnormalFlushingHardwareControl_ = true; hasSubnormalFlushingHardwareControl_ = true;
if (context.flushSubnormalsToZero()) { if (context.flushSubnormalsToZero()) {
currentFenv_.__fpcr |= (1U << 24); // control register currentFenv_.__fpcr |= (1U << 24); // control register
} else { } else {
currentFenv_.__fpcr &= ~(1U << 24); // control register currentFenv_.__fpcr &= ~(1U << 24); // control register
} }
#elif defined(__BIONIC__) #elif defined(__BIONIC__)
hasSubnormalFlushingHardwareControl_ = true; hasSubnormalFlushingHardwareControl_ = true;
if (context.flushSubnormalsToZero()) { if (context.flushSubnormalsToZero()) {
currentFenv_.__control |= (1U << 24); // control register currentFenv_.__control |= (1U << 24); // control register
} else { } else {
currentFenv_.__control &= ~(1U << 24); // control register currentFenv_.__control &= ~(1U << 24); // control register
} }
#else #else
// If F18 is built with other C libraries on AArch64, software flushing will // If F18 is built with other C libraries on AArch64, software flushing will
@ -76,10 +76,18 @@ void HostFloatingPointEnvironment::SetUpHostFloatingPointEnvironment(
return; return;
} }
switch (context.rounding().mode) { switch (context.rounding().mode) {
case common::RoundingMode::TiesToEven: fesetround(FE_TONEAREST); break; case common::RoundingMode::TiesToEven:
case common::RoundingMode::ToZero: fesetround(FE_TOWARDZERO); break; fesetround(FE_TONEAREST);
case common::RoundingMode::Up: fesetround(FE_UPWARD); break; break;
case common::RoundingMode::Down: fesetround(FE_DOWNWARD); break; case common::RoundingMode::ToZero:
fesetround(FE_TOWARDZERO);
break;
case common::RoundingMode::Up:
fesetround(FE_UPWARD);
break;
case common::RoundingMode::Down:
fesetround(FE_DOWNWARD);
break;
case common::RoundingMode::TiesAwayFromZero: case common::RoundingMode::TiesAwayFromZero:
fesetround(FE_TONEAREST); fesetround(FE_TONEAREST);
context.messages().Say( context.messages().Say(
@ -135,4 +143,4 @@ void HostFloatingPointEnvironment::CheckAndRestoreFloatingPointEnvironment(
} }
errno = 0; errno = 0;
} }
} } // namespace Fortran::evaluate::host

View File

@ -48,14 +48,14 @@ private:
}; };
// Type mapping from F18 types to host types // Type mapping from F18 types to host types
struct UnsupportedType {}; // There is no host type for the F18 type struct UnsupportedType {}; // There is no host type for the F18 type
template<typename FTN_T> struct HostTypeHelper { template <typename FTN_T> struct HostTypeHelper {
using Type = UnsupportedType; using Type = UnsupportedType;
}; };
template<typename FTN_T> using HostType = typename HostTypeHelper<FTN_T>::Type; template <typename FTN_T> using HostType = typename HostTypeHelper<FTN_T>::Type;
template<typename... T> constexpr inline bool HostTypeExists() { template <typename... T> constexpr inline bool HostTypeExists() {
return (... && (!std::is_same_v<HostType<T>, UnsupportedType>)); return (... && (!std::is_same_v<HostType<T>, UnsupportedType>));
} }
@ -64,7 +64,7 @@ template<typename... T> constexpr inline bool HostTypeExists() {
// duplication. // duplication.
// Scalar conversion utilities from host scalars to F18 scalars // Scalar conversion utilities from host scalars to F18 scalars
template<typename FTN_T> template <typename FTN_T>
inline constexpr Scalar<FTN_T> CastHostToFortran(const HostType<FTN_T> &x) { inline constexpr Scalar<FTN_T> CastHostToFortran(const HostType<FTN_T> &x) {
static_assert(HostTypeExists<FTN_T>()); static_assert(HostTypeExists<FTN_T>());
if constexpr (FTN_T::category == TypeCategory::Complex && if constexpr (FTN_T::category == TypeCategory::Complex &&
@ -79,7 +79,7 @@ inline constexpr Scalar<FTN_T> CastHostToFortran(const HostType<FTN_T> &x) {
} }
// Scalar conversion utilities from F18 scalars to host scalars // Scalar conversion utilities from F18 scalars to host scalars
template<typename FTN_T> template <typename FTN_T>
inline constexpr HostType<FTN_T> CastFortranToHost(const Scalar<FTN_T> &x) { inline constexpr HostType<FTN_T> CastFortranToHost(const Scalar<FTN_T> &x) {
static_assert(HostTypeExists<FTN_T>()); static_assert(HostTypeExists<FTN_T>());
if constexpr (FTN_T::category == TypeCategory::Complex && if constexpr (FTN_T::category == TypeCategory::Complex &&
@ -93,40 +93,40 @@ inline constexpr HostType<FTN_T> CastFortranToHost(const Scalar<FTN_T> &x) {
} }
} }
template<typename T> struct BiggerOrSameHostTypeHelper { template <typename T> struct BiggerOrSameHostTypeHelper {
using Type = using Type =
std::conditional_t<HostTypeExists<T>(), HostType<T>, UnsupportedType>; std::conditional_t<HostTypeExists<T>(), HostType<T>, UnsupportedType>;
using FortranType = T; using FortranType = T;
}; };
template<typename FTN_T> template <typename FTN_T>
using BiggerOrSameHostType = typename BiggerOrSameHostTypeHelper<FTN_T>::Type; using BiggerOrSameHostType = typename BiggerOrSameHostTypeHelper<FTN_T>::Type;
template<typename FTN_T> template <typename FTN_T>
using BiggerOrSameFortranTypeSupportedOnHost = using BiggerOrSameFortranTypeSupportedOnHost =
typename BiggerOrSameHostTypeHelper<FTN_T>::FortranType; typename BiggerOrSameHostTypeHelper<FTN_T>::FortranType;
template<typename... T> constexpr inline bool BiggerOrSameHostTypeExists() { template <typename... T> constexpr inline bool BiggerOrSameHostTypeExists() {
return (... && (!std::is_same_v<BiggerOrSameHostType<T>, UnsupportedType>)); return (... && (!std::is_same_v<BiggerOrSameHostType<T>, UnsupportedType>));
} }
// Defining the actual mapping // Defining the actual mapping
template<> struct HostTypeHelper<Type<TypeCategory::Integer, 1>> { template <> struct HostTypeHelper<Type<TypeCategory::Integer, 1>> {
using Type = std::int8_t; using Type = std::int8_t;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Integer, 2>> { template <> struct HostTypeHelper<Type<TypeCategory::Integer, 2>> {
using Type = std::int16_t; using Type = std::int16_t;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Integer, 4>> { template <> struct HostTypeHelper<Type<TypeCategory::Integer, 4>> {
using Type = std::int32_t; using Type = std::int32_t;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Integer, 8>> { template <> struct HostTypeHelper<Type<TypeCategory::Integer, 8>> {
using Type = std::int64_t; using Type = std::int64_t;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Integer, 16>> { template <> struct HostTypeHelper<Type<TypeCategory::Integer, 16>> {
#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__) #if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
using Type = __int128_t; using Type = __int128_t;
#else #else
@ -137,21 +137,21 @@ template<> struct HostTypeHelper<Type<TypeCategory::Integer, 16>> {
// TODO no mapping to host types are defined currently for 16bits float // TODO no mapping to host types are defined currently for 16bits float
// It should be defined when gcc/clang have a better support for it. // It should be defined when gcc/clang have a better support for it.
template<> struct HostTypeHelper<Type<TypeCategory::Real, 4>> { template <> struct HostTypeHelper<Type<TypeCategory::Real, 4>> {
// IEE 754 64bits // IEE 754 64bits
using Type = std::conditional_t<sizeof(float) == 4 && using Type = std::conditional_t<sizeof(float) == 4 &&
std::numeric_limits<float>::is_iec559, std::numeric_limits<float>::is_iec559,
float, UnsupportedType>; float, UnsupportedType>;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Real, 8>> { template <> struct HostTypeHelper<Type<TypeCategory::Real, 8>> {
// IEE 754 64bits // IEE 754 64bits
using Type = std::conditional_t<sizeof(double) == 8 && using Type = std::conditional_t<sizeof(double) == 8 &&
std::numeric_limits<double>::is_iec559, std::numeric_limits<double>::is_iec559,
double, UnsupportedType>; double, UnsupportedType>;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Real, 10>> { template <> struct HostTypeHelper<Type<TypeCategory::Real, 10>> {
// X87 80bits // X87 80bits
using Type = std::conditional_t<sizeof(long double) >= 10 && using Type = std::conditional_t<sizeof(long double) >= 10 &&
std::numeric_limits<long double>::digits == 64 && std::numeric_limits<long double>::digits == 64 &&
@ -159,7 +159,7 @@ template<> struct HostTypeHelper<Type<TypeCategory::Real, 10>> {
long double, UnsupportedType>; long double, UnsupportedType>;
}; };
template<> struct HostTypeHelper<Type<TypeCategory::Real, 16>> { template <> struct HostTypeHelper<Type<TypeCategory::Real, 16>> {
// IEE 754 128bits // IEE 754 128bits
using Type = std::conditional_t<sizeof(long double) == 16 && using Type = std::conditional_t<sizeof(long double) == 16 &&
std::numeric_limits<long double>::digits == 113 && std::numeric_limits<long double>::digits == 113 &&
@ -167,30 +167,30 @@ template<> struct HostTypeHelper<Type<TypeCategory::Real, 16>> {
long double, UnsupportedType>; long double, UnsupportedType>;
}; };
template<int KIND> struct HostTypeHelper<Type<TypeCategory::Complex, KIND>> { template <int KIND> struct HostTypeHelper<Type<TypeCategory::Complex, KIND>> {
using RealT = Fortran::evaluate::Type<TypeCategory::Real, KIND>; using RealT = Fortran::evaluate::Type<TypeCategory::Real, KIND>;
using Type = std::conditional_t<HostTypeExists<RealT>(), using Type = std::conditional_t<HostTypeExists<RealT>(),
std::complex<HostType<RealT>>, UnsupportedType>; std::complex<HostType<RealT>>, UnsupportedType>;
}; };
template<int KIND> struct HostTypeHelper<Type<TypeCategory::Logical, KIND>> { template <int KIND> struct HostTypeHelper<Type<TypeCategory::Logical, KIND>> {
using Type = std::conditional_t<KIND <= 8, std::uint8_t, UnsupportedType>; using Type = std::conditional_t<KIND <= 8, std::uint8_t, UnsupportedType>;
}; };
template<int KIND> struct HostTypeHelper<Type<TypeCategory::Character, KIND>> { template <int KIND> struct HostTypeHelper<Type<TypeCategory::Character, KIND>> {
using Type = using Type =
Scalar<typename Fortran::evaluate::Type<TypeCategory::Character, KIND>>; Scalar<typename Fortran::evaluate::Type<TypeCategory::Character, KIND>>;
}; };
// Type mapping from host types to F18 types. This need to be placed after all // Type mapping from host types to F18 types. This need to be placed after all
// HostTypeHelper specializations. // HostTypeHelper specializations.
template<typename T, typename... TT> struct IndexInTupleHelper {}; template <typename T, typename... TT> struct IndexInTupleHelper {};
template<typename T, typename... TT> template <typename T, typename... TT>
struct IndexInTupleHelper<T, std::tuple<TT...>> { struct IndexInTupleHelper<T, std::tuple<TT...>> {
static constexpr int value{common::TypeIndex<T, TT...>}; static constexpr int value{common::TypeIndex<T, TT...>};
}; };
struct UnknownType {}; // the host type does not match any F18 types struct UnknownType {}; // the host type does not match any F18 types
template<typename HOST_T> struct FortranTypeHelper { template <typename HOST_T> struct FortranTypeHelper {
using HostTypeMapping = using HostTypeMapping =
common::MapTemplate<HostType, AllIntrinsicTypes, std::tuple>; common::MapTemplate<HostType, AllIntrinsicTypes, std::tuple>;
static constexpr int index{ static constexpr int index{
@ -202,38 +202,38 @@ template<typename HOST_T> struct FortranTypeHelper {
UnknownType>; UnknownType>;
}; };
template<typename HOST_T> template <typename HOST_T>
using FortranType = typename FortranTypeHelper<HOST_T>::Type; using FortranType = typename FortranTypeHelper<HOST_T>::Type;
template<typename... HT> constexpr inline bool FortranTypeExists() { template <typename... HT> constexpr inline bool FortranTypeExists() {
return (... && (!std::is_same_v<FortranType<HT>, UnknownType>)); return (... && (!std::is_same_v<FortranType<HT>, UnknownType>));
} }
// Utility to find "bigger" types that exist on host. By bigger, it is meant // Utility to find "bigger" types that exist on host. By bigger, it is meant
// that the bigger type can represent all the values of the smaller types // that the bigger type can represent all the values of the smaller types
// without information loss. // without information loss.
template<TypeCategory cat, int KIND> struct NextBiggerReal { template <TypeCategory cat, int KIND> struct NextBiggerReal {
using Type = void; using Type = void;
}; };
template<TypeCategory cat> struct NextBiggerReal<cat, 2> { template <TypeCategory cat> struct NextBiggerReal<cat, 2> {
using Type = Fortran::evaluate::Type<cat, 4>; using Type = Fortran::evaluate::Type<cat, 4>;
}; };
template<TypeCategory cat> struct NextBiggerReal<cat, 3> { template <TypeCategory cat> struct NextBiggerReal<cat, 3> {
using Type = Fortran::evaluate::Type<cat, 4>; using Type = Fortran::evaluate::Type<cat, 4>;
}; };
template<TypeCategory cat> struct NextBiggerReal<cat, 4> { template <TypeCategory cat> struct NextBiggerReal<cat, 4> {
using Type = Fortran::evaluate::Type<cat, 8>; using Type = Fortran::evaluate::Type<cat, 8>;
}; };
template<TypeCategory cat> struct NextBiggerReal<cat, 8> { template <TypeCategory cat> struct NextBiggerReal<cat, 8> {
using Type = Fortran::evaluate::Type<cat, 10>; using Type = Fortran::evaluate::Type<cat, 10>;
}; };
template<TypeCategory cat> struct NextBiggerReal<cat, 10> { template <TypeCategory cat> struct NextBiggerReal<cat, 10> {
using Type = Fortran::evaluate::Type<cat, 16>; using Type = Fortran::evaluate::Type<cat, 16>;
}; };
template<int KIND> template <int KIND>
struct BiggerOrSameHostTypeHelper<Type<TypeCategory::Real, KIND>> { struct BiggerOrSameHostTypeHelper<Type<TypeCategory::Real, KIND>> {
using T = Fortran::evaluate::Type<TypeCategory::Real, KIND>; using T = Fortran::evaluate::Type<TypeCategory::Real, KIND>;
using NextT = typename NextBiggerReal<TypeCategory::Real, KIND>::Type; using NextT = typename NextBiggerReal<TypeCategory::Real, KIND>::Type;
@ -243,7 +243,7 @@ struct BiggerOrSameHostTypeHelper<Type<TypeCategory::Real, KIND>> {
typename BiggerOrSameHostTypeHelper<NextT>::FortranType>; typename BiggerOrSameHostTypeHelper<NextT>::FortranType>;
}; };
template<int KIND> template <int KIND>
struct BiggerOrSameHostTypeHelper<Type<TypeCategory::Complex, KIND>> { struct BiggerOrSameHostTypeHelper<Type<TypeCategory::Complex, KIND>> {
using T = Fortran::evaluate::Type<TypeCategory::Complex, KIND>; using T = Fortran::evaluate::Type<TypeCategory::Complex, KIND>;
using NextT = typename NextBiggerReal<TypeCategory::Complex, KIND>::Type; using NextT = typename NextBiggerReal<TypeCategory::Complex, KIND>::Type;
@ -252,7 +252,7 @@ struct BiggerOrSameHostTypeHelper<Type<TypeCategory::Complex, KIND>> {
using FortranType = std::conditional_t<HostTypeExists<T>(), T, using FortranType = std::conditional_t<HostTypeExists<T>(), T,
typename BiggerOrSameHostTypeHelper<NextT>::FortranType>; typename BiggerOrSameHostTypeHelper<NextT>::FortranType>;
}; };
} } // namespace host
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_HOST_H_ #endif // FORTRAN_EVALUATE_HOST_H_

View File

@ -15,7 +15,7 @@
namespace Fortran::evaluate { namespace Fortran::evaluate {
template<typename REAL, typename INT> template <typename REAL, typename INT>
ValueWithRealFlags<REAL> TimesIntPowerOf(const REAL &factor, const REAL &base, ValueWithRealFlags<REAL> TimesIntPowerOf(const REAL &factor, const REAL &base,
const INT &power, Rounding rounding = defaultRounding) { const INT &power, Rounding rounding = defaultRounding) {
ValueWithRealFlags<REAL> result{factor}; ValueWithRealFlags<REAL> result{factor};
@ -48,11 +48,11 @@ ValueWithRealFlags<REAL> TimesIntPowerOf(const REAL &factor, const REAL &base,
return result; return result;
} }
template<typename REAL, typename INT> template <typename REAL, typename INT>
ValueWithRealFlags<REAL> IntPower( ValueWithRealFlags<REAL> IntPower(
const REAL &base, const INT &power, Rounding rounding = defaultRounding) { const REAL &base, const INT &power, Rounding rounding = defaultRounding) {
REAL one{REAL::FromInteger(INT{1}).value}; REAL one{REAL::FromInteger(INT{1}).value};
return TimesIntPowerOf(one, base, power, rounding); return TimesIntPowerOf(one, base, power, rounding);
} }
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_INT_POWER_H_ #endif // FORTRAN_EVALUATE_INT_POWER_H_

View File

@ -28,4 +28,4 @@ static_assert(Integer<64>::partBits == 32);
static_assert(std::is_same_v<typename Integer<64>::Part, std::uint32_t>); static_assert(std::is_same_v<typename Integer<64>::Part, std::uint32_t>);
static_assert(Integer<128>::partBits == 32); static_assert(Integer<128>::partBits == 32);
static_assert(std::is_same_v<typename Integer<128>::Part, std::uint32_t>); static_assert(std::is_same_v<typename Integer<128>::Part, std::uint32_t>);
} } // namespace Fortran::evaluate::value

View File

@ -29,8 +29,8 @@ namespace Fortran::evaluate {
// Define meaningful types for the runtime // Define meaningful types for the runtime
using RuntimeTypes = evaluate::AllIntrinsicTypes; using RuntimeTypes = evaluate::AllIntrinsicTypes;
template<typename T, typename... TT> struct IndexInTupleHelper {}; template <typename T, typename... TT> struct IndexInTupleHelper {};
template<typename T, typename... TT> template <typename T, typename... TT>
struct IndexInTupleHelper<T, std::tuple<TT...>> { struct IndexInTupleHelper<T, std::tuple<TT...>> {
static constexpr TypeCode value{common::TypeIndex<T, TT...>}; static constexpr TypeCode value{common::TypeIndex<T, TT...>};
}; };
@ -38,36 +38,36 @@ struct IndexInTupleHelper<T, std::tuple<TT...>> {
static_assert( static_assert(
std::tuple_size_v<RuntimeTypes> < std::numeric_limits<TypeCode>::max(), std::tuple_size_v<RuntimeTypes> < std::numeric_limits<TypeCode>::max(),
"TypeCode is too small"); "TypeCode is too small");
template<typename T> template <typename T>
inline constexpr TypeCode typeCodeOf{ inline constexpr TypeCode typeCodeOf{
IndexInTupleHelper<T, RuntimeTypes>::value}; IndexInTupleHelper<T, RuntimeTypes>::value};
template<TypeCode n> template <TypeCode n>
using RuntimeTypeOf = typename std::tuple_element_t<n, RuntimeTypes>; using RuntimeTypeOf = typename std::tuple_element_t<n, RuntimeTypes>;
template<typename TA, PassBy Pass> template <typename TA, PassBy Pass>
using HostArgType = std::conditional_t<Pass == PassBy::Ref, using HostArgType = std::conditional_t<Pass == PassBy::Ref,
std::add_lvalue_reference_t<std::add_const_t<host::HostType<TA>>>, std::add_lvalue_reference_t<std::add_const_t<host::HostType<TA>>>,
host::HostType<TA>>; host::HostType<TA>>;
template<typename TR, typename... ArgInfo> template <typename TR, typename... ArgInfo>
using HostFuncPointer = FuncPointer<host::HostType<TR>, using HostFuncPointer = FuncPointer<host::HostType<TR>,
HostArgType<typename ArgInfo::Type, ArgInfo::pass>...>; HostArgType<typename ArgInfo::Type, ArgInfo::pass>...>;
// Software Subnormal Flushing helper. // Software Subnormal Flushing helper.
template<typename T> struct Flusher { template <typename T> struct Flusher {
// Only flush floating-points. Forward other scalars untouched. // Only flush floating-points. Forward other scalars untouched.
static constexpr inline const Scalar<T> &FlushSubnormals(const Scalar<T> &x) { static constexpr inline const Scalar<T> &FlushSubnormals(const Scalar<T> &x) {
return x; return x;
} }
}; };
template<int Kind> struct Flusher<Type<TypeCategory::Real, Kind>> { template <int Kind> struct Flusher<Type<TypeCategory::Real, Kind>> {
using T = Type<TypeCategory::Real, Kind>; using T = Type<TypeCategory::Real, Kind>;
static constexpr inline Scalar<T> FlushSubnormals(const Scalar<T> &x) { static constexpr inline Scalar<T> FlushSubnormals(const Scalar<T> &x) {
return x.FlushSubnormalToZero(); return x.FlushSubnormalToZero();
} }
}; };
template<int Kind> struct Flusher<Type<TypeCategory::Complex, Kind>> { template <int Kind> struct Flusher<Type<TypeCategory::Complex, Kind>> {
using T = Type<TypeCategory::Complex, Kind>; using T = Type<TypeCategory::Complex, Kind>;
static constexpr inline Scalar<T> FlushSubnormals(const Scalar<T> &x) { static constexpr inline Scalar<T> FlushSubnormals(const Scalar<T> &x) {
return x.FlushSubnormalToZero(); return x.FlushSubnormalToZero();
@ -75,7 +75,7 @@ template<int Kind> struct Flusher<Type<TypeCategory::Complex, Kind>> {
}; };
// Callable factory // Callable factory
template<typename TR, typename... ArgInfo> struct CallableHostWrapper { template <typename TR, typename... ArgInfo> struct CallableHostWrapper {
static Scalar<TR> scalarCallable(FoldingContext &context, static Scalar<TR> scalarCallable(FoldingContext &context,
HostFuncPointer<TR, ArgInfo...> func, HostFuncPointer<TR, ArgInfo...> func,
const Scalar<typename ArgInfo::Type> &... x) { const Scalar<typename ArgInfo::Type> &... x) {
@ -120,28 +120,28 @@ template<typename TR, typename... ArgInfo> struct CallableHostWrapper {
} }
}; };
template<typename TR, typename... TA> template <typename TR, typename... TA>
inline GenericFunctionPointer ToGenericFunctionPointer( inline GenericFunctionPointer ToGenericFunctionPointer(
FuncPointer<TR, TA...> f) { FuncPointer<TR, TA...> f) {
return reinterpret_cast<GenericFunctionPointer>(f); return reinterpret_cast<GenericFunctionPointer>(f);
} }
template<typename TR, typename... TA> template <typename TR, typename... TA>
inline FuncPointer<TR, TA...> FromGenericFunctionPointer( inline FuncPointer<TR, TA...> FromGenericFunctionPointer(
GenericFunctionPointer g) { GenericFunctionPointer g) {
return reinterpret_cast<FuncPointer<TR, TA...>>(g); return reinterpret_cast<FuncPointer<TR, TA...>>(g);
} }
template<typename TR, typename... ArgInfo> template <typename TR, typename... ArgInfo>
IntrinsicProcedureRuntimeDescription::IntrinsicProcedureRuntimeDescription( IntrinsicProcedureRuntimeDescription::IntrinsicProcedureRuntimeDescription(
const Signature<TR, ArgInfo...> &signature, bool isElemental) const Signature<TR, ArgInfo...> &signature, bool isElemental)
: name{signature.name}, returnType{typeCodeOf<TR>}, : name{signature.name}, returnType{typeCodeOf<TR>},
argumentsType{typeCodeOf<typename ArgInfo::Type>...}, argumentsType{typeCodeOf<typename ArgInfo::Type>...},
argumentsPassedBy{ArgInfo::pass...}, isElemental{isElemental}, argumentsPassedBy{ArgInfo::pass...}, isElemental{isElemental},
callable{ToGenericFunctionPointer( callable{ToGenericFunctionPointer(
CallableHostWrapper<TR, ArgInfo...>::MakeScalarCallable())} {} CallableHostWrapper<TR, ArgInfo...>::MakeScalarCallable())} {}
template<typename HostTA> static constexpr inline PassBy PassByMethod() { template <typename HostTA> static constexpr inline PassBy PassByMethod() {
if constexpr (std::is_pointer_v<std::decay_t<HostTA>> || if constexpr (std::is_pointer_v<std::decay_t<HostTA>> ||
std::is_lvalue_reference_v<HostTA>) { std::is_lvalue_reference_v<HostTA>) {
return PassBy::Ref; return PassBy::Ref;
@ -149,24 +149,24 @@ template<typename HostTA> static constexpr inline PassBy PassByMethod() {
return PassBy::Val; return PassBy::Val;
} }
template<typename HostTA> template <typename HostTA>
using ArgInfoFromHostType = using ArgInfoFromHostType =
ArgumentInfo<host::FortranType<std::remove_pointer_t<std::decay_t<HostTA>>>, ArgumentInfo<host::FortranType<std::remove_pointer_t<std::decay_t<HostTA>>>,
PassByMethod<HostTA>()>; PassByMethod<HostTA>()>;
template<typename HostTR, typename... HostTA> template <typename HostTR, typename... HostTA>
using SignatureFromHostFuncPointer = using SignatureFromHostFuncPointer =
Signature<host::FortranType<HostTR>, ArgInfoFromHostType<HostTA>...>; Signature<host::FortranType<HostTR>, ArgInfoFromHostType<HostTA>...>;
template<typename HostTR, typename... HostTA> template <typename HostTR, typename... HostTA>
HostRuntimeIntrinsicProcedure::HostRuntimeIntrinsicProcedure( HostRuntimeIntrinsicProcedure::HostRuntimeIntrinsicProcedure(
const std::string &name, FuncPointer<HostTR, HostTA...> func, const std::string &name, FuncPointer<HostTR, HostTA...> func,
bool isElemental) bool isElemental)
: IntrinsicProcedureRuntimeDescription( : IntrinsicProcedureRuntimeDescription(
SignatureFromHostFuncPointer<HostTR, HostTA...>{name}, isElemental), SignatureFromHostFuncPointer<HostTR, HostTA...>{name}, isElemental),
handle{ToGenericFunctionPointer(func)} {} handle{ToGenericFunctionPointer(func)} {}
template<template<typename> typename ConstantContainer, typename TR, template <template <typename> typename ConstantContainer, typename TR,
typename... TA> typename... TA>
std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>> std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>>
HostIntrinsicProceduresLibrary::GetHostProcedureWrapper( HostIntrinsicProceduresLibrary::GetHostProcedureWrapper(
@ -205,5 +205,5 @@ HostIntrinsicProceduresLibrary::GetHostProcedureWrapper(
return std::nullopt; return std::nullopt;
} }
} } // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_TEMPLATES_H_ #endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_TEMPLATES_H_

View File

@ -46,7 +46,7 @@ bool HostIntrinsicProceduresLibrary::HasEquivalentProcedure(
// Define which host runtime functions will be used for folding // Define which host runtime functions will be used for folding
template<typename HostT> template <typename HostT>
static void AddLibmRealHostProcedures( static void AddLibmRealHostProcedures(
HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) { HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) {
using F = FuncPointer<HostT, HostT>; using F = FuncPointer<HostT, HostT>;
@ -96,7 +96,7 @@ static void AddLibmRealHostProcedures(
} }
} }
template<typename HostT> template <typename HostT>
static void AddLibmComplexHostProcedures( static void AddLibmComplexHostProcedures(
HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) { HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) {
using F = FuncPointer<std::complex<HostT>, const std::complex<HostT> &>; using F = FuncPointer<std::complex<HostT>, const std::complex<HostT> &>;
@ -207,21 +207,21 @@ enum class I {
enum class L { F, R, P }; enum class L { F, R, P };
struct NoSuchRuntimeSymbol {}; struct NoSuchRuntimeSymbol {};
template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}}; template <L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
// Macros to declare fast/relaxed/precise libpgmath variants. // Macros to declare fast/relaxed/precise libpgmath variants.
#define DECLARE_PGMATH_FAST_REAL(func) \ #define DECLARE_PGMATH_FAST_REAL(func) \
extern "C" float __fs_##func##_1(float); \ extern "C" float __fs_##func##_1(float); \
extern "C" double __fd_##func##_1(double); \ extern "C" double __fd_##func##_1(double); \
template<> constexpr auto Sym<L::F, I::func, float>{__fs_##func##_1}; \ template <> constexpr auto Sym<L::F, I::func, float>{__fs_##func##_1}; \
template<> constexpr auto Sym<L::F, I::func, double>{__fd_##func##_1}; template <> constexpr auto Sym<L::F, I::func, double>{__fd_##func##_1};
#define DECLARE_PGMATH_FAST_COMPLEX(func) \ #define DECLARE_PGMATH_FAST_COMPLEX(func) \
extern "C" float _Complex __fc_##func##_1(float _Complex); \ extern "C" float _Complex __fc_##func##_1(float _Complex); \
extern "C" double _Complex __fz_##func##_1(double _Complex); \ extern "C" double _Complex __fz_##func##_1(double _Complex); \
template<> \ template <> \
constexpr auto Sym<L::F, I::func, std::complex<float>>{__fc_##func##_1}; \ constexpr auto Sym<L::F, I::func, std::complex<float>>{__fc_##func##_1}; \
template<> \ template <> \
constexpr auto Sym<L::F, I::func, std::complex<double>>{__fz_##func##_1}; constexpr auto Sym<L::F, I::func, std::complex<double>>{__fz_##func##_1};
#define DECLARE_PGMATH_FAST_ALL_FP(func) \ #define DECLARE_PGMATH_FAST_ALL_FP(func) \
@ -231,15 +231,15 @@ template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
#define DECLARE_PGMATH_PRECISE_REAL(func) \ #define DECLARE_PGMATH_PRECISE_REAL(func) \
extern "C" float __ps_##func##_1(float); \ extern "C" float __ps_##func##_1(float); \
extern "C" double __pd_##func##_1(double); \ extern "C" double __pd_##func##_1(double); \
template<> constexpr auto Sym<L::P, I::func, float>{__ps_##func##_1}; \ template <> constexpr auto Sym<L::P, I::func, float>{__ps_##func##_1}; \
template<> constexpr auto Sym<L::P, I::func, double>{__pd_##func##_1}; template <> constexpr auto Sym<L::P, I::func, double>{__pd_##func##_1};
#define DECLARE_PGMATH_PRECISE_COMPLEX(func) \ #define DECLARE_PGMATH_PRECISE_COMPLEX(func) \
extern "C" float _Complex __pc_##func##_1(float _Complex); \ extern "C" float _Complex __pc_##func##_1(float _Complex); \
extern "C" double _Complex __pz_##func##_1(double _Complex); \ extern "C" double _Complex __pz_##func##_1(double _Complex); \
template<> \ template <> \
constexpr auto Sym<L::P, I::func, std::complex<float>>{__pc_##func##_1}; \ constexpr auto Sym<L::P, I::func, std::complex<float>>{__pc_##func##_1}; \
template<> \ template <> \
constexpr auto Sym<L::P, I::func, std::complex<double>>{__pz_##func##_1}; constexpr auto Sym<L::P, I::func, std::complex<double>>{__pz_##func##_1};
#define DECLARE_PGMATH_PRECISE_ALL_FP(func) \ #define DECLARE_PGMATH_PRECISE_ALL_FP(func) \
@ -249,15 +249,15 @@ template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
#define DECLARE_PGMATH_RELAXED_REAL(func) \ #define DECLARE_PGMATH_RELAXED_REAL(func) \
extern "C" float __rs_##func##_1(float); \ extern "C" float __rs_##func##_1(float); \
extern "C" double __rd_##func##_1(double); \ extern "C" double __rd_##func##_1(double); \
template<> constexpr auto Sym<L::R, I::func, float>{__rs_##func##_1}; \ template <> constexpr auto Sym<L::R, I::func, float>{__rs_##func##_1}; \
template<> constexpr auto Sym<L::R, I::func, double>{__rd_##func##_1}; template <> constexpr auto Sym<L::R, I::func, double>{__rd_##func##_1};
#define DECLARE_PGMATH_RELAXED_COMPLEX(func) \ #define DECLARE_PGMATH_RELAXED_COMPLEX(func) \
extern "C" float _Complex __rc_##func##_1(float _Complex); \ extern "C" float _Complex __rc_##func##_1(float _Complex); \
extern "C" double _Complex __rz_##func##_1(double _Complex); \ extern "C" double _Complex __rz_##func##_1(double _Complex); \
template<> \ template <> \
constexpr auto Sym<L::R, I::func, std::complex<float>>{__rc_##func##_1}; \ constexpr auto Sym<L::R, I::func, std::complex<float>>{__rc_##func##_1}; \
template<> \ template <> \
constexpr auto Sym<L::R, I::func, std::complex<double>>{__rz_##func##_1}; constexpr auto Sym<L::R, I::func, std::complex<double>>{__rz_##func##_1};
#define DECLARE_PGMATH_RELAXED_ALL_FP(func) \ #define DECLARE_PGMATH_RELAXED_ALL_FP(func) \
@ -282,16 +282,16 @@ template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
#define DECLARE_PGMATH_FAST_REAL2(func) \ #define DECLARE_PGMATH_FAST_REAL2(func) \
extern "C" float __fs_##func##_1(float, float); \ extern "C" float __fs_##func##_1(float, float); \
extern "C" double __fd_##func##_1(double, double); \ extern "C" double __fd_##func##_1(double, double); \
template<> constexpr auto Sym<L::F, I::func, float>{__fs_##func##_1}; \ template <> constexpr auto Sym<L::F, I::func, float>{__fs_##func##_1}; \
template<> constexpr auto Sym<L::F, I::func, double>{__fd_##func##_1}; template <> constexpr auto Sym<L::F, I::func, double>{__fd_##func##_1};
#define DECLARE_PGMATH_FAST_COMPLEX2(func) \ #define DECLARE_PGMATH_FAST_COMPLEX2(func) \
extern "C" float _Complex __fc_##func##_1(float _Complex, float _Complex); \ extern "C" float _Complex __fc_##func##_1(float _Complex, float _Complex); \
extern "C" double _Complex __fz_##func##_1( \ extern "C" double _Complex __fz_##func##_1( \
double _Complex, double _Complex); \ double _Complex, double _Complex); \
template<> \ template <> \
constexpr auto Sym<L::F, I::func, std::complex<float>>{__fc_##func##_1}; \ constexpr auto Sym<L::F, I::func, std::complex<float>>{__fc_##func##_1}; \
template<> \ template <> \
constexpr auto Sym<L::F, I::func, std::complex<double>>{__fz_##func##_1}; constexpr auto Sym<L::F, I::func, std::complex<double>>{__fz_##func##_1};
#define DECLARE_PGMATH_FAST_ALL_FP2(func) \ #define DECLARE_PGMATH_FAST_ALL_FP2(func) \
@ -301,16 +301,16 @@ template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
#define DECLARE_PGMATH_PRECISE_REAL2(func) \ #define DECLARE_PGMATH_PRECISE_REAL2(func) \
extern "C" float __ps_##func##_1(float, float); \ extern "C" float __ps_##func##_1(float, float); \
extern "C" double __pd_##func##_1(double, double); \ extern "C" double __pd_##func##_1(double, double); \
template<> constexpr auto Sym<L::P, I::func, float>{__ps_##func##_1}; \ template <> constexpr auto Sym<L::P, I::func, float>{__ps_##func##_1}; \
template<> constexpr auto Sym<L::P, I::func, double>{__pd_##func##_1}; template <> constexpr auto Sym<L::P, I::func, double>{__pd_##func##_1};
#define DECLARE_PGMATH_PRECISE_COMPLEX2(func) \ #define DECLARE_PGMATH_PRECISE_COMPLEX2(func) \
extern "C" float _Complex __pc_##func##_1(float _Complex, float _Complex); \ extern "C" float _Complex __pc_##func##_1(float _Complex, float _Complex); \
extern "C" double _Complex __pz_##func##_1( \ extern "C" double _Complex __pz_##func##_1( \
double _Complex, double _Complex); \ double _Complex, double _Complex); \
template<> \ template <> \
constexpr auto Sym<L::P, I::func, std::complex<float>>{__pc_##func##_1}; \ constexpr auto Sym<L::P, I::func, std::complex<float>>{__pc_##func##_1}; \
template<> \ template <> \
constexpr auto Sym<L::P, I::func, std::complex<double>>{__pz_##func##_1}; constexpr auto Sym<L::P, I::func, std::complex<double>>{__pz_##func##_1};
#define DECLARE_PGMATH_PRECISE_ALL_FP2(func) \ #define DECLARE_PGMATH_PRECISE_ALL_FP2(func) \
@ -320,16 +320,16 @@ template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
#define DECLARE_PGMATH_RELAXED_REAL2(func) \ #define DECLARE_PGMATH_RELAXED_REAL2(func) \
extern "C" float __rs_##func##_1(float, float); \ extern "C" float __rs_##func##_1(float, float); \
extern "C" double __rd_##func##_1(double, double); \ extern "C" double __rd_##func##_1(double, double); \
template<> constexpr auto Sym<L::R, I::func, float>{__rs_##func##_1}; \ template <> constexpr auto Sym<L::R, I::func, float>{__rs_##func##_1}; \
template<> constexpr auto Sym<L::R, I::func, double>{__rd_##func##_1}; template <> constexpr auto Sym<L::R, I::func, double>{__rd_##func##_1};
#define DECLARE_PGMATH_RELAXED_COMPLEX2(func) \ #define DECLARE_PGMATH_RELAXED_COMPLEX2(func) \
extern "C" float _Complex __rc_##func##_1(float _Complex, float _Complex); \ extern "C" float _Complex __rc_##func##_1(float _Complex, float _Complex); \
extern "C" double _Complex __rz_##func##_1( \ extern "C" double _Complex __rz_##func##_1( \
double _Complex, double _Complex); \ double _Complex, double _Complex); \
template<> \ template <> \
constexpr auto Sym<L::R, I::func, std::complex<float>>{__rc_##func##_1}; \ constexpr auto Sym<L::R, I::func, std::complex<float>>{__rc_##func##_1}; \
template<> \ template <> \
constexpr auto Sym<L::R, I::func, std::complex<double>>{__rz_##func##_1}; constexpr auto Sym<L::R, I::func, std::complex<double>>{__rz_##func##_1};
#define DECLARE_PGMATH_RELAXED_ALL_FP2(func) \ #define DECLARE_PGMATH_RELAXED_ALL_FP2(func) \
@ -354,12 +354,12 @@ template<L, I, typename> constexpr auto Sym{NoSuchRuntimeSymbol{}};
#define DECLARE_PGMATH_MTH_VERSION_REAL(func) \ #define DECLARE_PGMATH_MTH_VERSION_REAL(func) \
extern "C" float __mth_i_##func(float); \ extern "C" float __mth_i_##func(float); \
extern "C" double __mth_i_d##func(double); \ extern "C" double __mth_i_d##func(double); \
template<> constexpr auto Sym<L::F, I::func, float>{__mth_i_##func}; \ template <> constexpr auto Sym<L::F, I::func, float>{__mth_i_##func}; \
template<> constexpr auto Sym<L::F, I::func, double>{__mth_i_d##func}; \ template <> constexpr auto Sym<L::F, I::func, double>{__mth_i_d##func}; \
template<> constexpr auto Sym<L::P, I::func, float>{__mth_i_##func}; \ template <> constexpr auto Sym<L::P, I::func, float>{__mth_i_##func}; \
template<> constexpr auto Sym<L::P, I::func, double>{__mth_i_d##func}; \ template <> constexpr auto Sym<L::P, I::func, double>{__mth_i_d##func}; \
template<> constexpr auto Sym<L::R, I::func, float>{__mth_i_##func}; \ template <> constexpr auto Sym<L::R, I::func, float>{__mth_i_##func}; \
template<> constexpr auto Sym<L::R, I::func, double>{__mth_i_d##func}; template <> constexpr auto Sym<L::R, I::func, double>{__mth_i_d##func};
// Actual libpgmath declarations // Actual libpgmath declarations
DECLARE_PGMATH_ALL(acos) DECLARE_PGMATH_ALL(acos)
@ -376,20 +376,20 @@ DECLARE_PGMATH_MTH_VERSION_REAL(bessel_y1)
// bessel_jn and bessel_yn takes an int as first arg // bessel_jn and bessel_yn takes an int as first arg
extern "C" float __mth_i_bessel_jn(int, float); extern "C" float __mth_i_bessel_jn(int, float);
extern "C" double __mth_i_dbessel_jn(int, double); extern "C" double __mth_i_dbessel_jn(int, double);
template<> constexpr auto Sym<L::F, I::bessel_jn, float>{__mth_i_bessel_jn}; template <> constexpr auto Sym<L::F, I::bessel_jn, float>{__mth_i_bessel_jn};
template<> constexpr auto Sym<L::F, I::bessel_jn, double>{__mth_i_dbessel_jn}; template <> constexpr auto Sym<L::F, I::bessel_jn, double>{__mth_i_dbessel_jn};
template<> constexpr auto Sym<L::P, I::bessel_jn, float>{__mth_i_bessel_jn}; template <> constexpr auto Sym<L::P, I::bessel_jn, float>{__mth_i_bessel_jn};
template<> constexpr auto Sym<L::P, I::bessel_jn, double>{__mth_i_dbessel_jn}; template <> constexpr auto Sym<L::P, I::bessel_jn, double>{__mth_i_dbessel_jn};
template<> constexpr auto Sym<L::R, I::bessel_jn, float>{__mth_i_bessel_jn}; template <> constexpr auto Sym<L::R, I::bessel_jn, float>{__mth_i_bessel_jn};
template<> constexpr auto Sym<L::R, I::bessel_jn, double>{__mth_i_dbessel_jn}; template <> constexpr auto Sym<L::R, I::bessel_jn, double>{__mth_i_dbessel_jn};
extern "C" float __mth_i_bessel_yn(int, float); extern "C" float __mth_i_bessel_yn(int, float);
extern "C" double __mth_i_dbessel_yn(int, double); extern "C" double __mth_i_dbessel_yn(int, double);
template<> constexpr auto Sym<L::F, I::bessel_yn, float>{__mth_i_bessel_yn}; template <> constexpr auto Sym<L::F, I::bessel_yn, float>{__mth_i_bessel_yn};
template<> constexpr auto Sym<L::F, I::bessel_yn, double>{__mth_i_dbessel_yn}; template <> constexpr auto Sym<L::F, I::bessel_yn, double>{__mth_i_dbessel_yn};
template<> constexpr auto Sym<L::P, I::bessel_yn, float>{__mth_i_bessel_yn}; template <> constexpr auto Sym<L::P, I::bessel_yn, float>{__mth_i_bessel_yn};
template<> constexpr auto Sym<L::P, I::bessel_yn, double>{__mth_i_dbessel_yn}; template <> constexpr auto Sym<L::P, I::bessel_yn, double>{__mth_i_dbessel_yn};
template<> constexpr auto Sym<L::R, I::bessel_yn, float>{__mth_i_bessel_yn}; template <> constexpr auto Sym<L::R, I::bessel_yn, float>{__mth_i_bessel_yn};
template<> constexpr auto Sym<L::R, I::bessel_yn, double>{__mth_i_dbessel_yn}; template <> constexpr auto Sym<L::R, I::bessel_yn, double>{__mth_i_dbessel_yn};
DECLARE_PGMATH_ALL(cos) DECLARE_PGMATH_ALL(cos)
DECLARE_PGMATH_ALL(cosh) DECLARE_PGMATH_ALL(cosh)
DECLARE_PGMATH_MTH_VERSION_REAL(erf) DECLARE_PGMATH_MTH_VERSION_REAL(erf)
@ -399,34 +399,34 @@ DECLARE_PGMATH_ALL(exp)
DECLARE_PGMATH_MTH_VERSION_REAL(gamma) DECLARE_PGMATH_MTH_VERSION_REAL(gamma)
extern "C" float __mth_i_hypot(float, float); extern "C" float __mth_i_hypot(float, float);
extern "C" double __mth_i_dhypot(double, double); extern "C" double __mth_i_dhypot(double, double);
template<> constexpr auto Sym<L::F, I::hypot, float>{__mth_i_hypot}; template <> constexpr auto Sym<L::F, I::hypot, float>{__mth_i_hypot};
template<> constexpr auto Sym<L::F, I::hypot, double>{__mth_i_dhypot}; template <> constexpr auto Sym<L::F, I::hypot, double>{__mth_i_dhypot};
template<> constexpr auto Sym<L::P, I::hypot, float>{__mth_i_hypot}; template <> constexpr auto Sym<L::P, I::hypot, float>{__mth_i_hypot};
template<> constexpr auto Sym<L::P, I::hypot, double>{__mth_i_dhypot}; template <> constexpr auto Sym<L::P, I::hypot, double>{__mth_i_dhypot};
template<> constexpr auto Sym<L::R, I::hypot, float>{__mth_i_hypot}; template <> constexpr auto Sym<L::R, I::hypot, float>{__mth_i_hypot};
template<> constexpr auto Sym<L::R, I::hypot, double>{__mth_i_dhypot}; template <> constexpr auto Sym<L::R, I::hypot, double>{__mth_i_dhypot};
DECLARE_PGMATH_ALL(log) DECLARE_PGMATH_ALL(log)
DECLARE_PGMATH_REAL(log10) DECLARE_PGMATH_REAL(log10)
DECLARE_PGMATH_MTH_VERSION_REAL(log_gamma) DECLARE_PGMATH_MTH_VERSION_REAL(log_gamma)
// no function for modulo in libpgmath // no function for modulo in libpgmath
extern "C" float __fs_mod_1(float, float); extern "C" float __fs_mod_1(float, float);
extern "C" double __fd_mod_1(double, double); extern "C" double __fd_mod_1(double, double);
template<> constexpr auto Sym<L::F, I::mod, float>{__fs_mod_1}; template <> constexpr auto Sym<L::F, I::mod, float>{__fs_mod_1};
template<> constexpr auto Sym<L::F, I::mod, double>{__fd_mod_1}; template <> constexpr auto Sym<L::F, I::mod, double>{__fd_mod_1};
template<> constexpr auto Sym<L::P, I::mod, float>{__fs_mod_1}; template <> constexpr auto Sym<L::P, I::mod, float>{__fs_mod_1};
template<> constexpr auto Sym<L::P, I::mod, double>{__fd_mod_1}; template <> constexpr auto Sym<L::P, I::mod, double>{__fd_mod_1};
template<> constexpr auto Sym<L::R, I::mod, float>{__fs_mod_1}; template <> constexpr auto Sym<L::R, I::mod, float>{__fs_mod_1};
template<> constexpr auto Sym<L::R, I::mod, double>{__fd_mod_1}; template <> constexpr auto Sym<L::R, I::mod, double>{__fd_mod_1};
DECLARE_PGMATH_ALL2(pow) DECLARE_PGMATH_ALL2(pow)
DECLARE_PGMATH_ALL(sin) DECLARE_PGMATH_ALL(sin)
DECLARE_PGMATH_ALL(sinh) DECLARE_PGMATH_ALL(sinh)
DECLARE_PGMATH_MTH_VERSION_REAL(sqrt) DECLARE_PGMATH_MTH_VERSION_REAL(sqrt)
DECLARE_PGMATH_COMPLEX(sqrt) // real versions are __mth_i... DECLARE_PGMATH_COMPLEX(sqrt) // real versions are __mth_i...
DECLARE_PGMATH_ALL(tan) DECLARE_PGMATH_ALL(tan)
DECLARE_PGMATH_ALL(tanh) DECLARE_PGMATH_ALL(tanh)
// Fill the function map used for folding with libpgmath symbols // Fill the function map used for folding with libpgmath symbols
template<L Lib, typename HostT> template <L Lib, typename HostT>
static void AddLibpgmathRealHostProcedures( static void AddLibpgmathRealHostProcedures(
HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) { HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) {
static_assert(std::is_same_v<HostT, float> || std::is_same_v<HostT, double>); static_assert(std::is_same_v<HostT, float> || std::is_same_v<HostT, double>);
@ -437,7 +437,7 @@ static void AddLibpgmathRealHostProcedures(
{"asinh", Sym<Lib, I::asinh, HostT>, true}, {"asinh", Sym<Lib, I::asinh, HostT>, true},
{"atan", Sym<Lib, I::atan, HostT>, true}, {"atan", Sym<Lib, I::atan, HostT>, true},
{"atan", Sym<Lib, I::atan2, HostT>, {"atan", Sym<Lib, I::atan2, HostT>,
true}, // atan is also the generic name for atan2 true}, // atan is also the generic name for atan2
{"atanh", Sym<Lib, I::atanh, HostT>, true}, {"atanh", Sym<Lib, I::atanh, HostT>, true},
{"bessel_j0", Sym<Lib, I::bessel_j0, HostT>, true}, {"bessel_j0", Sym<Lib, I::bessel_j0, HostT>, true},
{"bessel_j1", Sym<Lib, I::bessel_j1, HostT>, true}, {"bessel_j1", Sym<Lib, I::bessel_j1, HostT>, true},
@ -475,19 +475,19 @@ static void AddLibpgmathRealHostProcedures(
// by a pair of register but std::complex<float> is returned by structure // by a pair of register but std::complex<float> is returned by structure
// address. To fix the issue, wrapper around C _Complex functions are defined // address. To fix the issue, wrapper around C _Complex functions are defined
// below. // below.
template<FuncPointer<float _Complex, float _Complex> func> template <FuncPointer<float _Complex, float _Complex> func>
static std::complex<float> ComplexCFuncWrapper(std::complex<float> &arg) { static std::complex<float> ComplexCFuncWrapper(std::complex<float> &arg) {
float _Complex res{func(*reinterpret_cast<float _Complex *>(&arg))}; float _Complex res{func(*reinterpret_cast<float _Complex *>(&arg))};
return *reinterpret_cast<std::complex<float> *>(&res); return *reinterpret_cast<std::complex<float> *>(&res);
} }
template<FuncPointer<double _Complex, double _Complex> func> template <FuncPointer<double _Complex, double _Complex> func>
static std::complex<double> ComplexCFuncWrapper(std::complex<double> &arg) { static std::complex<double> ComplexCFuncWrapper(std::complex<double> &arg) {
double _Complex res{func(*reinterpret_cast<double _Complex *>(&arg))}; double _Complex res{func(*reinterpret_cast<double _Complex *>(&arg))};
return *reinterpret_cast<std::complex<double> *>(&res); return *reinterpret_cast<std::complex<double> *>(&res);
} }
template<FuncPointer<float _Complex, float _Complex, float _Complex> func> template <FuncPointer<float _Complex, float _Complex, float _Complex> func>
static std::complex<float> ComplexCFuncWrapper( static std::complex<float> ComplexCFuncWrapper(
std::complex<float> &arg1, std::complex<float> &arg2) { std::complex<float> &arg1, std::complex<float> &arg2) {
float _Complex res{func(*reinterpret_cast<float _Complex *>(&arg1), float _Complex res{func(*reinterpret_cast<float _Complex *>(&arg1),
@ -495,7 +495,7 @@ static std::complex<float> ComplexCFuncWrapper(
return *reinterpret_cast<std::complex<float> *>(&res); return *reinterpret_cast<std::complex<float> *>(&res);
} }
template<FuncPointer<double _Complex, double _Complex, double _Complex> func> template <FuncPointer<double _Complex, double _Complex, double _Complex> func>
static std::complex<double> ComplexCFuncWrapper( static std::complex<double> ComplexCFuncWrapper(
std::complex<double> &arg1, std::complex<double> &arg2) { std::complex<double> &arg1, std::complex<double> &arg2) {
double _Complex res{func(*reinterpret_cast<double _Complex *>(&arg1), double _Complex res{func(*reinterpret_cast<double _Complex *>(&arg1),
@ -503,7 +503,7 @@ static std::complex<double> ComplexCFuncWrapper(
return *reinterpret_cast<std::complex<double> *>(&res); return *reinterpret_cast<std::complex<double> *>(&res);
} }
template<L Lib, typename HostT> template <L Lib, typename HostT>
static void AddLibpgmathComplexHostProcedures( static void AddLibpgmathComplexHostProcedures(
HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) { HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) {
static_assert(std::is_same_v<HostT, float> || std::is_same_v<HostT, double>); static_assert(std::is_same_v<HostT, float> || std::is_same_v<HostT, double>);
@ -535,7 +535,7 @@ static void AddLibpgmathComplexHostProcedures(
} }
} }
template<L Lib> template <L Lib>
static void InitHostIntrinsicLibraryWithLibpgmath( static void InitHostIntrinsicLibraryWithLibpgmath(
HostIntrinsicProceduresLibrary &lib) { HostIntrinsicProceduresLibrary &lib) {
if constexpr (host::FortranTypeExists<float>()) { if constexpr (host::FortranTypeExists<float>()) {
@ -558,8 +558,8 @@ static void InitHostIntrinsicLibraryWithLibpgmath(
AddLibmComplexHostProcedures<long double>(lib); AddLibmComplexHostProcedures<long double>(lib);
} }
} }
} } // namespace pgmath
#endif // LINK_WITH_LIBPGMATH #endif // LINK_WITH_LIBPGMATH
// Define which host runtime functions will be used for folding // Define which host runtime functions will be used for folding
HostIntrinsicProceduresLibrary::HostIntrinsicProceduresLibrary() { HostIntrinsicProceduresLibrary::HostIntrinsicProceduresLibrary() {
@ -581,4 +581,4 @@ HostIntrinsicProceduresLibrary::HostIntrinsicProceduresLibrary() {
InitHostIntrinsicLibraryWithLibm(*this); InitHostIntrinsicLibraryWithLibm(*this);
#endif #endif
} }
} } // namespace Fortran::evaluate

View File

@ -70,20 +70,20 @@ static constexpr CategorySet IntrinsicType{
static constexpr CategorySet AnyType{IntrinsicType | DerivedType}; static constexpr CategorySet AnyType{IntrinsicType | DerivedType};
ENUM_CLASS(KindCode, none, defaultIntegerKind, ENUM_CLASS(KindCode, none, defaultIntegerKind,
defaultRealKind, // is also the default COMPLEX kind defaultRealKind, // is also the default COMPLEX kind
doublePrecision, defaultCharKind, defaultLogicalKind, doublePrecision, defaultCharKind, defaultLogicalKind,
any, // matches any kind value; each instance is independent any, // matches any kind value; each instance is independent
same, // match any kind, but all "same" kinds must be equal same, // match any kind, but all "same" kinds must be equal
operand, // match any kind, with promotion (non-standard) operand, // match any kind, with promotion (non-standard)
typeless, // BOZ literals are INTEGER with this kind typeless, // BOZ literals are INTEGER with this kind
teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays) teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
kindArg, // this argument is KIND= kindArg, // this argument is KIND=
effectiveKind, // for function results: "kindArg" value, possibly defaulted effectiveKind, // for function results: "kindArg" value, possibly defaulted
dimArg, // this argument is DIM= dimArg, // this argument is DIM=
likeMultiply, // for DOT_PRODUCT and MATMUL likeMultiply, // for DOT_PRODUCT and MATMUL
subscript, // address-sized integer subscript, // address-sized integer
size, // default KIND= for SIZE(), UBOUND, &c. size, // default KIND= for SIZE(), UBOUND, &c.
addressable, // for PRESENT(), &c.; anything (incl. procedure) but BOZ addressable, // for PRESENT(), &c.; anything (incl. procedure) but BOZ
) )
struct TypePattern { struct TypePattern {
@ -166,27 +166,27 @@ static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind};
// The default rank pattern for dummy arguments and function results is // The default rank pattern for dummy arguments and function results is
// "elemental". // "elemental".
ENUM_CLASS(Rank, ENUM_CLASS(Rank,
elemental, // scalar, or array that conforms with other array arguments elemental, // scalar, or array that conforms with other array arguments
elementalOrBOZ, // elemental, or typeless BOZ literal scalar elementalOrBOZ, // elemental, or typeless BOZ literal scalar
scalar, vector, scalar, vector,
shape, // INTEGER vector of known length and no negative element shape, // INTEGER vector of known length and no negative element
matrix, matrix,
array, // not scalar, rank is known and greater than zero array, // not scalar, rank is known and greater than zero
known, // rank is known and can be scalar known, // rank is known and can be scalar
anyOrAssumedRank, // rank can be unknown; assumed-type TYPE(*) allowed anyOrAssumedRank, // rank can be unknown; assumed-type TYPE(*) allowed
conformable, // scalar, or array of same rank & shape as "array" argument conformable, // scalar, or array of same rank & shape as "array" argument
reduceOperation, // a pure function with constraints for REDUCE reduceOperation, // a pure function with constraints for REDUCE
dimReduced, // scalar if no DIM= argument, else rank(array)-1 dimReduced, // scalar if no DIM= argument, else rank(array)-1
dimRemoved, // scalar, or rank(array)-1 dimRemoved, // scalar, or rank(array)-1
rankPlus1, // rank(known)+1 rankPlus1, // rank(known)+1
shaped, // rank is length of SHAPE vector shaped, // rank is length of SHAPE vector
) )
ENUM_CLASS(Optionality, required, optional, ENUM_CLASS(Optionality, required, optional,
defaultsToSameKind, // for MatchingDefaultKIND defaultsToSameKind, // for MatchingDefaultKIND
defaultsToDefaultForResult, // for DefaultingKIND defaultsToDefaultForResult, // for DefaultingKIND
defaultsToSizeKind, // for SizeDefaultKIND defaultsToSizeKind, // for SizeDefaultKIND
repeats, // for MAX/MIN and their several variants repeats, // for MAX/MIN and their several variants
) )
struct IntrinsicDummyArgument { struct IntrinsicDummyArgument {
@ -224,7 +224,7 @@ static constexpr IntrinsicDummyArgument OptionalMASK{
"mask", AnyLogical, Rank::conformable, Optionality::optional}; "mask", AnyLogical, Rank::conformable, Optionality::optional};
struct IntrinsicInterface { struct IntrinsicInterface {
static constexpr int maxArguments{7}; // if not a MAX/MIN(...) static constexpr int maxArguments{7}; // if not a MAX/MIN(...)
const char *name{nullptr}; const char *name{nullptr};
IntrinsicDummyArgument dummy[maxArguments]; IntrinsicDummyArgument dummy[maxArguments];
TypePattern result; TypePattern result;
@ -350,7 +350,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"dot_product", {"dot_product",
{{"vector_a", AnyComplex, Rank::vector}, {{"vector_a", AnyComplex, Rank::vector},
{"vector_b", AnyNumeric, Rank::vector}}, {"vector_b", AnyNumeric, Rank::vector}},
ResultNumeric, Rank::scalar}, // conjugates vector_a ResultNumeric, Rank::scalar}, // conjugates vector_a
{"dot_product", {"dot_product",
{{"vector_a", AnyIntOrReal, Rank::vector}, {{"vector_a", AnyIntOrReal, Rank::vector},
{"vector_b", AnyNumeric, Rank::vector}}, {"vector_b", AnyNumeric, Rank::vector}},
@ -600,7 +600,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"rank", {{"a", AnyData, Rank::anyOrAssumedRank}}, DefaultInt, {"rank", {{"a", AnyData, Rank::anyOrAssumedRank}}, DefaultInt,
Rank::scalar}, Rank::scalar},
{"real", {{"a", SameComplex, Rank::elemental}}, {"real", {{"a", SameComplex, Rank::elemental}},
SameReal}, // 16.9.160(4)(ii) SameReal}, // 16.9.160(4)(ii)
{"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, {"real", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND},
KINDReal}, KINDReal},
{"reduce", {"reduce",
@ -943,7 +943,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
{"mvbits", {"mvbits",
{{"from", SameInt}, {"frompos", AnyInt}, {"len", AnyInt}, {{"from", SameInt}, {"frompos", AnyInt}, {"len", AnyInt},
{"to", SameInt}, {"topos", AnyInt}}, {"to", SameInt}, {"topos", AnyInt}},
{}}, // elemental {}}, // elemental
{"random_init", {"random_init",
{{"repeatable", AnyLogical, Rank::scalar}, {{"repeatable", AnyLogical, Rank::scalar},
{"image_distinct", AnyLogical, Rank::scalar}}, {"image_distinct", AnyLogical, Rank::scalar}},
@ -953,7 +953,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
{{"size", DefaultInt, Rank::scalar, Optionality::optional}, {{"size", DefaultInt, Rank::scalar, Optionality::optional},
{"put", DefaultInt, Rank::vector, Optionality::optional}, {"put", DefaultInt, Rank::vector, Optionality::optional},
{"get", DefaultInt, Rank::vector, Optionality::optional}}, {"get", DefaultInt, Rank::vector, Optionality::optional}},
{}}, // TODO: at most one argument can be present {}}, // TODO: at most one argument can be present
{"system_clock", {"system_clock",
{{"count", AnyInt, Rank::scalar, Optionality::optional}, {{"count", AnyInt, Rank::scalar, Optionality::optional},
{"count_rate", AnyIntOrReal, Rank::scalar, Optionality::optional}, {"count_rate", AnyIntOrReal, Rank::scalar, Optionality::optional},
@ -1066,7 +1066,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (!arg) { if (!arg) {
if (d.optionality == Optionality::required) { if (d.optionality == Optionality::required) {
messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword); messages.Say("missing mandatory '%s=' argument"_err_en_US, d.keyword);
return std::nullopt; // missing non-OPTIONAL argument return std::nullopt; // missing non-OPTIONAL argument
} else { } else {
continue; continue;
} }
@ -1114,13 +1114,13 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
} else if (!d.typePattern.categorySet.test(type->category())) { } else if (!d.typePattern.categorySet.test(type->category())) {
messages.Say("Actual argument for '%s=' has bad type '%s'"_err_en_US, messages.Say("Actual argument for '%s=' has bad type '%s'"_err_en_US,
d.keyword, type->AsFortran()); d.keyword, type->AsFortran());
return std::nullopt; // argument has invalid type category return std::nullopt; // argument has invalid type category
} }
bool argOk{false}; bool argOk{false};
switch (d.typePattern.kindCode) { switch (d.typePattern.kindCode) {
case KindCode::none: case KindCode::none:
case KindCode::typeless: case KindCode::typeless:
case KindCode::teamType: // TODO: TEAM_TYPE case KindCode::teamType: // TODO: TEAM_TYPE
argOk = false; argOk = false;
break; break;
case KindCode::defaultIntegerKind: case KindCode::defaultIntegerKind:
@ -1138,7 +1138,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case KindCode::defaultLogicalKind: case KindCode::defaultLogicalKind:
argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Logical); argOk = type->kind() == defaults.GetDefaultKind(TypeCategory::Logical);
break; break;
case KindCode::any: argOk = true; break; case KindCode::any:
argOk = true;
break;
case KindCode::kindArg: case KindCode::kindArg:
CHECK(type->category() == TypeCategory::Integer); CHECK(type->category() == TypeCategory::Integer);
CHECK(!kindArg); CHECK(!kindArg);
@ -1175,8 +1177,11 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
"for intrinsic '%s'", "for intrinsic '%s'",
d.keyword, name); d.keyword, name);
break; break;
case KindCode::addressable: argOk = true; break; case KindCode::addressable:
default: CRASH_NO_CASE; argOk = true;
break;
default:
CRASH_NO_CASE;
} }
if (!argOk) { if (!argOk) {
messages.Say( messages.Say(
@ -1210,8 +1215,12 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
} }
argOk = rank == 0 || rank == elementalRank; argOk = rank == 0 || rank == elementalRank;
break; break;
case Rank::scalar: argOk = rank == 0; break; case Rank::scalar:
case Rank::vector: argOk = rank == 1; break; argOk = rank == 0;
break;
case Rank::vector:
argOk = rank == 1;
break;
case Rank::shape: case Rank::shape:
CHECK(!shapeArgSize); CHECK(!shapeArgSize);
if (rank == 1) { if (rank == 1) {
@ -1229,7 +1238,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
return std::nullopt; return std::nullopt;
} }
break; break;
case Rank::matrix: argOk = rank == 2; break; case Rank::matrix:
argOk = rank == 2;
break;
case Rank::array: case Rank::array:
argOk = rank > 0; argOk = rank > 0;
if (!arrayArg) { if (!arrayArg) {
@ -1244,7 +1255,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
} }
argOk = rank == knownArg->Rank(); argOk = rank == knownArg->Rank();
break; break;
case Rank::anyOrAssumedRank: argOk = true; break; case Rank::anyOrAssumedRank:
argOk = true;
break;
case Rank::conformable: case Rank::conformable:
CHECK(arrayArg); CHECK(arrayArg);
argOk = rank == 0 || rank == arrayArg->Rank(); argOk = rank == 0 || rank == arrayArg->Rank();
@ -1383,7 +1396,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
common::die( common::die(
"INTERNAL: bad KindCode appears on intrinsic '%s' result", name); "INTERNAL: bad KindCode appears on intrinsic '%s' result", name);
break; break;
default: CRASH_NO_CASE; default:
CRASH_NO_CASE;
} }
} else { } else {
if (!call.isSubroutineCall) { if (!call.isSubroutineCall) {
@ -1396,10 +1410,18 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
// Determine the rank of the function result. // Determine the rank of the function result.
int resultRank{0}; int resultRank{0};
switch (rank) { switch (rank) {
case Rank::elemental: resultRank = elementalRank; break; case Rank::elemental:
case Rank::scalar: resultRank = 0; break; resultRank = elementalRank;
case Rank::vector: resultRank = 1; break; break;
case Rank::matrix: resultRank = 2; break; case Rank::scalar:
resultRank = 0;
break;
case Rank::vector:
resultRank = 1;
break;
case Rank::matrix:
resultRank = 2;
break;
case Rank::conformable: case Rank::conformable:
CHECK(arrayArg); CHECK(arrayArg);
resultRank = arrayArg->Rank(); resultRank = arrayArg->Rank();
@ -1496,7 +1518,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
class IntrinsicProcTable::Implementation { class IntrinsicProcTable::Implementation {
public: public:
explicit Implementation(const common::IntrinsicTypeDefaultKinds &dfts) explicit Implementation(const common::IntrinsicTypeDefaultKinds &dfts)
: defaults_{dfts} { : defaults_{dfts} {
for (const IntrinsicInterface &f : genericIntrinsicFunction) { for (const IntrinsicInterface &f : genericIntrinsicFunction) {
genericFuncs_.insert(std::make_pair(std::string{f.name}, &f)); genericFuncs_.insert(std::make_pair(std::string{f.name}, &f));
} }
@ -1798,10 +1820,14 @@ static DynamicType GetReturnType(const SpecificIntrinsicInterface &interface,
const common::IntrinsicTypeDefaultKinds &defaults) { const common::IntrinsicTypeDefaultKinds &defaults) {
TypeCategory category{TypeCategory::Integer}; TypeCategory category{TypeCategory::Integer};
switch (interface.result.kindCode) { switch (interface.result.kindCode) {
case KindCode::defaultIntegerKind: break; case KindCode::defaultIntegerKind:
break;
case KindCode::doublePrecision: case KindCode::doublePrecision:
case KindCode::defaultRealKind: category = TypeCategory::Real; break; case KindCode::defaultRealKind:
default: CRASH_NO_CASE; category = TypeCategory::Real;
break;
default:
CRASH_NO_CASE;
} }
int kind{interface.result.kindCode == KindCode::doublePrecision int kind{interface.result.kindCode == KindCode::doublePrecision
? defaults.doublePrecisionKind() ? defaults.doublePrecisionKind()
@ -1836,7 +1862,7 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
return specificCall; return specificCall;
} }
} }
return std::nullopt; // TODO return std::nullopt; // TODO
} }
// Helper to avoid emitting errors before it is sure there is no match // Helper to avoid emitting errors before it is sure there is no match
@ -2063,4 +2089,4 @@ llvm::raw_ostream &IntrinsicProcTable::Implementation::Dump(
llvm::raw_ostream &IntrinsicProcTable::Dump(llvm::raw_ostream &o) const { llvm::raw_ostream &IntrinsicProcTable::Dump(llvm::raw_ostream &o) const {
return impl_->Dump(o); return impl_->Dump(o);
} }
} } // namespace Fortran::evaluate

View File

@ -14,4 +14,4 @@ template class Logical<8>;
template class Logical<16>; template class Logical<16>;
template class Logical<32>; template class Logical<32>;
template class Logical<64>; template class Logical<64>;
} } // namespace Fortran::evaluate::value

View File

@ -16,26 +16,26 @@
namespace Fortran::evaluate::value { namespace Fortran::evaluate::value {
template<typename W, int P> Relation Real<W, P>::Compare(const Real &y) const { template <typename W, int P> Relation Real<W, P>::Compare(const Real &y) const {
if (IsNotANumber() || y.IsNotANumber()) { // NaN vs x, x vs NaN if (IsNotANumber() || y.IsNotANumber()) { // NaN vs x, x vs NaN
return Relation::Unordered; return Relation::Unordered;
} else if (IsInfinite()) { } else if (IsInfinite()) {
if (y.IsInfinite()) { if (y.IsInfinite()) {
if (IsNegative()) { // -Inf vs +/-Inf if (IsNegative()) { // -Inf vs +/-Inf
return y.IsNegative() ? Relation::Equal : Relation::Less; return y.IsNegative() ? Relation::Equal : Relation::Less;
} else { // +Inf vs +/-Inf } else { // +Inf vs +/-Inf
return y.IsNegative() ? Relation::Greater : Relation::Equal; return y.IsNegative() ? Relation::Greater : Relation::Equal;
} }
} else { // +/-Inf vs finite } else { // +/-Inf vs finite
return IsNegative() ? Relation::Less : Relation::Greater; return IsNegative() ? Relation::Less : Relation::Greater;
} }
} else if (y.IsInfinite()) { // finite vs +/-Inf } else if (y.IsInfinite()) { // finite vs +/-Inf
return y.IsNegative() ? Relation::Greater : Relation::Less; return y.IsNegative() ? Relation::Greater : Relation::Less;
} else { // two finite numbers } else { // two finite numbers
bool isNegative{IsNegative()}; bool isNegative{IsNegative()};
if (isNegative != y.IsNegative()) { if (isNegative != y.IsNegative()) {
if (word_.IOR(y.word_).IBCLR(bits - 1).IsZero()) { if (word_.IOR(y.word_).IBCLR(bits - 1).IsZero()) {
return Relation::Equal; // +/-0.0 == -/+0.0 return Relation::Equal; // +/-0.0 == -/+0.0
} else { } else {
return isNegative ? Relation::Less : Relation::Greater; return isNegative ? Relation::Less : Relation::Greater;
} }
@ -53,12 +53,12 @@ template<typename W, int P> Relation Real<W, P>::Compare(const Real &y) const {
} }
} }
template<typename W, int P> template <typename W, int P>
ValueWithRealFlags<Real<W, P>> Real<W, P>::Add( ValueWithRealFlags<Real<W, P>> Real<W, P>::Add(
const Real &y, Rounding rounding) const { const Real &y, Rounding rounding) const {
ValueWithRealFlags<Real> result; ValueWithRealFlags<Real> result;
if (IsNotANumber() || y.IsNotANumber()) { if (IsNotANumber() || y.IsNotANumber()) {
result.value = NotANumber(); // NaN + x -> NaN result.value = NotANumber(); // NaN + x -> NaN
if (IsSignalingNaN() || y.IsSignalingNaN()) { if (IsSignalingNaN() || y.IsSignalingNaN()) {
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} }
@ -69,18 +69,18 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Add(
if (IsInfinite()) { if (IsInfinite()) {
if (y.IsInfinite()) { if (y.IsInfinite()) {
if (isNegative == yIsNegative) { if (isNegative == yIsNegative) {
result.value = *this; // +/-Inf + +/-Inf -> +/-Inf result.value = *this; // +/-Inf + +/-Inf -> +/-Inf
} else { } else {
result.value = NotANumber(); // +/-Inf + -/+Inf -> NaN result.value = NotANumber(); // +/-Inf + -/+Inf -> NaN
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} }
} else { } else {
result.value = *this; // +/-Inf + x -> +/-Inf result.value = *this; // +/-Inf + x -> +/-Inf
} }
return result; return result;
} }
if (y.IsInfinite()) { if (y.IsInfinite()) {
result.value = y; // x + +/-Inf -> +/-Inf result.value = y; // x + +/-Inf -> +/-Inf
return result; return result;
} }
int exponent{Exponent()}; int exponent{Exponent()};
@ -98,7 +98,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Add(
if (order == Ordering::Equal) { if (order == Ordering::Equal) {
// x + (-x) -> +0.0 unless rounding is directed downwards // x + (-x) -> +0.0 unless rounding is directed downwards
if (rounding.mode == common::RoundingMode::Down) { if (rounding.mode == common::RoundingMode::Down) {
result.value.word_ = result.value.word_.IBSET(bits - 1); // -0.0 result.value.word_ = result.value.word_.IBSET(bits - 1); // -0.0
} }
return result; return result;
} }
@ -110,7 +110,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Add(
Fraction yFraction{y.GetFraction()}; Fraction yFraction{y.GetFraction()};
int rshift = exponent - yExponent; int rshift = exponent - yExponent;
if (exponent > 0 && yExponent == 0) { if (exponent > 0 && yExponent == 0) {
--rshift; // correct overshift when only y is subnormal --rshift; // correct overshift when only y is subnormal
} }
RoundingBits roundingBits{yFraction, rshift}; RoundingBits roundingBits{yFraction, rshift};
yFraction = yFraction.SHIFTR(rshift); yFraction = yFraction.SHIFTR(rshift);
@ -133,12 +133,12 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Add(
return result; return result;
} }
template<typename W, int P> template <typename W, int P>
ValueWithRealFlags<Real<W, P>> Real<W, P>::Multiply( ValueWithRealFlags<Real<W, P>> Real<W, P>::Multiply(
const Real &y, Rounding rounding) const { const Real &y, Rounding rounding) const {
ValueWithRealFlags<Real> result; ValueWithRealFlags<Real> result;
if (IsNotANumber() || y.IsNotANumber()) { if (IsNotANumber() || y.IsNotANumber()) {
result.value = NotANumber(); // NaN * x -> NaN result.value = NotANumber(); // NaN * x -> NaN
if (IsSignalingNaN() || y.IsSignalingNaN()) { if (IsSignalingNaN() || y.IsSignalingNaN()) {
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} }
@ -146,7 +146,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Multiply(
bool isNegative{IsNegative() != y.IsNegative()}; bool isNegative{IsNegative() != y.IsNegative()};
if (IsInfinite() || y.IsInfinite()) { if (IsInfinite() || y.IsInfinite()) {
if (IsZero() || y.IsZero()) { if (IsZero() || y.IsZero()) {
result.value = NotANumber(); // 0 * Inf -> NaN result.value = NotANumber(); // 0 * Inf -> NaN
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} else { } else {
result.value = Infinity(isNegative); result.value = Infinity(isNegative);
@ -193,12 +193,12 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Multiply(
return result; return result;
} }
template<typename W, int P> template <typename W, int P>
ValueWithRealFlags<Real<W, P>> Real<W, P>::Divide( ValueWithRealFlags<Real<W, P>> Real<W, P>::Divide(
const Real &y, Rounding rounding) const { const Real &y, Rounding rounding) const {
ValueWithRealFlags<Real> result; ValueWithRealFlags<Real> result;
if (IsNotANumber() || y.IsNotANumber()) { if (IsNotANumber() || y.IsNotANumber()) {
result.value = NotANumber(); // NaN / x -> NaN, x / NaN -> NaN result.value = NotANumber(); // NaN / x -> NaN, x / NaN -> NaN
if (IsSignalingNaN() || y.IsSignalingNaN()) { if (IsSignalingNaN() || y.IsSignalingNaN()) {
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} }
@ -206,20 +206,20 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Divide(
bool isNegative{IsNegative() != y.IsNegative()}; bool isNegative{IsNegative() != y.IsNegative()};
if (IsInfinite()) { if (IsInfinite()) {
if (y.IsInfinite()) { if (y.IsInfinite()) {
result.value = NotANumber(); // Inf/Inf -> NaN result.value = NotANumber(); // Inf/Inf -> NaN
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} else { // Inf/x -> Inf, Inf/0 -> Inf } else { // Inf/x -> Inf, Inf/0 -> Inf
result.value = Infinity(isNegative); result.value = Infinity(isNegative);
} }
} else if (y.IsZero()) { } else if (y.IsZero()) {
if (IsZero()) { // 0/0 -> NaN if (IsZero()) { // 0/0 -> NaN
result.value = NotANumber(); result.value = NotANumber();
result.flags.set(RealFlag::InvalidArgument); result.flags.set(RealFlag::InvalidArgument);
} else { // x/0 -> Inf, Inf/0 -> Inf } else { // x/0 -> Inf, Inf/0 -> Inf
result.value = Infinity(isNegative); result.value = Infinity(isNegative);
result.flags.set(RealFlag::DivideByZero); result.flags.set(RealFlag::DivideByZero);
} }
} else if (IsZero() || y.IsInfinite()) { // 0/x, x/Inf -> 0 } else if (IsZero() || y.IsInfinite()) { // 0/x, x/Inf -> 0
if (isNegative) { if (isNegative) {
result.value.word_ = result.value.word_.IBSET(bits - 1); result.value.word_ = result.value.word_.IBSET(bits - 1);
} }
@ -261,7 +261,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Divide(
return result; return result;
} }
template<typename W, int P> template <typename W, int P>
ValueWithRealFlags<Real<W, P>> Real<W, P>::ToWholeNumber( ValueWithRealFlags<Real<W, P>> Real<W, P>::ToWholeNumber(
common::RoundingMode mode) const { common::RoundingMode mode) const {
ValueWithRealFlags<Real> result{*this}; ValueWithRealFlags<Real> result{*this};
@ -273,11 +273,11 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::ToWholeNumber(
} else { } else {
constexpr int noClipExponent{exponentBias + binaryPrecision - 1}; constexpr int noClipExponent{exponentBias + binaryPrecision - 1};
if (Exponent() < noClipExponent) { if (Exponent() < noClipExponent) {
Real adjust; // ABS(EPSILON(adjust)) == 0.5 Real adjust; // ABS(EPSILON(adjust)) == 0.5
adjust.Normalize(IsSignBitSet(), noClipExponent, Fraction::MASKL(1)); adjust.Normalize(IsSignBitSet(), noClipExponent, Fraction::MASKL(1));
// Compute ival=(*this + adjust), losing any fractional bits; keep flags // Compute ival=(*this + adjust), losing any fractional bits; keep flags
result = Add(adjust, Rounding{mode}); result = Add(adjust, Rounding{mode});
result.flags.reset(RealFlag::Inexact); // result *is* exact result.flags.reset(RealFlag::Inexact); // result *is* exact
// Return (ival-adjust) with original sign in case we've generated a zero. // Return (ival-adjust) with original sign in case we've generated a zero.
result.value = result.value =
result.value.Subtract(adjust, Rounding{common::RoundingMode::ToZero}) result.value.Subtract(adjust, Rounding{common::RoundingMode::ToZero})
@ -287,7 +287,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::ToWholeNumber(
return result; return result;
} }
template<typename W, int P> template <typename W, int P>
RealFlags Real<W, P>::Normalize(bool negative, int exponent, RealFlags Real<W, P>::Normalize(bool negative, int exponent,
const Fraction &fraction, Rounding rounding, RoundingBits *roundingBits) { const Fraction &fraction, Rounding rounding, RoundingBits *roundingBits) {
int lshift{fraction.LEADZ()}; int lshift{fraction.LEADZ()};
@ -311,7 +311,7 @@ RealFlags Real<W, P>::Normalize(bool negative, int exponent,
rounding.mode == common::RoundingMode::TiesAwayFromZero || rounding.mode == common::RoundingMode::TiesAwayFromZero ||
(rounding.mode == common::RoundingMode::Up && !negative) || (rounding.mode == common::RoundingMode::Up && !negative) ||
(rounding.mode == common::RoundingMode::Down && negative)) { (rounding.mode == common::RoundingMode::Down && negative)) {
word_ = Word{maxExponent}.SHIFTL(significandBits); // Inf word_ = Word{maxExponent}.SHIFTL(significandBits); // Inf
} else { } else {
// directed rounding: round to largest finite value rather than infinity // directed rounding: round to largest finite value rather than infinity
// (x86 does this, not sure whether it's standard behavior) // (x86 does this, not sure whether it's standard behavior)
@ -347,7 +347,7 @@ RealFlags Real<W, P>::Normalize(bool negative, int exponent,
return {}; return {};
} }
template<typename W, int P> template <typename W, int P>
RealFlags Real<W, P>::Round( RealFlags Real<W, P>::Round(
Rounding rounding, const RoundingBits &bits, bool multiply) { Rounding rounding, const RoundingBits &bits, bool multiply) {
int origExponent{Exponent()}; int origExponent{Exponent()};
@ -365,7 +365,7 @@ RealFlags Real<W, P>::Round(
// The fraction was all ones before rounding; sum.value is now zero // The fraction was all ones before rounding; sum.value is now zero
sum.value = sum.value.IBSET(binaryPrecision - 1); sum.value = sum.value.IBSET(binaryPrecision - 1);
if (++newExponent >= maxExponent) { if (++newExponent >= maxExponent) {
flags.set(RealFlag::Overflow); // rounded away to an infinity flags.set(RealFlag::Overflow); // rounded away to an infinity
} }
} }
flags |= Normalize(IsNegative(), newExponent, sum.value); flags |= Normalize(IsNegative(), newExponent, sum.value);
@ -388,7 +388,7 @@ RealFlags Real<W, P>::Round(
return flags; return flags;
} }
template<typename W, int P> template <typename W, int P>
void Real<W, P>::NormalizeAndRound(ValueWithRealFlags<Real> &result, void Real<W, P>::NormalizeAndRound(ValueWithRealFlags<Real> &result,
bool isNegative, int exponent, const Fraction &fraction, Rounding rounding, bool isNegative, int exponent, const Fraction &fraction, Rounding rounding,
RoundingBits roundingBits, bool multiply) { RoundingBits roundingBits, bool multiply) {
@ -400,13 +400,18 @@ void Real<W, P>::NormalizeAndRound(ValueWithRealFlags<Real> &result,
inline enum decimal::FortranRounding MapRoundingMode( inline enum decimal::FortranRounding MapRoundingMode(
common::RoundingMode rounding) { common::RoundingMode rounding) {
switch (rounding) { switch (rounding) {
case common::RoundingMode::TiesToEven: break; case common::RoundingMode::TiesToEven:
case common::RoundingMode::ToZero: return decimal::RoundToZero; break;
case common::RoundingMode::Down: return decimal::RoundDown; case common::RoundingMode::ToZero:
case common::RoundingMode::Up: return decimal::RoundUp; return decimal::RoundToZero;
case common::RoundingMode::TiesAwayFromZero: return decimal::RoundCompatible; case common::RoundingMode::Down:
return decimal::RoundDown;
case common::RoundingMode::Up:
return decimal::RoundUp;
case common::RoundingMode::TiesAwayFromZero:
return decimal::RoundCompatible;
} }
return decimal::RoundNearest; // dodge gcc warning about lack of result return decimal::RoundNearest; // dodge gcc warning about lack of result
} }
inline RealFlags MapFlags(decimal::ConversionResultFlags flags) { inline RealFlags MapFlags(decimal::ConversionResultFlags flags) {
@ -423,7 +428,7 @@ inline RealFlags MapFlags(decimal::ConversionResultFlags flags) {
return result; return result;
} }
template<typename W, int P> template <typename W, int P>
ValueWithRealFlags<Real<W, P>> Real<W, P>::Read( ValueWithRealFlags<Real<W, P>> Real<W, P>::Read(
const char *&p, Rounding rounding) { const char *&p, Rounding rounding) {
auto converted{ auto converted{
@ -432,7 +437,7 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::Read(
return {*value, MapFlags(converted.flags)}; return {*value, MapFlags(converted.flags)};
} }
template<typename W, int P> std::string Real<W, P>::DumpHexadecimal() const { template <typename W, int P> std::string Real<W, P>::DumpHexadecimal() const {
if (IsNotANumber()) { if (IsNotANumber()) {
return "NaN 0x"s + word_.Hexadecimal(); return "NaN 0x"s + word_.Hexadecimal();
} else if (IsNegative()) { } else if (IsNegative()) {
@ -478,7 +483,7 @@ template<typename W, int P> std::string Real<W, P>::DumpHexadecimal() const {
} }
} }
template<typename W, int P> template <typename W, int P>
llvm::raw_ostream &Real<W, P>::AsFortran( llvm::raw_ostream &Real<W, P>::AsFortran(
llvm::raw_ostream &o, int kind, bool minimal) const { llvm::raw_ostream &o, int kind, bool minimal) const {
if (IsNotANumber()) { if (IsNotANumber()) {
@ -492,8 +497,8 @@ llvm::raw_ostream &Real<W, P>::AsFortran(
} else { } else {
using B = decimal::BinaryFloatingPointNumber<P>; using B = decimal::BinaryFloatingPointNumber<P>;
const auto *value{reinterpret_cast<const B *>(this)}; const auto *value{reinterpret_cast<const B *>(this)};
char buffer[24000]; // accommodate real*16 char buffer[24000]; // accommodate real*16
decimal::DecimalConversionFlags flags{}; // default: exact representation decimal::DecimalConversionFlags flags{}; // default: exact representation
if (minimal) { if (minimal) {
flags = decimal::Minimize; flags = decimal::Minimize;
} }
@ -522,4 +527,4 @@ template class Real<Integer<32>, 24>;
template class Real<Integer<64>, 53>; template class Real<Integer<64>, 53>;
template class Real<Integer<80>, 64>; template class Real<Integer<80>, 64>;
template class Real<Integer<128>, 113>; template class Real<Integer<128>, 113>;
} } // namespace Fortran::evaluate::value

View File

@ -18,7 +18,7 @@
#include "flang/Semantics/symbol.h" #include "flang/Semantics/symbol.h"
#include <functional> #include <functional>
using namespace std::placeholders; // _1, _2, &c. for std::bind() using namespace std::placeholders; // _1, _2, &c. for std::bind()
namespace Fortran::evaluate { namespace Fortran::evaluate {
@ -36,7 +36,7 @@ bool IsExplicitShape(const Symbol &symbol0) {
const Symbol &symbol{ResolveAssociations(symbol0)}; const Symbol &symbol{ResolveAssociations(symbol0)};
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) { if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
const auto &shape{details->shape()}; const auto &shape{details->shape()};
return shape.Rank() == 0 || shape.IsExplicitShape(); // even if scalar return shape.Rank() == 0 || shape.IsExplicitShape(); // even if scalar
} else { } else {
return false; return false;
} }
@ -186,7 +186,7 @@ public:
using Base = Traverse<GetLowerBoundHelper, ExtentExpr>; using Base = Traverse<GetLowerBoundHelper, ExtentExpr>;
using Base::operator(); using Base::operator();
GetLowerBoundHelper(FoldingContext &c, int d) GetLowerBoundHelper(FoldingContext &c, int d)
: Base{*this}, context_{c}, dimension_{d} {} : Base{*this}, context_{c}, dimension_{d} {}
static ExtentExpr Default() { return ExtentExpr{1}; } static ExtentExpr Default() { return ExtentExpr{1}; }
static ExtentExpr Combine(Result &&, Result &&) { return Default(); } static ExtentExpr Combine(Result &&, Result &&) { return Default(); }
ExtentExpr operator()(const Symbol &); ExtentExpr operator()(const Symbol &);
@ -318,7 +318,7 @@ MaybeExtentExpr GetExtent(FoldingContext &context, const Subscript &subscript,
[&](const IndirectSubscriptIntegerExpr &subs) -> MaybeExtentExpr { [&](const IndirectSubscriptIntegerExpr &subs) -> MaybeExtentExpr {
if (auto shape{GetShape(context, subs.value())}) { if (auto shape{GetShape(context, subs.value())}) {
if (GetRank(*shape) > 0) { if (GetRank(*shape) > 0) {
CHECK(GetRank(*shape) == 1); // vector-valued subscript CHECK(GetRank(*shape) == 1); // vector-valued subscript
return std::move(shape->at(0)); return std::move(shape->at(0));
} }
} }
@ -378,7 +378,7 @@ Shape GetUpperBounds(FoldingContext &context, const NamedEntity &base) {
result.emplace_back(Fold(context, common::Clone(*bound))); result.emplace_back(Fold(context, common::Clone(*bound)));
} else if (details->IsAssumedSize()) { } else if (details->IsAssumedSize()) {
CHECK(dim + 1 == base.Rank()); CHECK(dim + 1 == base.Rank());
result.emplace_back(std::nullopt); // UBOUND folding replaces with -1 result.emplace_back(std::nullopt); // UBOUND folding replaces with -1
} else { } else {
result.emplace_back(ComputeUpperBound(context, result.emplace_back(ComputeUpperBound(context,
GetLowerBound(context, base, dim), GetExtent(context, base, dim))); GetLowerBound(context, base, dim), GetExtent(context, base, dim)));
@ -409,7 +409,7 @@ auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result {
} }
}, },
[](const semantics::EntityDetails &) { [](const semantics::EntityDetails &) {
return Scalar(); // no dimensions seen return Scalar(); // no dimensions seen
}, },
[&](const semantics::ProcEntityDetails &proc) { [&](const semantics::ProcEntityDetails &proc) {
if (const Symbol * interface{proc.interface().symbol()}) { if (const Symbol * interface{proc.interface().symbol()}) {
@ -617,7 +617,7 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
} }
} }
} else if (intrinsic->characteristics.value().attrs.test(characteristics:: } else if (intrinsic->characteristics.value().attrs.test(characteristics::
Procedure::Attr::NullPointer)) { // NULL(MOLD=) Procedure::Attr::NullPointer)) { // NULL(MOLD=)
return (*this)(call.arguments()); return (*this)(call.arguments());
} else { } else {
// TODO: shapes of other non-elemental intrinsic results // TODO: shapes of other non-elemental intrinsic results
@ -653,4 +653,4 @@ bool CheckConformance(parser::ContextualMessages &messages, const Shape &left,
} }
return true; return true;
} }
} } // namespace Fortran::evaluate

View File

@ -93,4 +93,4 @@ std::optional<std::u32string> StaticDataObject::AsU32String() const {
} }
return std::nullopt; return std::nullopt;
} }
} } // namespace Fortran::evaluate

View File

@ -705,13 +705,12 @@ bool IsProcedure(const Expr<SomeType> &expr) {
} }
bool IsProcedurePointer(const Expr<SomeType> &expr) { bool IsProcedurePointer(const Expr<SomeType> &expr) {
return std::visit( return std::visit(common::visitors{
common::visitors{ [](const NullPointer &) { return true; },
[](const NullPointer &) { return true; }, [](const ProcedureDesignator &) { return true; },
[](const ProcedureDesignator &) { return true; }, [](const ProcedureRef &) { return true; },
[](const ProcedureRef &) { return true; }, [](const auto &) { return false; },
[](const auto &) { return false; }, },
},
expr.u); expr.u);
} }

Some files were not shown because too many files have changed in this diff Show More