static std::optional<Name> Parse(ParseState *state) {
if (std::optional<Name> n{name.Parse(state)}) {
if (const auto *user = state->userState()) {
- if (user->IsStructureComponent(n->source)) {
+ if (user->IsOldStructureComponent(n->source)) {
return n;
}
}
return {std::move(**funcref)};
}
Designator *desig{&*std::get<Indirection<Designator>>(var->u)};
- if (std::optional<Call> call{desig->ConvertToCall()}) {
+ if (std::optional<Call> call{desig->ConvertToCall(state->userState())}) {
if (!std::get<std::list<ActualArgSpec>>(call.value().t).empty()) {
// Parsed a designator that ended with a nonempty list of subscripts
// that have all been converted to actual arguments.
return {CallStmt{std::move((*funcref)->v)}};
}
Designator *desig{&*std::get<Indirection<Designator>>(var->u)};
- if (std::optional<Call> call{desig->ConvertToCall()}) {
+ if (std::optional<Call> call{desig->ConvertToCall(state->userState())}) {
return {CallStmt{std::move(call.value())}};
}
}
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);
+ ustate->NoteOldStructureComponent(std::get<Name>(decl.t).source);
}
}
}
#include "parse-tree.h"
#include "idioms.h"
#include "indirection.h"
+#include "user-state.h"
#include <algorithm>
namespace Fortran {
visitors{
[](ObjectName &n) -> ProcedureDesignator { return {std::move(n)}; },
[](DataReference &dr) -> ProcedureDesignator {
- if (Name *n = std::get_if<Name>(&dr.u)) {
+ if (Name * n{std::get_if<Name>(&dr.u)}) {
return {std::move(*n)};
}
StructureComponent &sc{
u);
}
-std::optional<Call> Designator::ConvertToCall() {
+std::optional<Call> Designator::ConvertToCall(const UserState *ustate) {
return std::visit(
visitors{[](ObjectName &n) -> std::optional<Call> {
return {Call{ProcedureDesignator{std::move(n)},
std::list<ActualArgSpec>{}}};
},
- [this](DataReference &dr) -> std::optional<Call> {
+ [=](DataReference &dr) -> std::optional<Call> {
if (std::holds_alternative<Indirection<CoindexedNamedObject>>(
dr.u)) {
return {};
}
- if (Name *n = std::get_if<Name>(&dr.u)) {
+ if (Name * n{std::get_if<Name>(&dr.u)}) {
return {Call{ProcedureDesignator{std::move(*n)},
std::list<ActualArgSpec>{}}};
}
if (auto *isc =
std::get_if<Indirection<StructureComponent>>(&dr.u)) {
StructureComponent &sc{**isc};
+ if (ustate &&
+ ustate->IsOldStructureComponent(sc.component.source)) {
+ return {};
+ }
Variable var{Indirection<Designator>{std::move(sc.base)}};
ProcComponentRef pcr{
Scalar<Variable>{std::move(var)}, std::move(sc.component)};
}
StructureComponent &bsc{
*std::get<Indirection<StructureComponent>>(ae.base.u)};
+ if (ustate &&
+ ustate->IsOldStructureComponent(bsc.component.source)) {
+ return {};
+ }
Variable var{Indirection<Designator>{std::move(bsc.base)}};
ProcComponentRef pcr{
Scalar<Variable>{std::move(var)}, std::move(bsc.component)};
#include "indirection.h"
#include "message.h"
#include "provenance.h"
+#include "user-state.h"
#include <cinttypes>
#include <list>
#include <optional>
UNION_CLASS_BOILERPLATE(Designator);
bool EndsInBareName() const;
ProcedureDesignator ConvertToProcedureDesignator();
- std::optional<Call> ConvertToCall();
+ std::optional<Call> ConvertToCall(const UserState *ustate = nullptr);
std::variant<ObjectName, DataReference, Substring> u;
};
.set_encoding(options.encoding)
.set_enableBackslashEscapesInCharLiterals(options.enableBackslashEscapes)
.set_enableOldDebugLines(options.enableOldDebugLines)
+ .set_warnOnNonstandardUsage(options_.isStrictlyStandard)
.AddCompilerDirectiveSentinel("dir$");
ProvenanceRange range{
allSources_.AddIncludedFile(*sourceFile, ProvenanceRange{})};
enableOldDebugLines_{that.enableOldDebugLines_},
enableBackslashEscapesInCharLiterals_{
that.enableBackslashEscapesInCharLiterals_},
+ warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
compilerDirectiveBloomFilter_{that.compilerDirectiveBloomFilter_},
compilerDirectiveSentinels_{that.compilerDirectiveSentinels_} {}
}
// Normal case: not in a compiler directive.
if (*p == '&') {
- return p + 1; // extension; TODO: emit warning with -Mstandard
+ // Extension: '&' as continuation marker
+ if (warnOnNonstandardUsage_) {
+ Complain("nonstandard usage"_en_US, GetProvenance(p));
+ }
+ return p + 1;
}
if (*p == '\t' && p[1] >= '1' && p[1] <= '9') {
tabInCurrentLine_ = true;
fixedFormColumnLimit_ = limit;
return *this;
}
+ Prescanner &set_warnOnNonstandardUsage(bool yes) {
+ warnOnNonstandardUsage_ = yes;
+ return *this;
+ }
Prescanner &AddCompilerDirectiveSentinel(const std::string &);
Encoding encoding_{Encoding::UTF8};
bool enableOldDebugLines_{false};
bool enableBackslashEscapesInCharLiterals_{true};
+ bool warnOnNonstandardUsage_{false};
int delimiterNesting_{0};
Provenance startProvenance_;
void NewSubprogram() {
doLabels_.clear();
nonlabelDoConstructNestingDepth_ = 0;
- structureComponents_.clear();
+ oldStructureComponents_.clear();
}
using Label = std::uint64_t;
}
}
- void NoteStructureComponent(const CharBlock &name) {
- structureComponents_.insert(name);
+ void NoteOldStructureComponent(const CharBlock &name) {
+ oldStructureComponents_.insert(name);
}
- bool IsStructureComponent(const CharBlock &name) const {
- return structureComponents_.find(name) != structureComponents_.end();
+ bool IsOldStructureComponent(const CharBlock &name) const {
+ return oldStructureComponents_.find(name) != oldStructureComponents_.end();
}
private:
std::unordered_set<Label> doLabels_;
int nonlabelDoConstructNestingDepth_{0};
- std::set<CharBlock> structureComponents_;
+ std::set<CharBlock> oldStructureComponents_;
};
} // namespace parser
} // namespace Fortran