[flang] Check for undefined derived types

It's possible to specify refer to an undefined derived type as the type of a
component of another derived type and then never define the type of the
component.  We were not detecting this situation.  To fix this, I
changed the value of isForwardReferenced_ in the symbol's
DerivedTypeDetails and checked for it when performing other derived type
checks.

I also had to record the fact that error messages were previously
emitted for the same problem in some cases so that I could avoid
duplicate messages.

I also added a test.

Differential Revision: https://reviews.llvm.org/D103714
This commit is contained in:
Peter Steinfeld
2021-06-04 13:24:19 -07:00
parent f2622a150a
commit 2b795ec682
5 changed files with 15 additions and 2 deletions

View File

@@ -259,7 +259,7 @@ public:
void add_paramDecl(const Symbol &symbol) { paramDecls_.push_back(symbol); }
void add_component(const Symbol &);
void set_sequence(bool x = true) { sequence_ = x; }
void set_isForwardReferenced() { isForwardReferenced_ = true; }
void set_isForwardReferenced(bool value) { isForwardReferenced_ = value; }
const std::list<SourceName> &componentNames() const {
return componentNames_;
}

View File

@@ -845,6 +845,10 @@ void CheckHelper::CheckSubprogram(
void CheckHelper::CheckDerivedType(
const Symbol &derivedType, const DerivedTypeDetails &details) {
if (details.isForwardReferenced() && !context_.HasError(derivedType)) {
messages_.Say("The derived type '%s' has not been defined"_err_en_US,
derivedType.name());
}
const Scope *scope{derivedType.scope()};
if (!scope) {
CHECK(details.isForwardReferenced());

View File

@@ -3957,6 +3957,7 @@ bool DeclarationVisitor::Pre(const parser::DerivedTypeDef &x) {
CHECK(scope.symbol());
CHECK(scope.symbol()->scope() == &scope);
auto &details{scope.symbol()->get<DerivedTypeDetails>()};
details.set_isForwardReferenced(false);
std::set<SourceName> paramNames;
for (auto &paramName : std::get<std::list<parser::Name>>(stmt.statement.t)) {
details.add_paramName(paramName.source);
@@ -5027,7 +5028,7 @@ std::optional<DerivedTypeSpec> DeclarationVisitor::ResolveDerivedType(
Resolve(name, *symbol);
};
DerivedTypeDetails details;
details.set_isForwardReferenced();
details.set_isForwardReferenced(true);
symbol->set_details(std::move(details));
} else { // C732
Say(name, "Derived type '%s' not found"_err_en_US);

View File

@@ -244,6 +244,7 @@ void DerivedTypeSpec::Instantiate(Scope &containingScope) {
foldingContext.messages().Say(typeSymbol_.name(),
"The derived type '%s' was forward-referenced but not defined"_err_en_US,
typeSymbol_.name());
context.SetError(typeSymbol_);
return;
}
EvaluateParameters(context);

View File

@@ -90,3 +90,10 @@ subroutine s9
integer, kind :: n = 3
end type
end subroutine s9
subroutine s10
type t
!ERROR: The derived type 'undef' has not been defined
type(undef), pointer :: y
end type
end subroutine s10