bool Pre(const parser::IntrinsicTypeSpec::Real &);
bool Pre(const parser::IntrinsicTypeSpec::Complex &);
bool Pre(const parser::IntrinsicTypeSpec::DoublePrecision &);
+ bool Pre(const parser::IntrinsicTypeSpec::DoubleComplex &);
+ void Post(const parser::IntrinsicTypeSpec::Character &);
bool Pre(const parser::DeclarationTypeSpec::ClassStar &);
bool Pre(const parser::DeclarationTypeSpec::TypeStar &);
bool Pre(const parser::DeclarationTypeSpec::Record &);
void Post(const parser::TypeParamSpec &);
- bool Pre(const parser::TypeParamValue &);
+ void Post(const parser::TypeParamValue &);
void Post(const parser::StructureConstructor &);
bool Pre(const parser::AllocateStmt &);
void Post(const parser::AllocateStmt &);
void Post(const parser::EntityDecl &);
void Post(const parser::ObjectDecl &);
+
+ bool Pre(const parser::BindStmt &) { return BeginAttrs(); }
+ void Post(const parser::BindStmt &) { EndAttrs(); }
+ bool Pre(const parser::BindEntity &);
+ bool Pre(const parser::NamedConstantDef &);
bool Pre(const parser::AsynchronousStmt &);
bool Pre(const parser::ContiguousStmt &);
bool Pre(const parser::ExternalStmt &);
// Handle a statement that sets an attribute on a list of names.
bool HandleAttributeStmt(Attr, const std::list<parser::Name> &);
+ Symbol &HandleAttributeStmt(Attr, const SourceName &);
void DeclareObjectEntity(const parser::Name &, Attrs);
void DeclareProcEntity(const parser::Name &, Attrs, const ProcInterface &);
bool ConvertToProcEntity(Symbol &);
bool Pre(const parser::EndBlockStmt &);
bool Pre(const parser::ImplicitStmt &);
+ void Post(const parser::AllocateObject &x) {
+ CheckImplicitSymbol(std::get_if<parser::Name>(&x.u));
+ }
+ void Post(const parser::PointerAssignmentStmt &x) {
+ ResolveDataRef(std::get<parser::DataRef>(x.t));
+ }
void Post(const parser::Expr &x) { CheckImplicitSymbol(GetVariableName(x)); }
void Post(const parser::Variable &x) {
CheckImplicitSymbol(GetVariableName(x));
void DeclTypeSpecVisitor::Post(const parser::TypeParamSpec &x) {
typeParamValue_.reset();
}
-bool DeclTypeSpecVisitor::Pre(const parser::TypeParamValue &x) {
+void DeclTypeSpecVisitor::Post(const parser::TypeParamValue &x) {
typeParamValue_ = std::make_unique<ParamValue>(std::visit(
common::visitors{
// TODO: create IntExpr from ScalarIntExpr
},
},
x.u));
- return false;
}
bool DeclTypeSpecVisitor::Pre(const parser::DeclarationTypeSpec::Record &x) {
MakeIntrinsic(IntegerTypeSpec::Make(GetKindParamValue(x.v)));
return false;
}
+void DeclTypeSpecVisitor::Post(const parser::IntrinsicTypeSpec::Character &x) {
+ CHECK(!"TODO: character");
+}
bool DeclTypeSpecVisitor::Pre(const parser::IntrinsicTypeSpec::Logical &x) {
MakeIntrinsic(LogicalTypeSpec::Make(GetKindParamValue(x.kind)));
return false;
CHECK(!"TODO: double precision");
return false;
}
+bool DeclTypeSpecVisitor::Pre(
+ const parser::IntrinsicTypeSpec::DoubleComplex &) {
+ CHECK(!"TODO: double complex");
+ return false;
+}
void DeclTypeSpecVisitor::MakeIntrinsic(
const IntrinsicTypeSpec &intrinsicTypeSpec) {
SetDeclTypeSpec(DeclTypeSpec{intrinsicTypeSpec});
}
}
+bool DeclarationVisitor::Pre(const parser::BindEntity &x) {
+ auto &name{std::get<parser::Name>(x.t)};
+ if (std::get<parser::BindEntity::Kind>(x.t) ==
+ parser::BindEntity::Kind::Object) {
+ HandleAttributeStmt(Attr::BIND_C, name.source);
+ } else {
+ // TODO: name is common block
+ }
+ return false;
+}
+bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) {
+ auto &name{std::get<parser::NamedConstant>(x.t).v.source};
+ // TODO: auto &expr{std::get<parser::ConstantExpr>(x.t)};
+ // TODO: old-style parameters: type based on expr
+ auto &symbol{HandleAttributeStmt(Attr::PARAMETER, name)};
+ ApplyImplicitRules(name, symbol);
+ return false;
+}
bool DeclarationVisitor::Pre(const parser::AsynchronousStmt &x) {
return HandleAttributeStmt(Attr::ASYNCHRONOUS, x.v);
}
bool DeclarationVisitor::HandleAttributeStmt(
Attr attr, const std::list<parser::Name> &names) {
for (const auto &name : names) {
- const auto pair{currScope().try_emplace(name.source, Attrs{attr})};
- if (!pair.second) {
- // symbol was already there: set attribute on it
- Symbol &symbol{*pair.first->second};
- if (attr == Attr::ASYNCHRONOUS || attr == Attr::VOLATILE) {
- // TODO: if in a BLOCK, attribute should only be set while in the block
- } else if (symbol.has<UseDetails>()) {
- Say(*currStmtSource(),
- "Cannot change %s attribute on use-associated '%s'"_err_en_US,
- EnumToString(attr), name.source);
- }
- symbol.attrs().set(attr);
- symbol.add_occurrence(name.source);
- }
+ HandleAttributeStmt(attr, name.source);
}
return false;
}
+Symbol &DeclarationVisitor::HandleAttributeStmt(
+ Attr attr, const SourceName &name) {
+ const auto pair{currScope().try_emplace(name, Attrs{attr})};
+ Symbol &symbol{*pair.first->second};
+ if (!pair.second) {
+ // symbol was already there: set attribute on it
+ if (attr == Attr::ASYNCHRONOUS || attr == Attr::VOLATILE) {
+ // TODO: if in a BLOCK, attribute should only be set while in the block
+ } else if (symbol.has<UseDetails>()) {
+ Say(*currStmtSource(),
+ "Cannot change %s attribute on use-associated '%s'"_err_en_US,
+ EnumToString(attr), name);
+ }
+ symbol.attrs().set(attr);
+ symbol.add_occurrence(name);
+ }
+ return symbol;
+}
+
// Convert symbol to be a ProcEntity or return false if it can't be.
bool DeclarationVisitor::ConvertToProcEntity(Symbol &symbol) {
if (symbol.has<ProcEntityDetails>()) {
Symbol &symbol{DeclareEntity<ObjectEntityDetails>(name, attrs)};
if (auto *details{symbol.detailsIf<ObjectEntityDetails>()}) {
if (auto &type{GetDeclTypeSpec()}) {
- if (details->type()) {
- Say(name, "The type of '%s' has already been declared"_err_en_US);
- } else {
- details->set_type(*type);
- }
+ SetType(name.source, symbol, *type);
}
if (!arraySpec().empty()) {
if (!details->shape().empty()) {
void DeclarationVisitor::SetType(
const SourceName &name, Symbol &symbol, const DeclTypeSpec &type) {
- if (symbol.GetType()) {
+ auto *prevType{symbol.GetType()};
+ if (!prevType) {
+ symbol.SetType(type);
+ } else if (!symbol.test(Symbol::Flag::Implicit)) {
Say(name, "The type of '%s' has already been declared"_err_en_US);
- return;
+ } else if (type != *prevType) {
+ Say(name,
+ "The type of '%s' has already been implicitly declared"_err_en_US);
+ } else {
+ symbol.set(Symbol::Flag::Implicit, false);
}
- symbol.SetType(type);
}
// Find the Symbol for this derived type.
bool ResolveNamesVisitor::Pre(const parser::StructureComponent &x) {
ResolveStructureComponent(x);
- return false;
+ return true;
}
const Symbol *ResolveNamesVisitor::ResolveStructureComponent(
common::visitors{
[](const parser::ObjectName &x) { return &x; },
[&](const parser::DataRef &x) { return GetVariableName(x); },
- [](const auto &) {
- return static_cast<const parser::Name *>(nullptr);
+ [&](const parser::Substring &x) {
+ return GetVariableName(std::get<parser::DataRef>(x.t));
},
},
x.u);