@@ -296,7 +296,8 @@ class InstantiateHelper {
296296 template <typename A> A Fold (A &&expr) {
297297 return evaluate::Fold (foldingContext (), std::move (expr));
298298 }
299- void InstantiateComponent (const Symbol &);
299+ Symbol *BeginComponentInstantiation (const Symbol &);
300+ void CompleteComponentInstantiation (Symbol &);
300301 const DeclTypeSpec *InstantiateType (const Symbol &);
301302 const DeclTypeSpec &InstantiateIntrinsicType (
302303 SourceName, const DeclTypeSpec &);
@@ -319,12 +320,16 @@ static int PlumbPDTInstantiationDepth(const Scope *scope) {
319320static void InstantiateNonPDTScope (Scope &typeScope, Scope &containingScope) {
320321 auto &context{containingScope.context ()};
321322 auto &foldingContext{context.foldingContext ()};
323+ std::set<DerivedTypeSpec *> deferred;
322324 for (auto &pair : typeScope) {
323325 Symbol &symbol{*pair.second };
324326 if (DeclTypeSpec * type{symbol.GetType ()}) {
325327 if (DerivedTypeSpec * derived{type->AsDerived ()}) {
326- if (!(derived->IsForwardReferenced () &&
327- IsAllocatableOrPointer (symbol))) {
328+ if (IsAllocatableOrPointer (symbol)) {
329+ if (!derived->IsForwardReferenced ()) {
330+ deferred.insert (derived);
331+ }
332+ } else {
328333 derived->Instantiate (containingScope);
329334 }
330335 }
@@ -340,6 +345,9 @@ static void InstantiateNonPDTScope(Scope &typeScope, Scope &containingScope) {
340345 }
341346 }
342347 ComputeOffsets (context, typeScope);
348+ for (DerivedTypeSpec *derived : deferred) {
349+ derived->Instantiate (containingScope);
350+ }
343351}
344352
345353void DerivedTypeSpec::Instantiate (Scope &containingScope) {
@@ -441,10 +449,16 @@ void InstantiateHelper::InstantiateComponents(const Scope &fromScope) {
441449 // Instantiate symbols in declaration order; this ensures that
442450 // parent components and type parameters of ancestor types exist
443451 // by the time that they're needed.
452+ std::vector<Symbol *> newSymbols;
444453 for (SymbolRef ref : fromScope.GetSymbols ()) {
445- InstantiateComponent (*ref);
454+ if (Symbol * newSymbol{BeginComponentInstantiation (*ref)}) {
455+ newSymbols.emplace_back (newSymbol);
456+ }
446457 }
447458 ComputeOffsets (context (), scope_);
459+ for (Symbol *symbol : newSymbols) {
460+ CompleteComponentInstantiation (*symbol);
461+ }
448462}
449463
450464// Walks a parsed expression to prepare it for (re)analysis;
@@ -472,20 +486,23 @@ class ResetHelper {
472486 Scope &scope_;
473487};
474488
475- void InstantiateHelper::InstantiateComponent (const Symbol &oldSymbol) {
489+ Symbol *InstantiateHelper::BeginComponentInstantiation (
490+ const Symbol &oldSymbol) {
476491 auto pair{scope_.try_emplace (
477492 oldSymbol.name (), oldSymbol.attrs (), common::Clone (oldSymbol.details ()))};
478493 Symbol &newSymbol{*pair.first ->second };
479494 if (!pair.second ) {
480495 // Symbol was already present in the scope, which can only happen
481496 // in the case of type parameters.
482497 CHECK (oldSymbol.has <TypeParamDetails>());
483- return ;
498+ return nullptr ;
484499 }
485500 newSymbol.flags () = oldSymbol.flags ();
486501 if (auto *details{newSymbol.detailsIf <ObjectEntityDetails>()}) {
487- if (const DeclTypeSpec * newType{InstantiateType (newSymbol)}) {
488- details->ReplaceType (*newType);
502+ if (!IsAllocatableOrPointer (newSymbol)) {
503+ if (const DeclTypeSpec *newType{InstantiateType (newSymbol)}) {
504+ details->ReplaceType (*newType);
505+ }
489506 }
490507 for (ShapeSpec &dim : details->shape ()) {
491508 if (dim.lbound ().isExplicit ()) {
@@ -533,6 +550,17 @@ void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
533550 }
534551 }
535552 }
553+ return &newSymbol;
554+ }
555+
556+ void InstantiateHelper::CompleteComponentInstantiation (Symbol &newSymbol) {
557+ if (auto *details{newSymbol.detailsIf <ObjectEntityDetails>()}) {
558+ if (IsAllocatableOrPointer (newSymbol)) {
559+ if (const DeclTypeSpec *newType{InstantiateType (newSymbol)}) {
560+ details->ReplaceType (*newType);
561+ }
562+ }
563+ }
536564}
537565
538566const DeclTypeSpec *InstantiateHelper::InstantiateType (const Symbol &symbol) {
0 commit comments