forked from OSchip/llvm-project
[flang] Fix false error message for "ptr => func()" array conformance
Pointers must have deferred shapes, so CheckConformance must be extended to allow for them. Differential Revision: https://reviews.llvm.org/D93320
This commit is contained in:
parent
09edd9df6e
commit
d6a74ec826
|
@ -145,8 +145,9 @@ public:
|
|||
|
||||
int Rank() const { return GetRank(shape_); }
|
||||
bool IsCompatibleWith(parser::ContextualMessages &, const TypeAndShape &that,
|
||||
const char *thisIs = "POINTER", const char *thatIs = "TARGET",
|
||||
bool isElemental = false) const;
|
||||
const char *thisIs = "pointer", const char *thatIs = "target",
|
||||
bool isElemental = false, bool thisIsDeferredShape = false,
|
||||
bool thatIsDeferredShape = false) const;
|
||||
std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
|
||||
FoldingContext * = nullptr) const;
|
||||
|
||||
|
|
|
@ -211,7 +211,8 @@ std::optional<ConstantSubscripts> GetConstantExtents(
|
|||
bool CheckConformance(parser::ContextualMessages &, const Shape &left,
|
||||
const Shape &right, const char *leftIs = "left operand",
|
||||
const char *rightIs = "right operand", bool leftScalarExpandable = true,
|
||||
bool rightScalarExpandable = true);
|
||||
bool rightScalarExpandable = true, bool leftIsDeferredShape = false,
|
||||
bool rightIsDeferredShape = false);
|
||||
|
||||
// Increments one-based subscripts in element order (first varies fastest)
|
||||
// and returns true when they remain in range; resets them all to one and
|
||||
|
|
|
@ -150,7 +150,8 @@ std::optional<TypeAndShape> TypeAndShape::Characterize(
|
|||
|
||||
bool TypeAndShape::IsCompatibleWith(parser::ContextualMessages &messages,
|
||||
const TypeAndShape &that, const char *thisIs, const char *thatIs,
|
||||
bool isElemental) const {
|
||||
bool isElemental, bool thisIsDeferredShape,
|
||||
bool thatIsDeferredShape) const {
|
||||
if (!type_.IsTkCompatibleWith(that.type_)) {
|
||||
const auto &len{that.LEN()};
|
||||
messages.Say(
|
||||
|
@ -161,7 +162,8 @@ bool TypeAndShape::IsCompatibleWith(parser::ContextualMessages &messages,
|
|||
}
|
||||
return isElemental ||
|
||||
CheckConformance(messages, shape_, that.shape_, thisIs, thatIs, false,
|
||||
false /* no scalar expansion */);
|
||||
false /* no scalar expansion */, thisIsDeferredShape,
|
||||
thatIsDeferredShape);
|
||||
}
|
||||
|
||||
std::optional<Expr<SubscriptInteger>> TypeAndShape::MeasureSizeInBytes(
|
||||
|
|
|
@ -683,7 +683,8 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
|
|||
// that they conform
|
||||
bool CheckConformance(parser::ContextualMessages &messages, const Shape &left,
|
||||
const Shape &right, const char *leftIs, const char *rightIs,
|
||||
bool leftScalarExpandable, bool rightScalarExpandable) {
|
||||
bool leftScalarExpandable, bool rightScalarExpandable,
|
||||
bool leftIsDeferredShape, bool rightIsDeferredShape) {
|
||||
int n{GetRank(left)};
|
||||
if (n == 0 && leftScalarExpandable) {
|
||||
return true;
|
||||
|
@ -698,15 +699,18 @@ bool CheckConformance(parser::ContextualMessages &messages, const Shape &left,
|
|||
return false;
|
||||
}
|
||||
for (int j{0}; j < n; ++j) {
|
||||
auto leftDim{ToInt64(left[j])};
|
||||
auto rightDim{ToInt64(right[j])};
|
||||
if (!leftDim || !rightDim) {
|
||||
return false;
|
||||
}
|
||||
if (*leftDim != *rightDim) {
|
||||
messages.Say("Dimension %1$d of %2$s has extent %3$jd, "
|
||||
"but %4$s has extent %5$jd"_err_en_US,
|
||||
j + 1, leftIs, *leftDim, rightIs, *rightDim);
|
||||
if (auto leftDim{ToInt64(left[j])}) {
|
||||
if (auto rightDim{ToInt64(right[j])}) {
|
||||
if (*leftDim != *rightDim) {
|
||||
messages.Say("Dimension %1$d of %2$s has extent %3$jd, "
|
||||
"but %4$s has extent %5$jd"_err_en_US,
|
||||
j + 1, leftIs, *leftDim, rightIs, *rightDim);
|
||||
return false;
|
||||
}
|
||||
} else if (!rightIsDeferredShape) {
|
||||
return false;
|
||||
}
|
||||
} else if (!leftIsDeferredShape) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,7 +169,9 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) {
|
|||
} else if (lhsType_) {
|
||||
const auto *frTypeAndShape{funcResult->GetTypeAndShape()};
|
||||
CHECK(frTypeAndShape);
|
||||
if (!lhsType_->IsCompatibleWith(context_.messages(), *frTypeAndShape)) {
|
||||
if (!lhsType_->IsCompatibleWith(context_.messages(), *frTypeAndShape,
|
||||
"pointer", "function result", false /*elemental*/,
|
||||
true /*left: deferred shape*/, true /*right: deferred shape*/)) {
|
||||
msg = "%s is associated with the result of a reference to function '%s'"
|
||||
" whose pointer result has an incompatible type or shape"_err_en_US;
|
||||
}
|
||||
|
|
|
@ -61,10 +61,10 @@ subroutine test
|
|||
dt0x = dt0(ip0=null())
|
||||
dt0x = dt0(ip0=null(ip0))
|
||||
dt0x = dt0(ip0=null(mold=ip0))
|
||||
!ERROR: TARGET type 'REAL(4)' is not compatible with POINTER type 'INTEGER(4)'
|
||||
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
|
||||
!ERROR: pointer 'ip0' is associated with the result of a reference to function 'null' whose pointer result has an incompatible type or shape
|
||||
dt0x = dt0(ip0=null(mold=rp0))
|
||||
!ERROR: TARGET type 'REAL(4)' is not compatible with POINTER type 'INTEGER(4)'
|
||||
!ERROR: function result type 'REAL(4)' is not compatible with pointer type 'INTEGER(4)'
|
||||
!ERROR: pointer 'ip1' is associated with the result of a reference to function 'null' whose pointer result has an incompatible type or shape
|
||||
dt1x = dt1(ip1=null(mold=rp1))
|
||||
dt2x = dt2(pps0=null())
|
||||
|
|
Loading…
Reference in New Issue