[flang] Add a check for DO step expressions being zero

This is prohibited by Section 11.1.7.4.1, paragraph 1.

Note also that we allow for REAL step expressions.  But the check I
added only works for INTEGER step expressions.

I added a function to tools.cc to test to see if an expression is zero,
and I added calls to check-do.cc for regular and CONCURRENT DO
statements to this function.  I made the regular DO a warning and the DO
CONCURRENT message an error.  I added tests for the DO CONCURRENT case,
including a test that uses an integer constant.

Original-commit: flang-compiler/f18@8c4fadfe00
Reviewed-on: https://github.com/flang-compiler/f18/pull/834
This commit is contained in:
Pete Steinfeld 2019-11-20 13:33:04 -08:00
parent b0823c7b69
commit 7139a04e31
4 changed files with 41 additions and 3 deletions

View File

@ -464,7 +464,6 @@ private:
if (isReal && !warn) {
// No messages for the default case
} else if (isReal && warn) {
// TODO: Mark the following message as a warning when we have warnings
context_.Say(sourceLocation, "DO controls should be INTEGER"_en_US);
} else {
SayBadDoControl(sourceLocation);
@ -510,7 +509,11 @@ private:
CheckDoExpression(bounds.lower);
CheckDoExpression(bounds.upper);
if (bounds.step) {
CheckDoExpression(bounds.step.value());
CheckDoExpression(*bounds.step);
if (IsZero(*bounds.step)) {
context_.Say(bounds.step->thing.value().source,
"DO step expression should not be zero"_en_US);
}
}
}
@ -670,6 +673,10 @@ private:
if (const auto &expr{
std::get<std::optional<parser::ScalarIntExpr>>(c.t)}) {
HasNoReferences(indexNames, *expr);
if (IsZero(*expr)) {
context_.Say(expr->thing.thing.value().source,
"DO CONCURRENT step expression should not be zero"_err_en_US);
}
}
}
}

View File

@ -272,6 +272,11 @@ template<typename T> std::optional<std::int64_t> GetIntValue(const T &x) {
}
}
template<typename T> bool IsZero(const T &expr) {
auto value{GetIntValue(expr)};
return value && *value == 0;
}
// Derived type component iterator that provides a C++ LegacyForwardIterator
// iterator over the Ordered, Direct, Ultimate or Potential components of a
// DerivedTypeSpec. These iterators can be used with STL algorithms

View File

@ -14,6 +14,9 @@
! C1121 -- any procedure referenced in a concurrent header must be pure
! Also, check that the step expressions are not zero. This is prohibited by
! Section 11.1.7.4.1, paragraph 1.
SUBROUTINE do_concurrent_c1121(i,n)
IMPLICIT NONE
INTEGER :: i, n, flag
@ -28,3 +31,25 @@ SUBROUTINE do_concurrent_c1121(i,n)
i = 35
END FUNCTION random
END SUBROUTINE do_concurrent_c1121
SUBROUTINE s1()
INTEGER, PARAMETER :: constInt = 0
! Warn on this one for backwards compatibility
DO 10 I = 1, 10, 0
10 CONTINUE
! Warn on this one for backwards compatibility
DO 20 I = 1, 10, 5 - 5
20 CONTINUE
! Error, no compatibility requirement for DO CONCURRENT
!ERROR: DO CONCURRENT step expression should not be zero
DO CONCURRENT (I = 1 : 10 : 0)
END DO
! Error, this time with an integer constant
!ERROR: DO CONCURRENT step expression should not be zero
DO CONCURRENT (I = 1 : 10 : constInt)
END DO
end subroutine s1

View File

@ -46,7 +46,7 @@ subroutine s1()
! References in this DO CONCURRENT are OK since there's no DEFAULT(NONE)
! locality-spec
associate (avar => ivar)
do concurrent (i = 1:2:0) shared(jvar)
do concurrent (i = 1:2) shared(jvar)
ivar = 3
ivar = ivar + i
block
@ -61,6 +61,7 @@ subroutine s1()
end associate
associate (avar => ivar)
!ERROR: DO CONCURRENT step expression should not be zero
do concurrent (i = 1:2:0) default(none) shared(jvar) local(kvar)
!ERROR: Variable 'ivar' from an enclosing scope referenced in DO CONCURRENT with DEFAULT(NONE) must appear in a locality-spec
ivar = &