Skip to content

Commit 207d449

Browse files
committed
[flang][msvc] Split class declaration and constexpr variable definition. 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
1 parent 542db87 commit 207d449

File tree

3 files changed

+45
-30
lines changed

3 files changed

+45
-30
lines changed

flang/lib/Parser/basic-parsers.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -800,13 +800,14 @@ inline constexpr auto nonemptySeparated(PA p, PB sep) {
800800
// must discard its result in order to be compatible in type with other
801801
// parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even
802802
// when x and y have distinct result types.
803-
constexpr struct OkParser {
803+
struct OkParser {
804804
using resultType = Success;
805805
constexpr OkParser() {}
806806
static constexpr std::optional<Success> Parse(ParseState &) {
807807
return Success{};
808808
}
809-
} ok;
809+
};
810+
constexpr OkParser ok;
810811

811812
// A variant of recovery() above for convenience.
812813
template <typename PA, typename PB>

flang/lib/Parser/expr-parsers.cpp

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ inline std::optional<Expr> MultOperand::Parse(ParseState &state) {
119119
// R1005 add-operand -> [add-operand mult-op] mult-operand
120120
// R1008 mult-op -> * | /
121121
// The left recursion in the grammar is implemented iteratively.
122-
constexpr struct AddOperand {
122+
struct AddOperand {
123123
using resultType = Expr;
124124
constexpr AddOperand() {}
125125
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -142,7 +142,8 @@ constexpr struct AddOperand {
142142
}
143143
return result;
144144
}
145-
} addOperand;
145+
};
146+
constexpr AddOperand addOperand;
146147

147148
// R1006 level-2-expr -> [[level-2-expr] add-op] add-operand
148149
// R1009 add-op -> + | -
@@ -151,7 +152,7 @@ constexpr struct AddOperand {
151152
// by means of a missing first operand; e.g., 2*-3 is valid in C but not
152153
// standard Fortran. We accept unary + and - to appear before any primary
153154
// as an extension.
154-
constexpr struct Level2Expr {
155+
struct Level2Expr {
155156
using resultType = Expr;
156157
constexpr Level2Expr() {}
157158
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -179,13 +180,14 @@ constexpr struct Level2Expr {
179180
}
180181
return result;
181182
}
182-
} level2Expr;
183+
};
184+
constexpr Level2Expr level2Expr;
183185

184186
// R1010 level-3-expr -> [level-3-expr concat-op] level-2-expr
185187
// R1011 concat-op -> //
186188
// Concatenation (//) is left-associative for parsing performance, although
187189
// one would never notice if it were right-associated.
188-
constexpr struct Level3Expr {
190+
struct Level3Expr {
189191
using resultType = Expr;
190192
constexpr Level3Expr() {}
191193
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -203,14 +205,15 @@ constexpr struct Level3Expr {
203205
}
204206
return result;
205207
}
206-
} level3Expr;
208+
};
209+
constexpr Level3Expr level3Expr;
207210

208211
// R1012 level-4-expr -> [level-3-expr rel-op] level-3-expr
209212
// R1013 rel-op ->
210213
// .EQ. | .NE. | .LT. | .LE. | .GT. | .GE. |
211214
// == | /= | < | <= | > | >= @ | <>
212215
// N.B. relations are not recursive (i.e., LOGICAL is not ordered)
213-
constexpr struct Level4Expr {
216+
struct Level4Expr {
214217
using resultType = Expr;
215218
constexpr Level4Expr() {}
216219
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -252,17 +255,19 @@ constexpr struct Level4Expr {
252255
}
253256
return result;
254257
}
255-
} level4Expr;
258+
};
259+
constexpr Level4Expr level4Expr;
256260

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

267272
// Match a logical operator or, optionally, its abbreviation.
268273
inline constexpr auto logicalOp(const char *op, const char *abbrev) {
@@ -283,7 +288,7 @@ inline std::optional<Expr> AndOperand::Parse(ParseState &state) {
283288
// R1015 or-operand -> [or-operand and-op] and-operand
284289
// R1019 and-op -> .AND.
285290
// .AND. is left-associative
286-
constexpr struct OrOperand {
291+
struct OrOperand {
287292
using resultType = Expr;
288293
constexpr OrOperand() {}
289294
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -303,12 +308,13 @@ constexpr struct OrOperand {
303308
}
304309
return result;
305310
}
306-
} orOperand;
311+
};
312+
constexpr OrOperand orOperand;
307313

308314
// R1016 equiv-operand -> [equiv-operand or-op] or-operand
309315
// R1020 or-op -> .OR.
310316
// .OR. is left-associative
311-
constexpr struct EquivOperand {
317+
struct EquivOperand {
312318
using resultType = Expr;
313319
constexpr EquivOperand() {}
314320
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -327,13 +333,14 @@ constexpr struct EquivOperand {
327333
}
328334
return result;
329335
}
330-
} equivOperand;
336+
};
337+
constexpr EquivOperand equivOperand;
331338

332339
// R1017 level-5-expr -> [level-5-expr equiv-op] equiv-operand
333340
// R1021 equiv-op -> .EQV. | .NEQV.
334341
// Logical equivalence is left-associative.
335342
// Extension: .XOR. as synonym for .NEQV.
336-
constexpr struct Level5Expr {
343+
struct Level5Expr {
337344
using resultType = Expr;
338345
constexpr Level5Expr() {}
339346
static inline std::optional<Expr> Parse(ParseState &state) {
@@ -358,7 +365,8 @@ constexpr struct Level5Expr {
358365
}
359366
return result;
360367
}
361-
} level5Expr;
368+
};
369+
constexpr Level5Expr level5Expr;
362370

363371
// R1022 expr -> [expr defined-binary-op] level-5-expr
364372
// Defined binary operators associate leftwards.

flang/lib/Parser/token-parsers.h

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ constexpr auto letter{"abcdefghijklmnopqrstuvwxyz"_ch};
6262
constexpr auto digit{"0123456789"_ch};
6363

6464
// Skips over optional spaces. Always succeeds.
65-
constexpr struct Space {
65+
struct Space {
6666
using resultType = Success;
6767
constexpr Space() {}
6868
static std::optional<Success> Parse(ParseState &state) {
@@ -74,7 +74,8 @@ constexpr struct Space {
7474
}
7575
return {Success{}};
7676
}
77-
} space;
77+
};
78+
constexpr Space space;
7879

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

88-
constexpr struct SpaceCheck {
89+
struct SpaceCheck {
8990
using resultType = Success;
9091
constexpr SpaceCheck() {}
9192
static std::optional<Success> Parse(ParseState &state) {
@@ -101,7 +102,8 @@ constexpr struct SpaceCheck {
101102
}
102103
return {Success{}};
103104
}
104-
} spaceCheck;
105+
};
106+
constexpr SpaceCheck spaceCheck;
105107

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

347349
// R711 digit-string -> digit [digit]...
348350
// N.B. not a token -- no space is skipped
349-
constexpr struct DigitString {
351+
struct DigitString {
350352
using resultType = CharBlock;
351353
static std::optional<resultType> Parse(ParseState &state) {
352354
if (std::optional<const char *> ch1{state.PeekAtNextChar()}) {
@@ -363,7 +365,8 @@ constexpr struct DigitString {
363365
}
364366
return std::nullopt;
365367
}
366-
} digitString;
368+
};
369+
constexpr DigitString digitString;
367370

368371
struct SignedIntLiteralConstantWithoutKind {
369372
using resultType = CharBlock;
@@ -380,7 +383,7 @@ struct SignedIntLiteralConstantWithoutKind {
380383
}
381384
};
382385

383-
constexpr struct DigitString64 {
386+
struct DigitString64 {
384387
using resultType = std::uint64_t;
385388
static std::optional<std::uint64_t> Parse(ParseState &state) {
386389
std::optional<const char *> firstDigit{digit.Parse(state)};
@@ -406,7 +409,8 @@ constexpr struct DigitString64 {
406409
}
407410
return {value};
408411
}
409-
} digitString64;
412+
};
413+
constexpr DigitString64 digitString64;
410414

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

540-
constexpr struct ConsumedAllInputParser {
544+
struct ConsumedAllInputParser {
541545
using resultType = Success;
542546
constexpr ConsumedAllInputParser() {}
543547
static inline std::optional<Success> Parse(ParseState &state) {
@@ -546,7 +550,8 @@ constexpr struct ConsumedAllInputParser {
546550
}
547551
return std::nullopt;
548552
}
549-
} consumedAllInput;
553+
};
554+
constexpr ConsumedAllInputParser consumedAllInput;
550555

551556
template <char goal> struct SkipPast {
552557
using resultType = Success;
@@ -599,7 +604,7 @@ inline constexpr auto optionalListBeforeColons(const PA &p) {
599604
// the ones that specify the source form) that might appear before the
600605
// next statement. Skip over empty statements (bare semicolons) when
601606
// not in strict standard conformance mode. Always succeeds.
602-
constexpr struct SkipStuffBeforeStatement {
607+
struct SkipStuffBeforeStatement {
603608
using resultType = Success;
604609
static std::optional<Success> Parse(ParseState &state) {
605610
if (UserState * ustate{state.userState()}) {
@@ -637,7 +642,8 @@ constexpr struct SkipStuffBeforeStatement {
637642
}
638643
return {Success{}};
639644
}
640-
} skipStuffBeforeStatement;
645+
};
646+
constexpr SkipStuffBeforeStatement skipStuffBeforeStatement;
641647

642648
// R602 underscore -> _
643649
constexpr auto underscore{"_"_ch};

0 commit comments

Comments
 (0)