Skip to content

Commit 2d8b6a4

Browse files
committed
[flang] Add explanatory messages to grammar for language extensions
Extend "extension<LanguageFeature>()" to incorporate an explanatory message better than the current generic "nonstandard usage:". Differential Revision: https://reviews.llvm.org/D122035
1 parent ddca666 commit 2d8b6a4

File tree

7 files changed

+128
-63
lines changed

7 files changed

+128
-63
lines changed

flang/lib/Parser/Fortran-parsers.cpp

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,16 @@ constexpr auto namedIntrinsicOperator{
6565
".EQV." >> pure(DefinedOperator::IntrinsicOperator::EQV) ||
6666
".NEQV." >> pure(DefinedOperator::IntrinsicOperator::NEQV) ||
6767
extension<LanguageFeature::XOROperator>(
68+
"nonstandard usage: .XOR. spelling of .NEQV."_port_en_US,
6869
".XOR." >> pure(DefinedOperator::IntrinsicOperator::NEQV)) ||
6970
extension<LanguageFeature::LogicalAbbreviations>(
71+
"nonstandard usage: abbreviated logical operator"_port_en_US,
7072
".N." >> pure(DefinedOperator::IntrinsicOperator::NOT) ||
71-
".A." >> pure(DefinedOperator::IntrinsicOperator::AND) ||
72-
".O." >> pure(DefinedOperator::IntrinsicOperator::OR) ||
73-
extension<LanguageFeature::XOROperator>(
74-
".X." >> pure(DefinedOperator::IntrinsicOperator::NEQV)))};
73+
".A." >> pure(DefinedOperator::IntrinsicOperator::AND) ||
74+
".O." >> pure(DefinedOperator::IntrinsicOperator::OR) ||
75+
extension<LanguageFeature::XOROperator>(
76+
"nonstandard usage: .X. spelling of .NEQV."_port_en_US,
77+
".X." >> pure(DefinedOperator::IntrinsicOperator::NEQV)))};
7578

7679
constexpr auto intrinsicOperator{
7780
"**" >> pure(DefinedOperator::IntrinsicOperator::Power) ||
@@ -83,6 +86,7 @@ constexpr auto intrinsicOperator{
8386
"-" >> pure(DefinedOperator::IntrinsicOperator::Subtract) ||
8487
"<=" >> pure(DefinedOperator::IntrinsicOperator::LE) ||
8588
extension<LanguageFeature::AlternativeNE>(
89+
"nonstandard usage: <> spelling of /= or .NE."_port_en_US,
8690
"<>" >> pure(DefinedOperator::IntrinsicOperator::NE)) ||
8791
"<" >> pure(DefinedOperator::IntrinsicOperator::LT) ||
8892
"==" >> pure(DefinedOperator::IntrinsicOperator::EQ) ||
@@ -178,6 +182,7 @@ TYPE_CONTEXT_PARSER("declaration type spec"_en_US,
178182
construct<DeclarationTypeSpec>("*" >>
179183
construct<DeclarationTypeSpec::ClassStar>())) ||
180184
extension<LanguageFeature::DECStructures>(
185+
"nonstandard usage: STRUCTURE"_port_en_US,
181186
construct<DeclarationTypeSpec>(
182187
// As is also done for the STRUCTURE statement, the name of
183188
// the structure includes the surrounding slashes to avoid
@@ -202,9 +207,11 @@ TYPE_CONTEXT_PARSER("intrinsic type spec"_en_US,
202207
"CHARACTER" >> maybe(Parser<CharSelector>{}))),
203208
construct<IntrinsicTypeSpec>(construct<IntrinsicTypeSpec::Logical>(
204209
"LOGICAL" >> maybe(kindSelector))),
205-
extension<LanguageFeature::DoubleComplex>(construct<IntrinsicTypeSpec>(
206-
"DOUBLE COMPLEX" >> construct<IntrinsicTypeSpec::DoubleComplex>())),
207-
extension<LanguageFeature::Byte>(
210+
extension<LanguageFeature::DoubleComplex>(
211+
"nonstandard usage: DOUBLE COMPLEX"_port_en_US,
212+
construct<IntrinsicTypeSpec>("DOUBLE COMPLEX" >>
213+
construct<IntrinsicTypeSpec::DoubleComplex>())),
214+
extension<LanguageFeature::Byte>("nonstandard usage: BYTE"_port_en_US,
208215
construct<IntrinsicTypeSpec>(construct<IntegerTypeSpec>(
209216
"BYTE" >> construct<std::optional<KindSelector>>(pure(1)))))))
210217

@@ -215,8 +222,10 @@ TYPE_PARSER(construct<IntegerTypeSpec>("INTEGER" >> maybe(kindSelector)))
215222
// Legacy extension: kind-selector -> * digit-string
216223
TYPE_PARSER(construct<KindSelector>(
217224
parenthesized(maybe("KIND ="_tok) >> scalarIntConstantExpr)) ||
218-
extension<LanguageFeature::StarKind>(construct<KindSelector>(
219-
construct<KindSelector::StarSize>("*" >> digitString64 / spaceCheck))))
225+
extension<LanguageFeature::StarKind>(
226+
"nonstandard usage: TYPE*KIND syntax"_port_en_US,
227+
construct<KindSelector>(construct<KindSelector::StarSize>(
228+
"*" >> digitString64 / spaceCheck))))
220229

221230
// R707 signed-int-literal-constant -> [sign] int-literal-constant
222231
TYPE_PARSER(sourced(construct<SignedIntLiteralConstant>(
@@ -251,7 +260,9 @@ constexpr auto signedRealLiteralConstant{
251260
// Extension: Q
252261
// R717 exponent -> signed-digit-string
253262
constexpr auto exponentPart{
254-
("ed"_ch || extension<LanguageFeature::QuadPrecision>("q"_ch)) >>
263+
("ed"_ch ||
264+
extension<LanguageFeature::QuadPrecision>(
265+
"nonstandard usage: Q exponent"_port_en_US, "q"_ch)) >>
255266
SignedDigitString{}};
256267

257268
TYPE_CONTEXT_PARSER("REAL literal constant"_en_US,
@@ -431,6 +442,7 @@ TYPE_CONTEXT_PARSER("component declaration"_en_US,
431442
// The source field of the Name will be replaced with a distinct generated name.
432443
TYPE_CONTEXT_PARSER("%FILL item"_en_US,
433444
extension<LanguageFeature::DECStructures>(
445+
"nonstandard usage: %FILL"_port_en_US,
434446
construct<FillDecl>(space >> sourced("%FILL" >> construct<Name>()),
435447
maybe(Parser<ComponentArraySpec>{}), maybe("*" >> charLength))))
436448
TYPE_PARSER(construct<ComponentOrFill>(Parser<ComponentDecl>{}) ||
@@ -475,10 +487,12 @@ constexpr auto initialDataTarget{indirect(designator)};
475487
TYPE_PARSER(construct<Initialization>("=>" >> nullInit) ||
476488
construct<Initialization>("=>" >> initialDataTarget) ||
477489
construct<Initialization>("=" >> constantExpr) ||
478-
extension<LanguageFeature::SlashInitialization>(construct<Initialization>(
479-
"/" >> nonemptyList("expected values"_err_en_US,
480-
indirect(Parser<DataStmtValue>{})) /
481-
"/")))
490+
extension<LanguageFeature::SlashInitialization>(
491+
"nonstandard usage: /initialization/"_port_en_US,
492+
construct<Initialization>(
493+
"/" >> nonemptyList("expected values"_err_en_US,
494+
indirect(Parser<DataStmtValue>{})) /
495+
"/")))
482496

483497
// R745 private-components-stmt -> PRIVATE
484498
// R747 binding-private-stmt -> PRIVATE
@@ -608,10 +622,12 @@ TYPE_PARSER(
608622
nonemptyList("expected entity declarations"_err_en_US,
609623
entityDeclWithoutEqInit)) ||
610624
// PGI-only extension: comma in place of doubled colons
611-
extension<LanguageFeature::MissingColons>(construct<TypeDeclarationStmt>(
612-
declarationTypeSpec, defaulted("," >> nonemptyList(Parser<AttrSpec>{})),
613-
withMessage("expected entity declarations"_err_en_US,
614-
"," >> nonemptyList(entityDecl)))))
625+
extension<LanguageFeature::MissingColons>(
626+
"nonstandard usage: ',' in place of '::'"_port_en_US,
627+
construct<TypeDeclarationStmt>(declarationTypeSpec,
628+
defaulted("," >> nonemptyList(Parser<AttrSpec>{})),
629+
withMessage("expected entity declarations"_err_en_US,
630+
"," >> nonemptyList(entityDecl)))))
615631

616632
// R802 attr-spec ->
617633
// access-spec | ALLOCATABLE | ASYNCHRONOUS |
@@ -841,6 +857,7 @@ TYPE_PARSER(sourced(first(construct<DataStmtConstant>(literalConstant),
841857
construct<DataStmtConstant>(signedRealLiteralConstant),
842858
construct<DataStmtConstant>(signedIntLiteralConstant),
843859
extension<LanguageFeature::SignedComplexLiteral>(
860+
"nonstandard usage: signed COMPLEX literal"_port_en_US,
844861
construct<DataStmtConstant>(Parser<SignedComplexLiteralConstant>{})),
845862
construct<DataStmtConstant>(nullInit),
846863
construct<DataStmtConstant>(indirect(designator) / !"("_tok),
@@ -869,8 +886,10 @@ TYPE_CONTEXT_PARSER("PARAMETER statement"_en_US,
869886
construct<ParameterStmt>(
870887
"PARAMETER" >> parenthesized(nonemptyList(Parser<NamedConstantDef>{}))))
871888
TYPE_CONTEXT_PARSER("old style PARAMETER statement"_en_US,
872-
extension<LanguageFeature::OldStyleParameter>(construct<OldParameterStmt>(
873-
"PARAMETER" >> nonemptyList(Parser<NamedConstantDef>{}))))
889+
extension<LanguageFeature::OldStyleParameter>(
890+
"nonstandard usage: PARAMETER without parentheses"_port_en_US,
891+
construct<OldParameterStmt>(
892+
"PARAMETER" >> nonemptyList(Parser<NamedConstantDef>{}))))
874893
875894
// R852 named-constant-def -> named-constant = constant-expr
876895
TYPE_PARSER(construct<NamedConstantDef>(namedConstant, "=" >> constantExpr))
@@ -1024,6 +1043,7 @@ TYPE_CONTEXT_PARSER("designator"_en_US,
10241043
constexpr auto percentOrDot{"%"_tok ||
10251044
// legacy VAX extension for RECORD field access
10261045
extension<LanguageFeature::DECStructures>(
1046+
"nonstandard usage: component access with '.' in place of '%'"_port_en_US,
10271047
"."_tok / lookAhead(OldStructureComponentName{}))};
10281048
10291049
// R902 variable -> designator | function-reference
@@ -1184,10 +1204,12 @@ TYPE_PARSER(beginDirective >>
11841204
maybe(("="_tok || ":"_tok) >> digitString64))))) /
11851205
endDirective)
11861206

1187-
TYPE_PARSER(extension<LanguageFeature::CrayPointer>(construct<BasedPointerStmt>(
1188-
"POINTER" >> nonemptyList("expected POINTER associations"_err_en_US,
1189-
construct<BasedPointer>("(" >> objectName / ",",
1190-
objectName, maybe(Parser<ArraySpec>{}) / ")")))))
1207+
TYPE_PARSER(extension<LanguageFeature::CrayPointer>(
1208+
"nonstandard usage: based POINTER"_port_en_US,
1209+
construct<BasedPointerStmt>(
1210+
"POINTER" >> nonemptyList("expected POINTER associations"_err_en_US,
1211+
construct<BasedPointer>("(" >> objectName / ",",
1212+
objectName, maybe(Parser<ArraySpec>{}) / ")")))))
11911213

11921214
// Subtle: the name includes the surrounding slashes, which avoids
11931215
// clashes with other uses of the name in the same scope.
@@ -1206,10 +1228,12 @@ TYPE_PARSER(construct<StructureField>(statement(StructureComponents{})) ||
12061228
construct<StructureField>(indirect(nestedStructureDef)))
12071229

12081230
TYPE_CONTEXT_PARSER("STRUCTURE definition"_en_US,
1209-
extension<LanguageFeature::DECStructures>(construct<StructureDef>(
1210-
statement(Parser<StructureStmt>{}), many(Parser<StructureField>{}),
1211-
statement(
1212-
construct<StructureDef::EndStructureStmt>("END STRUCTURE"_tok)))))
1231+
extension<LanguageFeature::DECStructures>(
1232+
"nonstandard usage: STRUCTURE"_port_en_US,
1233+
construct<StructureDef>(statement(Parser<StructureStmt>{}),
1234+
many(Parser<StructureField>{}),
1235+
statement(construct<StructureDef::EndStructureStmt>(
1236+
"END STRUCTURE"_tok)))))
12131237

12141238
TYPE_CONTEXT_PARSER("UNION definition"_en_US,
12151239
construct<Union>(statement(construct<Union::UnionStmt>("UNION"_tok)),

flang/lib/Parser/basic-parsers.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,8 @@ template <LanguageFeature LF, typename PA> class NonstandardParser {
845845
public:
846846
using resultType = typename PA::resultType;
847847
constexpr NonstandardParser(const NonstandardParser &) = default;
848-
constexpr NonstandardParser(PA parser) : parser_{parser} {}
848+
constexpr NonstandardParser(PA parser, MessageFixedText msg)
849+
: parser_{parser}, message_{msg} {}
849850
std::optional<resultType> Parse(ParseState &state) const {
850851
if (UserState * ustate{state.userState()}) {
851852
if (!ustate->features().IsEnabled(LF)) {
@@ -855,19 +856,20 @@ template <LanguageFeature LF, typename PA> class NonstandardParser {
855856
auto at{state.GetLocation()};
856857
auto result{parser_.Parse(state)};
857858
if (result) {
858-
state.Nonstandard(CharBlock{at, std::max(state.GetLocation(), at + 1)},
859-
LF, "nonstandard usage"_port_en_US);
859+
state.Nonstandard(
860+
CharBlock{at, std::max(state.GetLocation(), at + 1)}, LF, message_);
860861
}
861862
return result;
862863
}
863864

864865
private:
865866
const PA parser_;
867+
const MessageFixedText message_;
866868
};
867869

868870
template <LanguageFeature LF, typename PA>
869-
inline constexpr auto extension(PA parser) {
870-
return NonstandardParser<LF, PA>(parser);
871+
inline constexpr auto extension(MessageFixedText feature, PA parser) {
872+
return NonstandardParser<LF, PA>(parser, feature);
871873
}
872874

873875
// If a is a parser for some deprecated or deleted language feature LF,

flang/lib/Parser/executable-parsers.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ TYPE_PARSER(recovery(
7676
construct<ExecutionPartConstruct>(
7777
statement(indirect(dataStmt))),
7878
extension<LanguageFeature::ExecutionPartNamelist>(
79+
"nonstandard usage: NAMELIST in execution part"_port_en_US,
7980
construct<ExecutionPartConstruct>(
8081
statement(indirect(Parser<NamelistStmt>{})))),
8182
obsoleteExecutionPartConstruct))),

flang/lib/Parser/expr-parsers.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ TYPE_PARSER(construct<AcSpec>(maybe(typeSpec / "::"),
4444
TYPE_PARSER(
4545
// PGI/Intel extension: accept triplets in array constructors
4646
extension<LanguageFeature::TripletInArrayConstructor>(
47+
"nonstandard usage: triplet in array constructor"_port_en_US,
4748
construct<AcValue>(construct<AcValue::Triplet>(scalarIntExpr,
4849
":" >> scalarIntExpr, maybe(":" >> scalarIntExpr)))) ||
4950
construct<AcValue>(indirect(expr)) ||
@@ -76,19 +77,24 @@ constexpr auto primary{instrumented("primary"_en_US,
7677
construct<Expr>(Parser<ArrayConstructor>{}),
7778
// PGI/XLF extension: COMPLEX constructor (x,y)
7879
extension<LanguageFeature::ComplexConstructor>(
80+
"nonstandard usage: generalized COMPLEX constructor"_port_en_US,
7981
construct<Expr>(parenthesized(
8082
construct<Expr::ComplexConstructor>(expr, "," >> expr)))),
81-
extension<LanguageFeature::PercentLOC>(construct<Expr>("%LOC" >>
82-
parenthesized(construct<Expr::PercentLoc>(indirect(variable)))))))};
83+
extension<LanguageFeature::PercentLOC>(
84+
"nonstandard usage: %LOC"_port_en_US,
85+
construct<Expr>("%LOC" >> parenthesized(construct<Expr::PercentLoc>(
86+
indirect(variable)))))))};
8387

8488
// R1002 level-1-expr -> [defined-unary-op] primary
8589
// TODO: Reasonable extension: permit multiple defined-unary-ops
8690
constexpr auto level1Expr{sourced(
8791
first(primary, // must come before define op to resolve .TRUE._8 ambiguity
8892
construct<Expr>(construct<Expr::DefinedUnary>(definedOpName, primary)),
8993
extension<LanguageFeature::SignedPrimary>(
94+
"nonstandard usage: signed primary"_port_en_US,
9095
construct<Expr>(construct<Expr::UnaryPlus>("+" >> primary))),
9196
extension<LanguageFeature::SignedPrimary>(
97+
"nonstandard usage: signed primary"_port_en_US,
9298
construct<Expr>(construct<Expr::Negate>("-" >> primary)))))};
9399

94100
// R1004 mult-operand -> level-1-expr [power-op mult-operand]
@@ -244,6 +250,7 @@ struct Level4Expr {
244250
(".EQ."_tok || "=="_tok) >> applyLambda(eq, level3Expr) ||
245251
(".NE."_tok || "/="_tok ||
246252
extension<LanguageFeature::AlternativeNE>(
253+
"nonstandard usage: <> for /= or .NE."_port_en_US,
247254
"<>"_tok /* PGI/Cray extension; Cray also has .LG. */)) >>
248255
applyLambda(ne, level3Expr) ||
249256
(".GE."_tok || ">="_tok) >> applyLambda(ge, level3Expr) ||
@@ -273,6 +280,7 @@ constexpr AndOperand andOperand;
273280
inline constexpr auto logicalOp(const char *op, const char *abbrev) {
274281
return TokenStringMatch{op} ||
275282
extension<LanguageFeature::LogicalAbbreviations>(
283+
"nonstandard usage: abbreviated LOGICAL operator"_port_en_US,
276284
TokenStringMatch{abbrev});
277285
}
278286

@@ -356,6 +364,7 @@ struct Level5Expr {
356364
auto more{attempt(sourced(".EQV." >> applyLambda(eqv, equivOperand) ||
357365
(".NEQV."_tok ||
358366
extension<LanguageFeature::XOROperator>(
367+
"nonstandard usage: .XOR./.X. spelling of .NEQV."_port_en_US,
359368
logicalOp(".XOR.", ".X."))) >>
360369
applyLambda(neqv, equivOperand)))};
361370
while (std::optional<Expr> next{more.Parse(state)}) {
@@ -397,8 +406,10 @@ template <> std::optional<Expr> Parser<Expr>::Parse(ParseState &state) {
397406
// and intrinsic operator names; this is handled by attempting their parses
398407
// first, and by name resolution on their definitions, for best errors.
399408
// N.B. The name of the operator is captured with the dots around it.
400-
constexpr auto definedOpNameChar{
401-
letter || extension<LanguageFeature::PunctuationInNames>("$@"_ch)};
409+
constexpr auto definedOpNameChar{letter ||
410+
extension<LanguageFeature::PunctuationInNames>(
411+
"nonstandard usage: non-alphabetic character in defined operator"_port_en_US,
412+
"$@"_ch)};
402413
TYPE_PARSER(
403414
space >> construct<DefinedOpName>(sourced("."_ch >>
404415
some(definedOpNameChar) >> construct<Name>() / "."_ch)))

0 commit comments

Comments
 (0)