[flang-commits] [flang] 33cef35 - [flang] Assign sizes & offsets before instantiating some component types (#178927)

via flang-commits flang-commits at lists.llvm.org
Sat Jan 31 14:48:56 PST 2026


Author: Peter Klausler
Date: 2026-01-31T14:48:52-08:00
New Revision: 33cef35bfb8bb7077ba19296fd99ba5cc4c4b0cf

URL: https://github.com/llvm/llvm-project/commit/33cef35bfb8bb7077ba19296fd99ba5cc4c4b0cf
DIFF: https://github.com/llvm/llvm-project/commit/33cef35bfb8bb7077ba19296fd99ba5cc4c4b0cf.diff

LOG: [flang] Assign sizes & offsets before instantiating some component types (#178927)

Semantics is instantiating derived types too soon is some cases, leading
to incorrect sizes and component offsets in cases of valid forward
references to derived types -- these appear in the declarations of
allocatable and pointer components. The incorrect size led to a runtime
crash in the linked bug report after an insufficient allocation.

Since those components are indirect, their sizes in the derived type
instantiation can be known without having to recursive instantiate the
components' types. Then, after laying out the derived type
instantiation, the compiler can then ensure that the components' types
are instantiated.

Fixes https://github.com/llvm/llvm-project/issues/178786.

Added: 
    flang/test/Semantics/bug178786.f90

Modified: 
    flang/lib/Semantics/type.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp
index 038a402e54f96..bb8fddbffd945 100644
--- a/flang/lib/Semantics/type.cpp
+++ b/flang/lib/Semantics/type.cpp
@@ -296,7 +296,8 @@ class InstantiateHelper {
   template <typename A> A Fold(A &&expr) {
     return evaluate::Fold(foldingContext(), std::move(expr));
   }
-  void InstantiateComponent(const Symbol &);
+  Symbol *BeginComponentInstantiation(const Symbol &);
+  void CompleteComponentInstantiation(Symbol &);
   const DeclTypeSpec *InstantiateType(const Symbol &);
   const DeclTypeSpec &InstantiateIntrinsicType(
       SourceName, const DeclTypeSpec &);
@@ -319,12 +320,16 @@ static int PlumbPDTInstantiationDepth(const Scope *scope) {
 static void InstantiateNonPDTScope(Scope &typeScope, Scope &containingScope) {
   auto &context{containingScope.context()};
   auto &foldingContext{context.foldingContext()};
+  std::set<DerivedTypeSpec *> deferred;
   for (auto &pair : typeScope) {
     Symbol &symbol{*pair.second};
     if (DeclTypeSpec * type{symbol.GetType()}) {
       if (DerivedTypeSpec * derived{type->AsDerived()}) {
-        if (!(derived->IsForwardReferenced() &&
-                IsAllocatableOrPointer(symbol))) {
+        if (IsAllocatableOrPointer(symbol)) {
+          if (!derived->IsForwardReferenced()) {
+            deferred.insert(derived);
+          }
+        } else {
           derived->Instantiate(containingScope);
         }
       }
@@ -340,6 +345,9 @@ static void InstantiateNonPDTScope(Scope &typeScope, Scope &containingScope) {
     }
   }
   ComputeOffsets(context, typeScope);
+  for (DerivedTypeSpec *derived : deferred) {
+    derived->Instantiate(containingScope);
+  }
 }
 
 void DerivedTypeSpec::Instantiate(Scope &containingScope) {
@@ -441,10 +449,16 @@ void InstantiateHelper::InstantiateComponents(const Scope &fromScope) {
   // Instantiate symbols in declaration order; this ensures that
   // parent components and type parameters of ancestor types exist
   // by the time that they're needed.
+  std::vector<Symbol *> newSymbols;
   for (SymbolRef ref : fromScope.GetSymbols()) {
-    InstantiateComponent(*ref);
+    if (Symbol * newSymbol{BeginComponentInstantiation(*ref)}) {
+      newSymbols.emplace_back(newSymbol);
+    }
   }
   ComputeOffsets(context(), scope_);
+  for (Symbol *symbol : newSymbols) {
+    CompleteComponentInstantiation(*symbol);
+  }
 }
 
 // Walks a parsed expression to prepare it for (re)analysis;
@@ -472,7 +486,8 @@ class ResetHelper {
   Scope &scope_;
 };
 
-void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
+Symbol *InstantiateHelper::BeginComponentInstantiation(
+    const Symbol &oldSymbol) {
   auto pair{scope_.try_emplace(
       oldSymbol.name(), oldSymbol.attrs(), common::Clone(oldSymbol.details()))};
   Symbol &newSymbol{*pair.first->second};
@@ -480,12 +495,14 @@ void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
     // Symbol was already present in the scope, which can only happen
     // in the case of type parameters.
     CHECK(oldSymbol.has<TypeParamDetails>());
-    return;
+    return nullptr;
   }
   newSymbol.flags() = oldSymbol.flags();
   if (auto *details{newSymbol.detailsIf<ObjectEntityDetails>()}) {
-    if (const DeclTypeSpec * newType{InstantiateType(newSymbol)}) {
-      details->ReplaceType(*newType);
+    if (!IsAllocatableOrPointer(newSymbol)) {
+      if (const DeclTypeSpec *newType{InstantiateType(newSymbol)}) {
+        details->ReplaceType(*newType);
+      }
     }
     for (ShapeSpec &dim : details->shape()) {
       if (dim.lbound().isExplicit()) {
@@ -533,6 +550,17 @@ void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) {
       }
     }
   }
+  return &newSymbol;
+}
+
+void InstantiateHelper::CompleteComponentInstantiation(Symbol &newSymbol) {
+  if (auto *details{newSymbol.detailsIf<ObjectEntityDetails>()}) {
+    if (IsAllocatableOrPointer(newSymbol)) {
+      if (const DeclTypeSpec *newType{InstantiateType(newSymbol)}) {
+        details->ReplaceType(*newType);
+      }
+    }
+  }
 }
 
 const DeclTypeSpec *InstantiateHelper::InstantiateType(const Symbol &symbol) {

diff  --git a/flang/test/Semantics/bug178786.f90 b/flang/test/Semantics/bug178786.f90
new file mode 100644
index 0000000000000..930b886a29987
--- /dev/null
+++ b/flang/test/Semantics/bug178786.f90
@@ -0,0 +1,63 @@
+!RUN: %flang_fc1 -fdebug-dump-symbols %s 2>&1 | FileCheck %s
+!CHECK:    DerivedType scope: b size=4048 alignment=8 instantiation of b sourceRange=62 bytes
+!CHECK:    DerivedType scope: e size=4080 alignment=8 instantiation of e sourceRange=48 bytes
+!CHECK:      DerivedType scope: size=4048 alignment=8 instantiation of b(k=4_4) sourceRange=0 bytes
+!CHECK:        DerivedType scope: size=4080 alignment=8 instantiation of e(k=4_4) sourceRange=0 bytes
+!CHECK:          DerivedType scope: size=4048 alignment=8 instantiation of b(k=4_4) sourceRange=0 bytes
+!CHECK:      DerivedType scope: size=4080 alignment=8 instantiation of e(k=4_4) sourceRange=0 bytes
+!CHECK:        DerivedType scope: size=4048 alignment=8 instantiation of b(k=4_4) sourceRange=0 bytes
+!CHECK:      DerivedType scope: size=4048 alignment=8 instantiation of b(k=4_4) sourceRange=0 bytes
+!CHECK:        DerivedType scope: size=4080 alignment=8 instantiation of e(k=4_4) sourceRange=0 bytes
+!CHECK:          DerivedType scope: size=4048 alignment=8 instantiation of b(k=4_4) sourceRange=0 bytes
+
+module noPDTs
+  type :: b
+    integer::d1
+    type (e),allocatable::n
+    integer::dd1(1000)
+  end type
+  type,extends(b) :: e
+    integer::d2
+    character(:),allocatable::c
+  end type
+ contains
+  subroutine alloc(d)
+    class (b),allocatable :: d
+    allocate(e::d)
+  end subroutine alloc
+  subroutine s1
+    class (b),allocatable :: v
+    call alloc(v)
+    deallocate(v)
+  end
+end
+
+module PDTs
+  type :: b(k)
+    integer, kind :: k
+    integer(k)::d1
+    type(e(k)),allocatable::n
+    integer::dd1(1000)
+  end type
+  type,extends(b) :: e
+    integer::d2
+    character(:),allocatable::c
+  end type
+ contains
+  subroutine alloc(d)
+    class(b(kind(0))),allocatable :: d
+    allocate(e(kind(0))::d)
+  end subroutine alloc
+  subroutine s2
+    class(b(kind(0))),allocatable :: v
+    call alloc(v)
+    deallocate(v)
+  end
+end
+
+use noPDTS, only: s1
+use PDTS, only: s2
+call s1
+call s2
+print *, 'ok'
+end


        


More information about the flang-commits mailing list