Skip to content

Commit

Permalink
[flang] Check constant POS/LEN arguments IBITS even when not both con…
Browse files Browse the repository at this point in the history
…stant

Apply compile-time checks to the values supplied for the POS and LEN
arguments of the IBITS intrinsic function even when only one of them
is a known constant.

Differential Revision: https://reviews.llvm.org/D154376
  • Loading branch information
klausler committed Jul 3, 2023
1 parent 58d7484 commit 6c5ba7c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 20 deletions.
37 changes: 17 additions & 20 deletions flang/lib/Evaluate/fold-integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,34 +726,31 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
const auto *lenCon{Folder<Int4>(context).Folding(args[2])};
if (const auto *argCon{Folder<T>(context).Folding(args[0])};
argCon && argCon->empty()) {
} else if (posCon && lenCon &&
(posCon->size() == 1 || lenCon->size() == 1 ||
posCon->size() == lenCon->size())) {
auto posIter{posCon->values().begin()};
auto lenIter{lenCon->values().begin()};
for (; posIter != posCon->values().end() &&
lenIter != lenCon->values().end();
++posIter, ++lenIter) {
posIter = posIter == posCon->values().end() ? posCon->values().begin()
: posIter;
lenIter = lenIter == lenCon->values().end() ? lenCon->values().begin()
: lenIter;
auto posVal{static_cast<int>(posIter->ToInt64())};
auto lenVal{static_cast<int>(lenIter->ToInt64())};
} else {
std::size_t posCt{posCon ? posCon->size() : 0};
std::size_t lenCt{lenCon ? lenCon->size() : 0};
std::size_t n{std::max(posCt, lenCt)};
for (std::size_t j{0}; j < n; ++j) {
int posVal{j < posCt || posCt == 1
? static_cast<int>(posCon->values()[j % posCt].ToInt64())
: 0};
int lenVal{j < lenCt || lenCt == 1
? static_cast<int>(lenCon->values()[j % lenCt].ToInt64())
: 0};
if (posVal < 0) {
context.messages().Say(
"bit position for IBITS(POS=%jd,LEN=%jd) is negative"_err_en_US,
std::intmax_t{posVal}, std::intmax_t{lenVal});
"bit position for IBITS(POS=%jd) is negative"_err_en_US,
std::intmax_t{posVal});
break;
} else if (lenVal < 0) {
context.messages().Say(
"bit length for IBITS(POS=%jd,LEN=%jd) is negative"_err_en_US,
std::intmax_t{posVal}, std::intmax_t{lenVal});
"bit length for IBITS(LEN=%jd) is negative"_err_en_US,
std::intmax_t{lenVal});
break;
} else if (posVal + lenVal > T::Scalar::bits) {
context.messages().Say(
"IBITS(POS=%jd,LEN=%jd) must have POS+LEN no greater than %d"_err_en_US,
std::intmax_t{posVal}, std::intmax_t{lenVal}, T::Scalar::bits);
"IBITS() must have POS+LEN (>=%jd) no greater than %d"_err_en_US,
std::intmax_t{posVal + lenVal}, T::Scalar::bits);
break;
}
}
Expand Down
11 changes: 11 additions & 0 deletions flang/test/Evaluate/errors01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ subroutine s13
!CHECK: error: NCOPIES= argument to REPEAT() should be nonnegative, but is -666
print *, repeat(' ', -666)
end subroutine
subroutine s14(n)
integer, intent(in) :: n
!CHECK: error: bit position for IBITS(POS=-1) is negative
print *, ibits(0, -1, n)
!CHECK: error: bit length for IBITS(LEN=-1) is negative
print *, ibits(0, n, -1)
!CHECK: error: IBITS() must have POS+LEN (>=33) no greater than 32
print *, ibits(0, n, 33)
!CHECK: error: IBITS() must have POS+LEN (>=33) no greater than 32
print *, ibits(0, 33, n)
end
subroutine warnings
real, parameter :: ok1 = scale(0.0, 99999) ! 0.0
real, parameter :: ok2 = scale(1.0, -99999) ! 0.0
Expand Down

0 comments on commit 6c5ba7c

Please sign in to comment.