diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -596,7 +596,9 @@ name == "dshiftl" ? &Scalar::DSHIFTL : &Scalar::DSHIFTR}; // Third argument can be of any kind. However, it must be smaller or equal // than BIT_SIZE. It can be converted to Int4 to simplify. - if (const auto *shiftCon{Folder(context).Folding(args[2])}) { + if (const auto *argCon{Folder(context).Folding(args[0])}; + argCon && argCon->empty()) { + } else if (const auto *shiftCon{Folder(context).Folding(args[2])}) { for (const auto &scalar : shiftCon->values()) { std::int64_t shiftVal{scalar.ToInt64()}; if (shiftVal < 0) { @@ -696,7 +698,9 @@ } else { common::die("missing case to fold intrinsic function %s", name.c_str()); } - if (const auto *posCon{Folder(context).Folding(args[1])}) { + if (const auto *argCon{Folder(context).Folding(args[0])}; + argCon && argCon->empty()) { + } else if (const auto *posCon{Folder(context).Folding(args[1])}) { for (const auto &scalar : posCon->values()) { std::int64_t posVal{scalar.ToInt64()}; if (posVal < 0) { @@ -720,7 +724,9 @@ } else if (name == "ibits") { const auto *posCon{Folder(context).Folding(args[1])}; const auto *lenCon{Folder(context).Folding(args[2])}; - if (posCon && lenCon && + if (const auto *argCon{Folder(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()}; @@ -823,9 +829,17 @@ return FoldBitReduction( context, std::move(funcRef), &Scalar::IEOR, Scalar{}); } else if (name == "ishft" || name == "ishftc") { + const auto *argCon{Folder(context).Folding(args[0])}; const auto *shiftCon{Folder(context).Folding(args[1])}; - if (shiftCon) { - for (const auto &scalar : shiftCon->values()) { + const auto *shiftVals{shiftCon ? &shiftCon->values() : nullptr}; + const auto *sizeCon{ + args.size() == 3 ? Folder(context).Folding(args[2]) : nullptr}; + const auto *sizeVals{sizeCon ? &sizeCon->values() : nullptr}; + if ((argCon && argCon->empty()) || !shiftVals || shiftVals->empty() || + (sizeVals && sizeVals->empty())) { + // size= and shift= values don't need to be checked + } else { + for (const auto &scalar : *shiftVals) { std::int64_t shiftVal{scalar.ToInt64()}; if (shiftVal < -T::Scalar::bits) { context.messages().Say( @@ -839,10 +853,8 @@ break; } } - } - if (args.size() == 3) { // ISHFTC - if (const auto *sizeCon{Folder(context).Folding(args[2])}) { - for (const auto &scalar : sizeCon->values()) { + if (sizeVals) { + for (const auto &scalar : *sizeVals) { std::int64_t sizeVal{scalar.ToInt64()}; if (sizeVal <= 0) { context.messages().Say( @@ -856,22 +868,14 @@ break; } } - if (shiftCon && - (shiftCon->size() == 1 || sizeCon->size() == 1 || - shiftCon->size() == sizeCon->size())) { - auto shiftIter{shiftCon->values().begin()}; - auto sizeIter{sizeCon->values().begin()}; - for (; shiftIter != shiftCon->values().end() && - sizeIter != sizeCon->values().end(); - ++shiftIter, ++sizeIter) { - shiftIter = shiftIter == shiftCon->values().end() - ? shiftCon->values().begin() - : shiftIter; - sizeIter = sizeIter == sizeCon->values().end() - ? sizeCon->values().begin() - : sizeIter; - auto shiftVal{static_cast(shiftIter->ToInt64())}; - auto sizeVal{static_cast(sizeIter->ToInt64())}; + if (shiftVals->size() == 1 || sizeVals->size() == 1 || + shiftVals->size() == sizeVals->size()) { + auto iters{std::max(shiftVals->size(), sizeVals->size())}; + for (std::size_t j{0}; j < iters; ++j) { + auto shiftVal{static_cast( + (*shiftVals)[j % shiftVals->size()].ToInt64())}; + auto sizeVal{ + static_cast((*sizeVals)[j % sizeVals->size()].ToInt64())}; if (sizeVal > 0 && std::abs(shiftVal) > sizeVal) { context.messages().Say( "SHIFT=%jd count for ishftc is greater in magnitude than SIZE=%jd"_err_en_US, @@ -900,7 +904,6 @@ ScalarFunc( [&](const Scalar &i, const Scalar &shift, const Scalar &size) -> Scalar { - // Errors are caught in intrinsics.cpp auto shiftVal{static_cast(shift.ToInt64())}; auto sizeVal{static_cast(size.ToInt64())}; return i.ISHFTC(shiftVal, sizeVal); @@ -1154,7 +1157,9 @@ } else { common::die("missing case to fold intrinsic function %s", name.c_str()); } - if (const auto *shiftCon{Folder(context).Folding(args[1])}) { + if (const auto *argCon{Folder(context).Folding(args[0])}; + argCon && argCon->empty()) { + } else if (const auto *shiftCon{Folder(context).Folding(args[1])}) { for (const auto &scalar : shiftCon->values()) { std::int64_t shiftVal{scalar.ToInt64()}; if (shiftVal < 0) { diff --git a/flang/test/Semantics/ishftc.f90 b/flang/test/Semantics/ishftc.f90 --- a/flang/test/Semantics/ishftc.f90 +++ b/flang/test/Semantics/ishftc.f90 @@ -26,6 +26,10 @@ n = ishftc(3, 2, 1) !ERROR: SHIFT=-2 count for ishftc is greater in magnitude than SIZE=1 n = ishftc(3, -2, 1) + !ERROR: SHIFT=4 count for ishftc is greater in magnitude than SIZE=3 + array_result = ishftc(666, [(j,integer::j=1,5)], 3) + !ERROR: SHIFT=4 count for ishftc is greater in magnitude than SIZE=3 + array_result = ishftc(666, 4, [(j,integer::j=10,3,-1)]) !ERROR: SIZE=-3 count for ishftc is not positive array_result = ishftc([3,3], [2,2], [-3,3]) !ERROR: SIZE=-3 count for ishftc is not positive @@ -44,5 +48,5 @@ array_result = ishftc([3,3], [-2,-2], const_arr6) !ERROR: SIZE=0 count for ishftc is not positive array_result = ishftc([3,3], [-2,-2], const_arr7) - + array_result = ishftc([(j,integer::j=1,0)], 10, 9) ! ok because empty end program test_ishftc