protected:
// Set when we see a stmt function that is really an array element assignment
- bool badStmtFuncFound_{false};
+ bool misparsedStmtFuncFound_{false};
private:
// Edits an existing symbol created for earlier calls to a subprogram or ENTRY
}
}
void ScopeHandler::PopScope() {
+ CHECK(currScope_ && !currScope_->IsGlobal());
// Entities that are not yet classified as objects or procedures are now
// assumed to be objects.
// TODO: Statement functions
const DeclTypeSpec *resultType{nullptr};
// Look up name: provides return type or tells us if it's an array
if (auto *symbol{FindSymbol(name)}) {
- auto *details{symbol->detailsIf<EntityDetails>()};
- if (!details || symbol->has<ObjectEntityDetails>() ||
- symbol->has<ProcEntityDetails>()) {
- badStmtFuncFound_ = true;
+ Symbol &ultimate{symbol->GetUltimate()};
+ if (ultimate.has<ObjectEntityDetails>() ||
+ CouldBeDataPointerValuedFunction(&ultimate)) {
+ misparsedStmtFuncFound_ = true;
return false;
}
- // TODO: check that attrs are compatible with stmt func
- resultType = details->type();
- symbol->details() = UnknownDetails{}; // will be replaced below
+ if (DoesScopeContain(&ultimate.owner(), currScope())) {
+ Say(name,
+ "Name '%s' from host scope should have a type declaration before its local statement function definition"_port_en_US);
+ MakeSymbol(name, Attrs{}, UnknownDetails{});
+ } else if (auto *entity{ultimate.detailsIf<EntityDetails>()};
+ entity && !ultimate.has<ProcEntityDetails>()) {
+ resultType = entity->type();
+ ultimate.details() = UnknownDetails{}; // will be replaced below
+ } else {
+ misparsedStmtFuncFound_ = true;
+ }
}
- if (badStmtFuncFound_) {
- Say(name, "'%s' has not been declared as an array"_err_en_US);
+ if (misparsedStmtFuncFound_) {
+ Say(name,
+ "'%s' has not been declared as an array or pointer-valued function"_err_en_US);
return false;
}
auto &symbol{PushSubprogramScope(name, Symbol::Flag::Function)};
void ResolveNamesVisitor::FinishSpecificationPart(
const std::list<parser::DeclarationConstruct> &decls) {
- badStmtFuncFound_ = false;
+ misparsedStmtFuncFound_ = false;
funcResultStack().CompleteFunctionResultType();
CheckImports();
bool inModule{currScope().kind() == Scope::Kind::Module};
const auto &name{std::get<parser::Name>(stmtFunc.t)};
Symbol *symbol{name.symbol};
auto *details{symbol ? symbol->detailsIf<SubprogramDetails>() : nullptr};
- if (!details || !symbol->scope()) {
- return;
+ if (!details || !symbol->scope() ||
+ &symbol->scope()->parent() != &currScope()) {
+ return; // error recovery
}
// Resolve the symbols on the RHS of the statement function.
PushScope(*symbol->scope());
if (HandleStmtFunction(x)) {
return false;
} else {
- // This is an array element assignment: resolve names of indices
+ // This is an array element or pointer-valued function assignment:
+ // resolve the names of indices/arguments
const auto &names{std::get<std::list<parser::Name>>(x.t)};
for (auto &name : names) {
ResolveName(name);