[flang-commits] [flang] 22ed61e - [flang] Emit errors on vector subscripts with duplicated elements when object must be definable
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Jul 17 12:24:30 PDT 2023
Author: Peter Klausler
Date: 2023-07-17T12:20:16-07:00
New Revision: 22ed61ed87ef7134825c01960d8b1a78c87a36c7
URL: https://github.com/llvm/llvm-project/commit/22ed61ed87ef7134825c01960d8b1a78c87a36c7
DIFF: https://github.com/llvm/llvm-project/commit/22ed61ed87ef7134825c01960d8b1a78c87a36c7.diff
LOG: [flang] Emit errors on vector subscripts with duplicated elements when object must be definable
When the left-hand side of an assignment, or any other context demanding
definability, comprises a designator with a vector subscript that is
known at compilation time to have one or more duplicated elements,
emit an error message.
Differential Revision: https://reviews.llvm.org/D155492
Added:
flang/test/Semantics/definable06.f90
Modified:
flang/lib/Semantics/check-call.cpp
flang/lib/Semantics/definable.cpp
flang/lib/Semantics/definable.h
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 260a1827c6b797..7999d3776aaf84 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -448,6 +448,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
}
// Definability
+ bool actualIsVariable{evaluate::IsVariable(actual)};
const char *reason{nullptr};
if (dummy.intent == common::Intent::Out) {
reason = "INTENT(OUT)";
@@ -457,7 +458,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
if (reason && scope) {
// Problems with polymorphism are caught in the callee's definition.
DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
- if (isElemental || dummyIsValue) { // 15.5.2.4(21)
+ if (isElemental) { // 15.5.2.4(21)
flags.set(DefinabilityFlag::VectorSubscriptIsOk);
}
if (actualIsPointer && dummyIsPointer) { // 19.6.8
@@ -475,7 +476,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
// technically legal but worth emitting a warning
// llvm-project issue #58973: constant actual argument passed in where dummy
// argument is marked volatile
- bool actualIsVariable{evaluate::IsVariable(actual)};
if (dummyIsVolatile && !actualIsVariable &&
context.ShouldWarn(common::UsageWarning::ExprPassedToVolatile)) {
messages.Say(
diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp
index abb5f35c28eaea..c3826e7f29d7e0 100644
--- a/flang/lib/Semantics/definable.cpp
+++ b/flang/lib/Semantics/definable.cpp
@@ -244,6 +244,47 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
return WhyNotDefinableLast(at, scope, flags, original);
}
+class DuplicatedSubscriptFinder
+ : public evaluate::AnyTraverse<DuplicatedSubscriptFinder, bool> {
+ using Base = evaluate::AnyTraverse<DuplicatedSubscriptFinder, bool>;
+
+public:
+ explicit DuplicatedSubscriptFinder(evaluate::FoldingContext &foldingContext)
+ : Base{*this}, foldingContext_{foldingContext} {}
+ using Base::operator();
+ bool operator()(const evaluate::ActualArgument &) {
+ return false; // don't descend into argument expressions
+ }
+ bool operator()(const evaluate::ArrayRef &aRef) {
+ bool anyVector{false};
+ for (const auto &ss : aRef.subscript()) {
+ if (ss.Rank() > 0) {
+ anyVector = true;
+ if (const auto *vecExpr{
+ std::get_if<evaluate::IndirectSubscriptIntegerExpr>(&ss.u)}) {
+ auto folded{evaluate::Fold(foldingContext_,
+ evaluate::Expr<evaluate::SubscriptInteger>{vecExpr->value()})};
+ if (const auto *con{
+ evaluate::UnwrapConstantValue<evaluate::SubscriptInteger>(
+ folded)}) {
+ std::set<std::int64_t> values;
+ for (const auto &j : con->values()) {
+ if (auto pair{values.emplace(j.ToInt64())}; !pair.second) {
+ return true; // duplicate
+ }
+ }
+ }
+ return false;
+ }
+ }
+ }
+ return anyVector ? false : (*this)(aRef.base());
+ }
+
+private:
+ evaluate::FoldingContext &foldingContext_;
+};
+
std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags,
const evaluate::Expr<evaluate::SomeType> &expr) {
@@ -288,6 +329,11 @@ std::optional<parser::Message> WhyNotDefinable(parser::CharBlock at,
}
}
}
+ if (!flags.test(DefinabilityFlag::DuplicatesAreOk) &&
+ DuplicatedSubscriptFinder{scope.context().foldingContext()}(expr)) {
+ return parser::Message{at,
+ "Variable has a vector subscript with a duplicated element"_because_en_US};
+ }
} else {
return parser::Message{at,
"Variable '%s' has a vector subscript"_because_en_US,
diff --git a/flang/lib/Semantics/definable.h b/flang/lib/Semantics/definable.h
index 374ea38451ac39..df869db252a9a4 100644
--- a/flang/lib/Semantics/definable.h
+++ b/flang/lib/Semantics/definable.h
@@ -27,6 +27,7 @@ class Scope;
ENUM_CLASS(DefinabilityFlag,
VectorSubscriptIsOk, // a vector subscript may appear (i.e., assignment)
+ DuplicatesAreOk, // vector subscript may have duplicates
PointerDefinition, // a pointer is being defined, not its target
AcceptAllocatable, // treat allocatable as if it were a pointer
PolymorphicOkInPure) // don't check for polymorphic type in pure subprogram
diff --git a/flang/test/Semantics/definable06.f90 b/flang/test/Semantics/definable06.f90
new file mode 100644
index 00000000000000..014a05313519bb
--- /dev/null
+++ b/flang/test/Semantics/definable06.f90
@@ -0,0 +1,20 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+module m
+ contains
+ elemental subroutine inout(x)
+ integer, intent(inout) :: x
+ end
+ subroutine test
+ integer :: x(2)
+ !ERROR: Left-hand side of assignment is not definable
+ !BECAUSE: Variable has a vector subscript with a duplicated element
+ x([1,1]) = 0
+ !ERROR: Actual argument associated with INTENT(IN OUT) dummy argument 'x=' is not definable
+ !BECAUSE: Variable has a vector subscript with a duplicated element
+ call inout(x([(mod(j-1,2)+1,j=1,10)]))
+ !ERROR: Input variable 'x' is not definable
+ !BECAUSE: Variable has a vector subscript with a duplicated element
+ read (*,*) x([2,2])
+ end
+end
+
More information about the flang-commits
mailing list