-
Notifications
You must be signed in to change notification settings - Fork 12k
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
Conversation
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.
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesDon'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:
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
…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.
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.