[flang] Perform definability checks on LHS of assignment

If the pure context check succeeds, call `WhyNotModifiable` to verify
the LHS can be modified.

Detect assignment to whole assumed-size array.

Change `IsVariable` to return false for a parameter or a component or
array reference whose base it a parameter.

When analyzing an assignment statement, report an error if the LHS is
a constant expression. Otherwise it might get folded and when we detect
the problem later the error will be confusing.

Handle Substring on LHS of assignment. Change ExtractDataRef and IsVariable
to work on a Substring.

Fix IsImpliedShape and IsAssumedSize predicates in ArraySpec.

Fix C709 check in check-declarations.cpp.

Original-commit: flang-compiler/f18@f2d2657aab
Reviewed-on: https://github.com/flang-compiler/f18/pull/1050
This commit is contained in:
Tim Keith
2020-03-05 17:55:51 -08:00
parent c97e1c0a45
commit a0a1f519c0
9 changed files with 178 additions and 17 deletions

View File

@@ -66,10 +66,23 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
const SomeExpr &rhs{assignment->rhs};
auto lhsLoc{std::get<parser::Variable>(stmt.t).GetSource()};
auto rhsLoc{std::get<parser::Expr>(stmt.t).source};
auto shape{evaluate::GetShape(foldingContext(), lhs)};
if (shape && !shape->empty() && !shape->back().has_value()) { // C1014
Say(lhsLoc,
"Left-hand side of assignment may not be a whole assumed-size array"_err_en_US);
}
if (CheckForPureContext(lhs, rhs, rhsLoc, false)) {
const Scope &scope{context_.FindScope(lhsLoc)};
if (auto whyNot{WhyNotModifiable(lhsLoc, lhs, scope)}) {
if (auto *msg{Say(lhsLoc,
"Left-hand side of assignment is not modifiable"_err_en_US)}) {
msg->Attach(*whyNot);
}
}
}
if (whereDepth_ > 0) {
CheckShape(lhsLoc, &lhs);
}
CheckForPureContext(lhs, rhs, rhsLoc, false);
}
}
@@ -169,7 +182,8 @@ bool AssignmentContext::CheckForPureContext(const SomeExpr &lhs,
// ASSOCIATE(a=>x) -- check x, not a, for "a=..."
base = dataRef ? &dataRef->GetFirstSymbol() : nullptr;
}
if (!CheckDefinabilityInPureScope(messages, *base, scope, *pure)) {
if (base &&
!CheckDefinabilityInPureScope(messages, *base, scope, *pure)) {
return false;
}
}