SemanticsContext &context() const { return *context_; }
void set_context(SemanticsContext &);
evaluate::FoldingContext &GetFoldingContext() const {
- return context_->foldingContext();
+ return DEREF(context_).foldingContext();
}
// Make a placeholder symbol for a Name that otherwise wouldn't have one.
const parser::Name &, const parser::InitialDataTarget &);
void PointerInitialization(
const parser::Name &, const parser::ProcPointerInit &);
- void CheckBindings(
- const Scope &, const parser::TypeBoundProcedureStmt::WithoutInterface &);
+ void CheckBindings(const parser::TypeBoundProcedureStmt::WithoutInterface &);
protected:
bool BeginDecl();
void AddSubpNames(const ProgramTree &);
bool BeginScope(const ProgramTree &);
void FinishSpecificationParts(const ProgramTree &);
- void FinishDerivedType(Scope &);
+ void FinishDerivedTypeDefinition(Scope &);
+ void FinishDerivedTypeInstantiation(Scope &);
void SetPassArg(const Symbol &, const Symbol *, WithPassArg &);
void ResolveExecutionParts(const ProgramTree &);
};
SetPassNameOn(*s);
}
}
- if (currScope().IsParameterizedDerivedType()) {
- CheckBindings(currScope(), x);
- }
}
-void DeclarationVisitor::CheckBindings(const Scope &typeScope,
+void DeclarationVisitor::CheckBindings(
const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) {
+ CHECK(currScope().kind() == Scope::Kind::DerivedType);
for (auto &declaration : tbps.declarations) {
auto &bindingName{std::get<parser::Name>(declaration.t)};
- if (Symbol * binding{FindInScope(typeScope, bindingName)}) {
+ if (Symbol * binding{FindInScope(currScope(), bindingName)}) {
if (auto *details{binding->detailsIf<ProcBindingDetails>()}) {
const Symbol &procedure{details->symbol().GetUltimate()};
if (!CanBeTypeBoundProc(procedure)) {
" a COMMON statement"_err_en_US);
} else { // C1108
Say(name,
- "SAVE statement in BLOCK construct may not contain a"
- " common block name '%s'"_err_en_US);
+ "SAVE statement in BLOCK construct may not contain a"
+ " common block name '%s'"_err_en_US);
}
} else {
for (Symbol *object : symbol->get<CommonBlockDetails>().objects()) {
if (name.symbol == nullptr) {
return;
}
- if (std::holds_alternative<parser::InitialDataTarget>(init.u) &&
- !currScope().IsParameterizedDerivedType()) {
+ if (std::holds_alternative<parser::InitialDataTarget>(init.u)) {
// Defer analysis to the end of the specification parts so that forward
// references work better.
return;
}
// The processing of initializers of pointers is deferred until all of
-// the pertinent specification parts have been visited. This deferral
-// enables the use of forward references in those initializers.
+// the pertinent specification parts have been visited. This deferred
+// processing enables the use of forward references in those initializers.
class DeferredPointerInitializationVisitor {
public:
explicit DeferredPointerInitializationVisitor(ResolveNamesVisitor &resolver)
void Post(const parser::DerivedTypeStmt &x) {
auto &name{std::get<parser::Name>(x.t)};
- if (const Symbol * symbol{name.symbol}) {
- if (const Scope * scope{symbol->scope()}) {
- if (scope->kind() == Scope::Kind::DerivedType &&
- !scope->IsParameterizedDerivedType()) {
- derivedTypeScope_ = scope;
+ if (Symbol * symbol{name.symbol}) {
+ if (Scope * scope{symbol->scope()}) {
+ if (scope->kind() == Scope::Kind::DerivedType) {
+ resolver_.PushScope(*scope);
+ pushedScope_ = true;
}
}
}
}
- void Post(const parser::EndTypeStmt &) { derivedTypeScope_ = nullptr; }
+ void Post(const parser::EndTypeStmt &) {
+ if (pushedScope_) {
+ resolver_.PopScope();
+ pushedScope_ = false;
+ }
+ }
bool Pre(const parser::EntityDecl &decl) {
Init(std::get<parser::Name>(decl.t),
return false;
}
void Post(const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) {
- if (derivedTypeScope_ != nullptr) {
- resolver_.CheckBindings(*derivedTypeScope_, tbps);
+ if (pushedScope_) {
+ resolver_.CheckBindings(tbps);
}
}
}
ResolveNamesVisitor &resolver_;
- const Scope *derivedTypeScope_{nullptr};
+ bool pushedScope_{false};
};
// Perform checks that need to happen after all of the specification parts
}
for (Scope &childScope : currScope().children()) {
if (childScope.IsDerivedType() && childScope.symbol()) {
- FinishDerivedType(childScope);
+ FinishDerivedTypeDefinition(childScope);
+ }
+ }
+ for (Scope &childScope : currScope().children()) {
+ if (childScope.IsDerivedType() && !childScope.symbol()) {
+ FinishDerivedTypeInstantiation(childScope);
}
}
for (const auto &child : node.children()) {
}
// Perform checks on procedure bindings of this type
-void ResolveNamesVisitor::FinishDerivedType(Scope &scope) {
- CHECK(scope.IsDerivedType());
+void ResolveNamesVisitor::FinishDerivedTypeDefinition(Scope &scope) {
+ CHECK(scope.IsDerivedType() && scope.symbol());
for (auto &pair : scope) {
Symbol &comp{*pair.second};
std::visit(
}
}
+// Fold object pointer initializer designators with the actual
+// type parameter values of a particular instantiation.
+void ResolveNamesVisitor::FinishDerivedTypeInstantiation(Scope &scope) {
+ CHECK(scope.IsDerivedType() && !scope.symbol());
+ if (const DerivedTypeSpec * spec{scope.derivedTypeSpec()}) {
+ const Symbol &origTypeSymbol{spec->typeSymbol()};
+ if (const Scope * origTypeScope{origTypeSymbol.scope()}) {
+ CHECK(origTypeScope->IsDerivedType() &&
+ origTypeScope->symbol() == &origTypeSymbol);
+ auto &foldingContext{GetFoldingContext()};
+ auto restorer{foldingContext.WithPDTInstance(*spec)};
+ for (auto &pair : scope) {
+ Symbol &comp{*pair.second};
+ const Symbol &origComp{DEREF(FindInScope(*origTypeScope, comp.name()))};
+ std::visit(
+ common::visitors{
+ [&](ObjectEntityDetails &x) {
+ if (IsPointer(comp)) {
+ auto origDetails{origComp.get<ObjectEntityDetails>()};
+ if (const MaybeExpr & init{origDetails.init()}) {
+ SomeExpr newInit{*init};
+ MaybeExpr folded{
+ evaluate::Fold(foldingContext, std::move(newInit))};
+ x.set_init(std::move(folded));
+ }
+ }
+ },
+ [&](ProcEntityDetails &x) {
+ auto origDetails{origComp.get<ProcEntityDetails>()};
+ if (auto pi{origDetails.passIndex()}) {
+ x.set_passIndex(*pi);
+ }
+ },
+ [&](ProcBindingDetails &x) {
+ auto origDetails{origComp.get<ProcBindingDetails>()};
+ if (auto pi{origDetails.passIndex()}) {
+ x.set_passIndex(*pi);
+ }
+ },
+ [](auto &) {},
+ },
+ comp.details());
+ }
+ }
+ }
+}
+
// Check C760, constraints on the passed-object dummy argument
// If they all pass, set the passIndex in details.
void ResolveNamesVisitor::SetPassArg(