} derived;
};
+ // Walk the parse tree of a type spec and return the DeclTypeSpec for it.
+ template<typename T> const DeclTypeSpec *ProcessTypeSpec(const T &x) {
+ auto save{common::ScopedSet(state_, State{})};
+ BeginDeclTypeSpec();
+ Walk(x);
+ const auto *type{GetDeclTypeSpec()};
+ EndDeclTypeSpec();
+ return type;
+ }
+
const DeclTypeSpec *GetDeclTypeSpec();
void BeginDeclTypeSpec();
void EndDeclTypeSpec();
- State SetDeclTypeSpecState(State);
void SetDeclTypeSpec(const DeclTypeSpec &);
void SetDeclTypeSpecCategory(DeclTypeSpec::Category);
DeclTypeSpec::Category GetDeclTypeSpecCategory() const {
bool Pre(const parser::SeparateModuleSubprogram &);
void Post(const parser::SeparateModuleSubprogram &);
bool Pre(const parser::Suffix &);
+ bool Pre(const parser::PrefixSpec &);
protected:
// Set when we see a stmt function that is really an array element assignment
bool badStmtFuncFound_{false};
+ void HandleFunctionPrefixType();
private:
- // Function result name from parser::Suffix, if any.
- const parser::Name *funcResultName_{nullptr};
+ // Info about the current function: parse tree of the type in the PrefixSpec;
+ // name and symbol of the function result from the Suffix; source location.
+ struct {
+ const parser::DeclarationTypeSpec *parsedType{nullptr};
+ const parser::Name *resultName{nullptr};
+ Symbol *resultSymbol{nullptr};
+ const SourceName *source{nullptr};
+ } funcInfo_;
bool BeginSubprogram(const parser::Name &, Symbol::Flag, bool hasModulePrefix,
const std::optional<parser::InternalSubprogramPart> &);
template<typename T> bool Pre(const T &) { return true; }
template<typename T> void Post(const T &) {}
- bool Pre(const parser::PrefixSpec &);
void Post(const parser::SpecificationPart &);
bool Pre(const parser::MainProgram &);
void Post(const parser::EndProgramStmt &);
state_ = {};
}
-DeclTypeSpecVisitor::State DeclTypeSpecVisitor::SetDeclTypeSpecState(State x) {
- auto result{state_};
- state_ = x;
- return result;
-}
-
void DeclTypeSpecVisitor::SetDeclTypeSpecCategory(
DeclTypeSpec::Category category) {
CHECK(state_.expectDeclTypeSpec);
bool SubprogramVisitor::Pre(const parser::Suffix &suffix) {
if (suffix.resultName) {
- funcResultName_ = &suffix.resultName.value();
+ funcInfo_.resultName = &suffix.resultName.value();
}
return true;
}
+bool SubprogramVisitor::Pre(const parser::PrefixSpec &x) {
+ // Save this to process after UseStmt and ImplicitPart
+ funcInfo_.parsedType = std::get_if<parser::DeclarationTypeSpec>(&x.u);
+ funcInfo_.source = currStmtSource();
+ return funcInfo_.parsedType == nullptr;
+}
+
+void SubprogramVisitor::HandleFunctionPrefixType() {
+ if (funcInfo_.parsedType) {
+ messageHandler().set_currStmtSource(funcInfo_.source);
+ if (const auto *type{ProcessTypeSpec(*funcInfo_.parsedType)}) {
+ funcInfo_.resultSymbol->SetType(*type);
+ }
+ }
+ funcInfo_ = {};
+}
+
bool HasModulePrefix(const std::list<parser::PrefixSpec> &prefixes) {
for (const auto &prefix : prefixes) {
if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {
return BeginAttrs();
}
bool SubprogramVisitor::Pre(const parser::FunctionStmt &stmt) {
- if (!subpNamesOnly_) {
- BeginDeclTypeSpec();
- CHECK(!funcResultName_);
- }
return BeginAttrs();
}
Symbol &dummy{MakeSymbol(dummyName, EntityDetails(true))};
details.add_dummyArg(dummy);
}
- // add function result to function scope
- EntityDetails funcResultDetails;
- funcResultDetails.set_funcResult(true);
- if (auto *type{GetDeclTypeSpec()}) {
- funcResultDetails.set_type(*type);
- }
- EndDeclTypeSpec();
-
const parser::Name *funcResultName;
- if (funcResultName_ && funcResultName_->source != name.source) {
- funcResultName = funcResultName_;
+ if (funcInfo_.resultName && funcInfo_.resultName->source != name.source) {
+ funcResultName = funcInfo_.resultName;
} else {
EraseSymbol(name); // was added by PushSubprogramScope
funcResultName = &name;
}
- details.set_result(MakeSymbol(*funcResultName, funcResultDetails));
- funcResultName_ = nullptr;
+ // add function result to function scope
+ EntityDetails funcResultDetails;
+ funcResultDetails.set_funcResult(true);
+ funcInfo_.resultSymbol = &MakeSymbol(*funcResultName, funcResultDetails);
+ details.set_result(*funcInfo_.resultSymbol);
}
SubprogramDetails &SubprogramVisitor::PostSubprogramStmt(
}
bool DeclarationVisitor::Pre(const parser::StructureConstructor &x) {
- auto savedState{SetDeclTypeSpecState({})};
- BeginDeclTypeSpec();
auto &parsedType{std::get<parser::DerivedTypeSpec>(x.t)};
- Walk(parsedType);
- const DeclTypeSpec *type{GetDeclTypeSpec()};
- EndDeclTypeSpec();
- SetDeclTypeSpecState(savedState);
-
+ const DeclTypeSpec *type{ProcessTypeSpec(parsedType)};
if (type == nullptr) {
return false;
}
return nullptr; // error was reported in DeclareEntity
}
if (type.has_value()) {
- BeginDeclTypeSpec();
- DeclarationVisitor::Post(*type);
- declTypeSpec = GetDeclTypeSpec();
- EndDeclTypeSpec();
+ declTypeSpec = ProcessTypeSpec(*type);
}
if (declTypeSpec != nullptr) {
SetType(name, *declTypeSpec);
}
bool ConstructVisitor::Pre(const parser::AcSpec &x) {
- // AcSpec can occur within a TypeDeclarationStmt: save and restore state
- auto savedState{SetDeclTypeSpecState({})};
- BeginDeclTypeSpec();
- Walk(x.type);
- EndDeclTypeSpec();
- SetDeclTypeSpecState(savedState);
+ ProcessTypeSpec(x.type);
PushScope(Scope::Kind::ImpliedDos, nullptr);
Walk(x.values);
PopScope();
// ResolveNamesVisitor implementation
-bool ResolveNamesVisitor::Pre(const parser::PrefixSpec &x) {
- return true; // TODO
-}
-
bool ResolveNamesVisitor::Pre(const parser::FunctionReference &x) {
HandleCall(Symbol::Flag::Function, x.v);
return false;
void ResolveNamesVisitor::Post(const parser::SpecificationPart &) {
badStmtFuncFound_ = false;
CheckImports();
+ HandleFunctionPrefixType();
bool inModule{currScope().kind() == Scope::Kind::Module};
for (auto &pair : currScope()) {
auto &symbol{*pair.second};