Skip to content

Commit

Permalink
[flang][msvc] Split class declaration and constexpr variable definiti…
Browse files Browse the repository at this point in the history
…on. NFC.

Msvc has trouble defining a struct/class and defining a constexpr symbol in the same declarator. It reports the following error:
```
basic-parsers.h(809): error C2131: expression did not evaluate to a constant
basic-parsers.h(809): note: failure was caused by call of undefined function or one not declared 'constexpr'
basic-parsers.h(809): note: see usage of 'Fortran::parser::OkParser::OkParser'
```

Fix the msvc compilation by splitting the two definitions into two separate declarators.

This patch is part of the series to [[ http://lists.llvm.org/pipermail/flang-dev/2020-July/000448.html | make flang compilable with MS Visual Studio ]].

Reviewed By: DavidTruby, klausler

Differential Revision: https://reviews.llvm.org/D85937
  • Loading branch information
Meinersbur committed Aug 22, 2020
1 parent 542db87 commit 207d449
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 30 deletions.
5 changes: 3 additions & 2 deletions flang/lib/Parser/basic-parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -800,13 +800,14 @@ inline constexpr auto nonemptySeparated(PA p, PB sep) {
// must discard its result in order to be compatible in type with other
// parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even
// when x and y have distinct result types.
constexpr struct OkParser {
struct OkParser {
using resultType = Success;
constexpr OkParser() {}
static constexpr std::optional<Success> Parse(ParseState &) {
return Success{};
}
} ok;
};
constexpr OkParser ok;

// A variant of recovery() above for convenience.
template <typename PA, typename PB>
Expand Down
40 changes: 24 additions & 16 deletions flang/lib/Parser/expr-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ inline std::optional<Expr> MultOperand::Parse(ParseState &state) {
// R1005 add-operand -> [add-operand mult-op] mult-operand
// R1008 mult-op -> * | /
// The left recursion in the grammar is implemented iteratively.
constexpr struct AddOperand {
struct AddOperand {
using resultType = Expr;
constexpr AddOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand All @@ -142,7 +142,8 @@ constexpr struct AddOperand {
}
return result;
}
} addOperand;
};
constexpr AddOperand addOperand;

// R1006 level-2-expr -> [[level-2-expr] add-op] add-operand
// R1009 add-op -> + | -
Expand All @@ -151,7 +152,7 @@ constexpr struct AddOperand {
// by means of a missing first operand; e.g., 2*-3 is valid in C but not
// standard Fortran. We accept unary + and - to appear before any primary
// as an extension.
constexpr struct Level2Expr {
struct Level2Expr {
using resultType = Expr;
constexpr Level2Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand Down Expand Up @@ -179,13 +180,14 @@ constexpr struct Level2Expr {
}
return result;
}
} level2Expr;
};
constexpr Level2Expr level2Expr;

// R1010 level-3-expr -> [level-3-expr concat-op] level-2-expr
// R1011 concat-op -> //
// Concatenation (//) is left-associative for parsing performance, although
// one would never notice if it were right-associated.
constexpr struct Level3Expr {
struct Level3Expr {
using resultType = Expr;
constexpr Level3Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand All @@ -203,14 +205,15 @@ constexpr struct Level3Expr {
}
return result;
}
} level3Expr;
};
constexpr Level3Expr level3Expr;

// R1012 level-4-expr -> [level-3-expr rel-op] level-3-expr
// R1013 rel-op ->
// .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. |
// == | /= | < | <= | > | >= @ | <>
// N.B. relations are not recursive (i.e., LOGICAL is not ordered)
constexpr struct Level4Expr {
struct Level4Expr {
using resultType = Expr;
constexpr Level4Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand Down Expand Up @@ -252,17 +255,19 @@ constexpr struct Level4Expr {
}
return result;
}
} level4Expr;
};
constexpr Level4Expr level4Expr;

// R1014 and-operand -> [not-op] level-4-expr
// R1018 not-op -> .NOT.
// N.B. Fortran's .NOT. binds less tightly than its comparison operators do.
// PGI/Intel extension: accept multiple .NOT. operators
constexpr struct AndOperand {
struct AndOperand {
using resultType = Expr;
constexpr AndOperand() {}
static inline std::optional<Expr> Parse(ParseState &);
} andOperand;
};
constexpr AndOperand andOperand;

// Match a logical operator or, optionally, its abbreviation.
inline constexpr auto logicalOp(const char *op, const char *abbrev) {
Expand All @@ -283,7 +288,7 @@ inline std::optional<Expr> AndOperand::Parse(ParseState &state) {
// R1015 or-operand -> [or-operand and-op] and-operand
// R1019 and-op -> .AND.
// .AND. is left-associative
constexpr struct OrOperand {
struct OrOperand {
using resultType = Expr;
constexpr OrOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand All @@ -303,12 +308,13 @@ constexpr struct OrOperand {
}
return result;
}
} orOperand;
};
constexpr OrOperand orOperand;

// R1016 equiv-operand -> [equiv-operand or-op] or-operand
// R1020 or-op -> .OR.
// .OR. is left-associative
constexpr struct EquivOperand {
struct EquivOperand {
using resultType = Expr;
constexpr EquivOperand() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand All @@ -327,13 +333,14 @@ constexpr struct EquivOperand {
}
return result;
}
} equivOperand;
};
constexpr EquivOperand equivOperand;

// R1017 level-5-expr -> [level-5-expr equiv-op] equiv-operand
// R1021 equiv-op -> .EQV. | .NEQV.
// Logical equivalence is left-associative.
// Extension: .XOR. as synonym for .NEQV.
constexpr struct Level5Expr {
struct Level5Expr {
using resultType = Expr;
constexpr Level5Expr() {}
static inline std::optional<Expr> Parse(ParseState &state) {
Expand All @@ -358,7 +365,8 @@ constexpr struct Level5Expr {
}
return result;
}
} level5Expr;
};
constexpr Level5Expr level5Expr;

// R1022 expr -> [expr defined-binary-op] level-5-expr
// Defined binary operators associate leftwards.
Expand Down
30 changes: 18 additions & 12 deletions flang/lib/Parser/token-parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ constexpr auto letter{"abcdefghijklmnopqrstuvwxyz"_ch};
constexpr auto digit{"0123456789"_ch};

// Skips over optional spaces. Always succeeds.
constexpr struct Space {
struct Space {
using resultType = Success;
constexpr Space() {}
static std::optional<Success> Parse(ParseState &state) {
Expand All @@ -74,7 +74,8 @@ constexpr struct Space {
}
return {Success{}};
}
} space;
};
constexpr Space space;

// Skips a space that in free form requires a warning if it precedes a
// character that could begin an identifier or keyword. Always succeeds.
Expand All @@ -85,7 +86,7 @@ inline void MissingSpace(ParseState &state) {
}
}

constexpr struct SpaceCheck {
struct SpaceCheck {
using resultType = Success;
constexpr SpaceCheck() {}
static std::optional<Success> Parse(ParseState &state) {
Expand All @@ -101,7 +102,8 @@ constexpr struct SpaceCheck {
}
return {Success{}};
}
} spaceCheck;
};
constexpr SpaceCheck spaceCheck;

// Matches a token string. Spaces in the token string denote where
// spaces may appear in the source; they can be made mandatory for
Expand Down Expand Up @@ -346,7 +348,7 @@ struct BOZLiteral {

// R711 digit-string -> digit [digit]...
// N.B. not a token -- no space is skipped
constexpr struct DigitString {
struct DigitString {
using resultType = CharBlock;
static std::optional<resultType> Parse(ParseState &state) {
if (std::optional<const char *> ch1{state.PeekAtNextChar()}) {
Expand All @@ -363,7 +365,8 @@ constexpr struct DigitString {
}
return std::nullopt;
}
} digitString;
};
constexpr DigitString digitString;

struct SignedIntLiteralConstantWithoutKind {
using resultType = CharBlock;
Expand All @@ -380,7 +383,7 @@ struct SignedIntLiteralConstantWithoutKind {
}
};

constexpr struct DigitString64 {
struct DigitString64 {
using resultType = std::uint64_t;
static std::optional<std::uint64_t> Parse(ParseState &state) {
std::optional<const char *> firstDigit{digit.Parse(state)};
Expand All @@ -406,7 +409,8 @@ constexpr struct DigitString64 {
}
return {value};
}
} digitString64;
};
constexpr DigitString64 digitString64;

// R707 signed-int-literal-constant -> [sign] int-literal-constant
// N.B. Spaces are consumed before and after the sign, since the sign
Expand Down Expand Up @@ -537,7 +541,7 @@ struct HollerithLiteral {
}
};

constexpr struct ConsumedAllInputParser {
struct ConsumedAllInputParser {
using resultType = Success;
constexpr ConsumedAllInputParser() {}
static inline std::optional<Success> Parse(ParseState &state) {
Expand All @@ -546,7 +550,8 @@ constexpr struct ConsumedAllInputParser {
}
return std::nullopt;
}
} consumedAllInput;
};
constexpr ConsumedAllInputParser consumedAllInput;

template <char goal> struct SkipPast {
using resultType = Success;
Expand Down Expand Up @@ -599,7 +604,7 @@ inline constexpr auto optionalListBeforeColons(const PA &p) {
// the ones that specify the source form) that might appear before the
// next statement. Skip over empty statements (bare semicolons) when
// not in strict standard conformance mode. Always succeeds.
constexpr struct SkipStuffBeforeStatement {
struct SkipStuffBeforeStatement {
using resultType = Success;
static std::optional<Success> Parse(ParseState &state) {
if (UserState * ustate{state.userState()}) {
Expand Down Expand Up @@ -637,7 +642,8 @@ constexpr struct SkipStuffBeforeStatement {
}
return {Success{}};
}
} skipStuffBeforeStatement;
};
constexpr SkipStuffBeforeStatement skipStuffBeforeStatement;

// R602 underscore -> _
constexpr auto underscore{"_"_ch};
Expand Down

0 comments on commit 207d449

Please sign in to comment.