std::optional<int> VectorSize() const;
std::optional<parser::CharBlock> keyword;
- bool isAssumedRank{false}; // TODO: make into a function of the value
bool isAlternateReturn{false}; // when true, "value" is a label number
// TODO: Mark legacy %VAL and %REF arguments
for (std::size_t j{0}; j < dummies; ++j) {
const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
if (const ActualArgument * arg{actualForDummy[j]}) {
- if (arg->isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
- messages.Say(
- "assumed-rank array cannot be used for '%s=' argument"_err_en_US,
+ if (IsAssumedRank(*arg->value) && d.rank != Rank::anyOrAssumedRank) {
+ messages.Say("assumed-rank array cannot be forwarded to "
+ "'%s=' argument"_err_en_US,
d.keyword);
return std::nullopt;
}
return std::visit([](const auto &x) { return IsConstant(x); }, expr.u);
}
+// Predicate: true when an expression is assumed-rank
+template<typename A> bool IsAssumedRank(const A &) { return false; }
+template<typename A> bool IsAssumedRank(const Designator<A> &designator) {
+ if (const auto *symbolPtr{
+ std::get_if<const semantics::Symbol *>(&designator.u)}) {
+ if (const auto *details{
+ (*symbolPtr)
+ ->template detailsIf<semantics::ObjectEntityDetails>()}) {
+ return details->IsAssumedRank();
+ }
+ }
+ return false;
+}
+template<typename A> bool IsAssumedRank(const Expr<A> &expr) {
+ return std::visit([](const auto &x) { return IsAssumedRank(x); }, expr.u);
+}
+
// When an expression is a constant integer, extract its value.
template<typename A> std::optional<std::int64_t> ToInt64(const A &) {
return std::nullopt;
symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
// C928 & C1002
if (Triplet * last{std::get_if<Triplet>(&ref.subscript.back().u)}) {
- if (!last->upper().has_value() && details->isAssumedSize()) {
+ if (!last->upper().has_value() && details->IsAssumedSize()) {
Say("assumed-size array '%s' must have explicit final subscript upper bound value"_err_en_US,
symbol.name().ToString().data());
}
void set_shape(const ArraySpec &shape);
bool isDummy() const { return isDummy_; }
bool isArray() const { return !shape_.empty(); }
- bool isAssumedSize() const {
+ bool IsAssumedSize() const {
return isDummy() && isArray() && shape_.back().ubound().isAssumed() &&
!shape_.back().lbound().isAssumed();
}
+ bool IsAssumedRank() const {
+ return isDummy() && isArray() && shape_.back().ubound().isAssumed() &&
+ shape_.back().lbound().isAssumed();
+ }
private:
bool isDummy_;