[flang] Look for declared STRUCTURE component names after a . rather than defined operator names.
Original-commit: flang-compiler/f18@cf64809551 Reviewed-on: https://github.com/flang-compiler/f18/pull/37 Tree-same-pre-rewrite: false
This commit is contained in:
parent
3a0351e43c
commit
f8c7fde5c2
|
@ -1633,26 +1633,25 @@ TYPE_PARSER(space >> "."_ch >>
|
||||||
// R911 data-ref -> part-ref [% part-ref]...
|
// R911 data-ref -> part-ref [% part-ref]...
|
||||||
// R914 coindexed-named-object -> data-ref
|
// R914 coindexed-named-object -> data-ref
|
||||||
// R917 array-element -> data-ref
|
// R917 array-element -> data-ref
|
||||||
constexpr struct DefinedOperatorName {
|
constexpr struct StructureComponentName {
|
||||||
using resultType = Success;
|
using resultType = Name;
|
||||||
static std::optional<Success> Parse(ParseState *state) {
|
static std::optional<Name> Parse(ParseState *state) {
|
||||||
if (std::optional<DefinedOpName> n{definedOpName.Parse(state)}) {
|
if (std::optional<Name> n{name.Parse(state)}) {
|
||||||
if (const auto *user = state->userState()) {
|
if (const auto *user = state->userState()) {
|
||||||
if (user->IsDefinedOperator(n->v.source)) {
|
if (user->IsStructureComponent(n->source)) {
|
||||||
return {Success{}};
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
} definedOperatorName;
|
} structureComponentName;
|
||||||
|
|
||||||
constexpr auto percentOrDot = "%"_tok ||
|
constexpr auto percentOrDot = "%"_tok ||
|
||||||
// legacy VAX extension for RECORD field access
|
// legacy VAX extension for RECORD field access
|
||||||
// TODO: this clashes with user-defined operators in modern Fortran!
|
extension("."_tok / lookAhead(structureComponentName));
|
||||||
// This work-around is incomplete; it can't see into modules.
|
|
||||||
extension(!namedIntrinsicOperator >> !definedOperatorName >> "."_tok);
|
|
||||||
|
|
||||||
|
// TODO - why is this not a TYPE_PARSER?
|
||||||
template<>
|
template<>
|
||||||
std::optional<DataReference> Parser<DataReference>::Parse(ParseState *state) {
|
std::optional<DataReference> Parser<DataReference>::Parse(ParseState *state) {
|
||||||
static constexpr auto partRefs =
|
static constexpr auto partRefs =
|
||||||
|
@ -3386,24 +3385,8 @@ TYPE_PARSER(construct<ProcedureStmt>{}("MODULE PROCEDURE"_sptok >>
|
||||||
// R1509 defined-io-generic-spec ->
|
// R1509 defined-io-generic-spec ->
|
||||||
// READ ( FORMATTED ) | READ ( UNFORMATTED ) |
|
// READ ( FORMATTED ) | READ ( UNFORMATTED ) |
|
||||||
// WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
|
// WRITE ( FORMATTED ) | WRITE ( UNFORMATTED )
|
||||||
constexpr struct NoteOperatorDefinition {
|
|
||||||
using resultType = DefinedOperator;
|
|
||||||
static std::optional<DefinedOperator> Parse(ParseState *state) {
|
|
||||||
static constexpr auto definedOperator = Parser<DefinedOperator>{};
|
|
||||||
std::optional<DefinedOperator> op{definedOperator.Parse(state)};
|
|
||||||
if (op.has_value()) {
|
|
||||||
if (auto ustate = state->userState()) {
|
|
||||||
if (const auto *name = std::get_if<DefinedOpName>(&op->u)) {
|
|
||||||
ustate->NoteDefinedOperator(name->v.source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
} noteOperatorDefinition;
|
|
||||||
|
|
||||||
TYPE_PARSER(construct<GenericSpec>{}(
|
TYPE_PARSER(construct<GenericSpec>{}(
|
||||||
"OPERATOR" >> parenthesized(noteOperatorDefinition)) ||
|
"OPERATOR" >> parenthesized(definedOperator)) ||
|
||||||
construct<GenericSpec>{}(
|
construct<GenericSpec>{}(
|
||||||
"ASSIGNMENT ( = )" >> construct<GenericSpec::Assignment>{}) ||
|
"ASSIGNMENT ( = )" >> construct<GenericSpec::Assignment>{}) ||
|
||||||
construct<GenericSpec>{}(
|
construct<GenericSpec>{}(
|
||||||
|
@ -3664,8 +3647,24 @@ TYPE_PARSER(construct<StructureStmt>{}("STRUCTURE /" >> name / "/", pure(true),
|
||||||
construct<StructureStmt>{}(
|
construct<StructureStmt>{}(
|
||||||
"STRUCTURE" >> name, pure(false), defaulted(cut >> many(entityDecl))))
|
"STRUCTURE" >> name, pure(false), defaulted(cut >> many(entityDecl))))
|
||||||
|
|
||||||
|
constexpr struct StructureComponents {
|
||||||
|
using resultType = DataComponentDefStmt;
|
||||||
|
static std::optional<DataComponentDefStmt> Parse(ParseState *state) {
|
||||||
|
static constexpr auto stmt = Parser<DataComponentDefStmt>{};
|
||||||
|
std::optional<DataComponentDefStmt> defs{stmt.Parse(state)};
|
||||||
|
if (defs.has_value()) {
|
||||||
|
if (auto ustate = state->userState()) {
|
||||||
|
for (const auto &decl : std::get<std::list<ComponentDecl>>(defs->t)) {
|
||||||
|
ustate->NoteStructureComponent(std::get<Name>(decl.t).source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defs;
|
||||||
|
}
|
||||||
|
} structureComponents;
|
||||||
|
|
||||||
TYPE_PARSER(
|
TYPE_PARSER(
|
||||||
construct<StructureField>{}(statement(Parser<DataComponentDefStmt>{})) ||
|
construct<StructureField>{}(statement(structureComponents)) ||
|
||||||
construct<StructureField>{}(indirect(Parser<Union>{})) ||
|
construct<StructureField>{}(indirect(Parser<Union>{})) ||
|
||||||
construct<StructureField>{}(indirect(Parser<StructureDef>{})))
|
construct<StructureField>{}(indirect(Parser<StructureDef>{})))
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
void NewSubprogram() {
|
void NewSubprogram() {
|
||||||
doLabels_.clear();
|
doLabels_.clear();
|
||||||
nonlabelDoConstructNestingDepth_ = 0;
|
nonlabelDoConstructNestingDepth_ = 0;
|
||||||
|
structureComponents_.clear();
|
||||||
}
|
}
|
||||||
void EnterNonlabelDoConstruct() { ++nonlabelDoConstructNestingDepth_; }
|
void EnterNonlabelDoConstruct() { ++nonlabelDoConstructNestingDepth_; }
|
||||||
void LeaveDoConstruct() {
|
void LeaveDoConstruct() {
|
||||||
|
@ -35,18 +36,18 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoteDefinedOperator(const CharBlock &opr) {
|
void NoteStructureComponent(const CharBlock &name) {
|
||||||
definedOperators_.insert(opr);
|
structureComponents_.insert(name);
|
||||||
}
|
}
|
||||||
bool IsDefinedOperator(const CharBlock &opr) const {
|
bool IsStructureComponent(const CharBlock &name) const {
|
||||||
return definedOperators_.find(opr) != definedOperators_.end();
|
return structureComponents_.find(name) != structureComponents_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_set<Label> doLabels_;
|
std::unordered_set<Label> doLabels_;
|
||||||
int nonlabelDoConstructNestingDepth_{0};
|
int nonlabelDoConstructNestingDepth_{0};
|
||||||
|
|
||||||
std::set<CharBlock> definedOperators_;
|
std::set<CharBlock> structureComponents_;
|
||||||
};
|
};
|
||||||
} // namespace parser
|
} // namespace parser
|
||||||
} // namespace Fortran
|
} // namespace Fortran
|
||||||
|
|
Loading…
Reference in a new issue