[flang] Handle structure constructors with forward references to PDTs
We were not correctly handling structure constructors that had forward references to parameterized derived types. I harvested the code that checks for forward references that was used during analysis of function call expressions and called it from there and also called it during the analysis of structure constructors. I also added a test that will produce an internal error without this change. Differential Revision: https://reviews.llvm.org/D101330
This commit is contained in:
parent
9c552d27ee
commit
8b550af7a9
|
@ -382,6 +382,7 @@ private:
|
|||
template <typename T> T Fold(T &&expr) {
|
||||
return evaluate::Fold(foldingContext_, std::move(expr));
|
||||
}
|
||||
bool CheckIsValidForwardReference(const semantics::DerivedTypeSpec &);
|
||||
|
||||
semantics::SemanticsContext &context_;
|
||||
FoldingContext &foldingContext_{context_.foldingContext()};
|
||||
|
|
|
@ -1463,7 +1463,16 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
|
|||
MaybeExpr ExpressionAnalyzer::Analyze(
|
||||
const parser::StructureConstructor &structure) {
|
||||
auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
|
||||
parser::CharBlock typeName{std::get<parser::Name>(parsedType.t).source};
|
||||
parser::Name structureType{std::get<parser::Name>(parsedType.t)};
|
||||
parser::CharBlock &typeName{structureType.source};
|
||||
if (semantics::Symbol * typeSymbol{structureType.symbol}) {
|
||||
if (typeSymbol->has<semantics::DerivedTypeDetails>()) {
|
||||
semantics::DerivedTypeSpec dtSpec{typeName, typeSymbol->GetUltimate()};
|
||||
if (!CheckIsValidForwardReference(dtSpec)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!parsedType.derivedTypeSpec) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -2182,6 +2191,17 @@ const Symbol *AssumedTypeDummy<parser::PointerObject>(
|
|||
return AssumedTypePointerOrAllocatableDummy(x);
|
||||
}
|
||||
|
||||
bool ExpressionAnalyzer::CheckIsValidForwardReference(
|
||||
const semantics::DerivedTypeSpec &dtSpec) {
|
||||
if (dtSpec.IsForwardReferenced()) {
|
||||
Say("Cannot construct value for derived type '%s' "
|
||||
"before it is defined"_err_en_US,
|
||||
dtSpec.name());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
|
||||
std::optional<parser::StructureConstructor> *structureConstructor) {
|
||||
const parser::Call &call{funcRef.v};
|
||||
|
@ -2209,11 +2229,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
|
|||
semantics::Scope &scope{context_.FindScope(name->source)};
|
||||
semantics::DerivedTypeSpec dtSpec{
|
||||
name->source, derivedType.GetUltimate()};
|
||||
if (dtSpec.IsForwardReferenced()) {
|
||||
Say(call.source,
|
||||
"Cannot construct value for derived type '%s' "
|
||||
"before it is defined"_err_en_US,
|
||||
name->source);
|
||||
if (!CheckIsValidForwardReference(dtSpec)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const semantics::DeclTypeSpec &type{
|
||||
|
|
|
@ -79,3 +79,14 @@ subroutine s8
|
|||
real :: c
|
||||
end type
|
||||
end subroutine
|
||||
|
||||
subroutine s9
|
||||
type con
|
||||
Type(t(3)), pointer :: y
|
||||
end type
|
||||
!ERROR: Cannot construct value for derived type 't' before it is defined
|
||||
Integer :: nn = Size(Transfer(t(3)(666),[0]))
|
||||
type :: t(n)
|
||||
integer, kind :: n = 3
|
||||
end type
|
||||
end subroutine s9
|
||||
|
|
Loading…
Reference in a new issue