Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang] Avoid crash in name resolution on erroneous type extension #109312

Merged
merged 1 commit into from
Sep 20, 2024

Conversation

klausler
Copy link
Contributor

Don't crash when a bad Fortran program tries to extend a derived type with previous legitimate forward references but no prior definition.

Fixes #109268.

Don't crash when a bad Fortran program tries to extend a derived
type with previous legitimate forward references but no prior
definition.

Fixes llvm#109268.
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 19, 2024

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

Don't crash when a bad Fortran program tries to extend a derived type with previous legitimate forward references but no prior definition.

Fixes #109268.


Full diff: https://github.com/llvm/llvm-project/pull/109312.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/resolve-names.cpp (+15-10)
  • (modified) flang/test/Semantics/bad-forward-type.f90 (+15)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 5414787d85f7f7..b105dbdce911aa 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1204,7 +1204,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
       const parser::Name &, const parser::Name *);
   Symbol *MakeTypeSymbol(const SourceName &, Details &&);
   Symbol *MakeTypeSymbol(const parser::Name &, Details &&);
-  bool OkToAddComponent(const parser::Name &, const Symbol * = nullptr);
+  bool OkToAddComponent(const parser::Name &, const Symbol *extends = nullptr);
   ParamValue GetParamValue(
       const parser::TypeParamValue &, common::TypeParamAttr attr);
   void CheckCommonBlockDerivedType(
@@ -5606,7 +5606,7 @@ void DeclarationVisitor::Post(const parser::DerivedTypeStmt &x) {
       comp.set(Symbol::Flag::ParentComp);
       DeclTypeSpec &type{currScope().MakeDerivedType(
           DeclTypeSpec::TypeDerived, std::move(*extendsType))};
-      type.derivedTypeSpec().set_scope(*extendsSymbol.scope());
+      type.derivedTypeSpec().set_scope(DEREF(extendsSymbol.scope()));
       comp.SetType(type);
       DerivedTypeDetails &details{symbol.get<DerivedTypeDetails>()};
       details.add_component(comp);
@@ -6797,15 +6797,20 @@ std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveDerivedType(
 
 std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveExtendsType(
     const parser::Name &typeName, const parser::Name *extendsName) {
-  if (!extendsName) {
-    return std::nullopt;
-  } else if (typeName.source == extendsName->source) {
-    Say(extendsName->source,
-        "Derived type '%s' cannot extend itself"_err_en_US);
-    return std::nullopt;
-  } else {
-    return ResolveDerivedType(*extendsName);
+  if (extendsName) {
+    if (typeName.source == extendsName->source) {
+      Say(extendsName->source,
+          "Derived type '%s' cannot extend itself"_err_en_US);
+    } else if (auto dtSpec{ResolveDerivedType(*extendsName)}) {
+      if (!dtSpec->IsForwardReferenced()) {
+        return dtSpec;
+      }
+      Say(typeName.source,
+          "Derived type '%s' cannot extend type '%s' that has not yet been defined"_err_en_US,
+          typeName.source, extendsName->source);
+    }
   }
+  return std::nullopt;
 }
 
 Symbol *DeclarationVisitor::NoteInterfaceName(const parser::Name &name) {
diff --git a/flang/test/Semantics/bad-forward-type.f90 b/flang/test/Semantics/bad-forward-type.f90
index 27c6045b0059fa..f379b274e1279b 100644
--- a/flang/test/Semantics/bad-forward-type.f90
+++ b/flang/test/Semantics/bad-forward-type.f90
@@ -97,3 +97,18 @@ subroutine s10
     type(undef), pointer :: y
   end type
 end subroutine s10
+
+subroutine s11
+  !ERROR: Derived type 'undef1' not found
+  type(undef1), pointer :: p
+  type t1
+    !ERROR: The derived type 'undef2' has not been defined
+    type(undef2), pointer :: p
+  end type
+  !ERROR: Derived type 'undef1' not found
+  type, extends(undef1) :: t2
+  end type
+  !ERROR: Derived type 't3' cannot extend type 'undef2' that has not yet been defined
+  type, extends(undef2) :: t3
+  end type
+end subroutine s11

@@ -1204,7 +1204,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
const parser::Name &, const parser::Name *);
Symbol *MakeTypeSymbol(const SourceName &, Details &&);
Symbol *MakeTypeSymbol(const parser::Name &, Details &&);
bool OkToAddComponent(const parser::Name &, const Symbol * = nullptr);
bool OkToAddComponent(const parser::Name &, const Symbol *extends = nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this update intentional? I don't see it being used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I added an argument name for documentation purposes.

@klausler klausler merged commit e8335ae into llvm:main Sep 20, 2024
11 checks passed
@klausler klausler deleted the bug109268 branch September 20, 2024 20:53
xgupta pushed a commit to xgupta/llvm-project that referenced this pull request Oct 4, 2024
…lvm#109312)

Don't crash when a bad Fortran program tries to extend a derived type
with previous legitimate forward references but no prior definition.

Fixes llvm#109268.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[flang] Flang crashes compiling a program with a derived type that extends an undefined derived type
3 participants