[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) {
|
template <typename T> T Fold(T &&expr) {
|
||||||
return evaluate::Fold(foldingContext_, std::move(expr));
|
return evaluate::Fold(foldingContext_, std::move(expr));
|
||||||
}
|
}
|
||||||
|
bool CheckIsValidForwardReference(const semantics::DerivedTypeSpec &);
|
||||||
|
|
||||||
semantics::SemanticsContext &context_;
|
semantics::SemanticsContext &context_;
|
||||||
FoldingContext &foldingContext_{context_.foldingContext()};
|
FoldingContext &foldingContext_{context_.foldingContext()};
|
||||||
|
|
|
@ -1463,7 +1463,16 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
|
||||||
MaybeExpr ExpressionAnalyzer::Analyze(
|
MaybeExpr ExpressionAnalyzer::Analyze(
|
||||||
const parser::StructureConstructor &structure) {
|
const parser::StructureConstructor &structure) {
|
||||||
auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
|
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) {
|
if (!parsedType.derivedTypeSpec) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -2182,6 +2191,17 @@ const Symbol *AssumedTypeDummy<parser::PointerObject>(
|
||||||
return AssumedTypePointerOrAllocatableDummy(x);
|
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,
|
MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
|
||||||
std::optional<parser::StructureConstructor> *structureConstructor) {
|
std::optional<parser::StructureConstructor> *structureConstructor) {
|
||||||
const parser::Call &call{funcRef.v};
|
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::Scope &scope{context_.FindScope(name->source)};
|
||||||
semantics::DerivedTypeSpec dtSpec{
|
semantics::DerivedTypeSpec dtSpec{
|
||||||
name->source, derivedType.GetUltimate()};
|
name->source, derivedType.GetUltimate()};
|
||||||
if (dtSpec.IsForwardReferenced()) {
|
if (!CheckIsValidForwardReference(dtSpec)) {
|
||||||
Say(call.source,
|
|
||||||
"Cannot construct value for derived type '%s' "
|
|
||||||
"before it is defined"_err_en_US,
|
|
||||||
name->source);
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const semantics::DeclTypeSpec &type{
|
const semantics::DeclTypeSpec &type{
|
||||||
|
|
|
@ -79,3 +79,14 @@ subroutine s8
|
||||||
real :: c
|
real :: c
|
||||||
end type
|
end type
|
||||||
end subroutine
|
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