diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index 86fb46ba6094e..e8818082c5cf5 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -525,30 +525,30 @@ Expr> FoldIntrinsicFunction( } else if (name == "iany") { return FoldBitReduction( context, std::move(funcRef), &Scalar::IOR, Scalar{}); - } else if (name == "ibclr" || name == "ibset" || name == "ishft" || - name == "shifta" || name == "shiftr" || name == "shiftl") { - // Second argument can be of any kind. However, it must be smaller or - // equal than BIT_SIZE. It can be converted to Int4 to simplify. + } else if (name == "ibclr" || name == "ibset") { + // Second argument can be of any kind. However, it must be smaller + // than BIT_SIZE. It can be converted to Int4 to simplify. auto fptr{&Scalar::IBCLR}; - if (name == "ibclr") { // done in fprt definition + if (name == "ibclr") { // done in fptr definition } else if (name == "ibset") { fptr = &Scalar::IBSET; - } else if (name == "ishft") { - fptr = &Scalar::ISHFT; - } else if (name == "shifta") { - fptr = &Scalar::SHIFTA; - } else if (name == "shiftr") { - fptr = &Scalar::SHIFTR; - } else if (name == "shiftl") { - fptr = &Scalar::SHIFTL; } else { common::die("missing case to fold intrinsic function %s", name.c_str()); } return FoldElementalIntrinsic(context, std::move(funcRef), - ScalarFunc( - [&fptr](const Scalar &i, const Scalar &pos) -> Scalar { - return std::invoke(fptr, i, static_cast(pos.ToInt64())); - })); + ScalarFunc([&](const Scalar &i, + const Scalar &pos) -> Scalar { + auto posVal{static_cast(pos.ToInt64())}; + if (posVal < 0) { + context.messages().Say( + "bit position for %s (%d) is negative"_err_en_US, name, posVal); + } else if (posVal >= i.bits) { + context.messages().Say( + "bit position for %s (%d) is not less than %d"_err_en_US, name, + posVal, i.bits); + } + return std::invoke(fptr, i, posVal); + })); } else if (name == "index" || name == "scan" || name == "verify") { if (auto *charExpr{UnwrapExpr>(args[0])}) { return std::visit( @@ -610,6 +610,35 @@ Expr> FoldIntrinsicFunction( } else if (name == "iparity") { return FoldBitReduction( context, std::move(funcRef), &Scalar::IEOR, Scalar{}); + } else if (name == "ishft" || name == "shifta" || name == "shiftr" || + name == "shiftl") { + // Second argument can be of any kind. However, it must be smaller or + // equal than BIT_SIZE. It can be converted to Int4 to simplify. + auto fptr{&Scalar::ISHFT}; + if (name == "ISHFT") { // done in fptr definition + } else if (name == "shifta") { + fptr = &Scalar::SHIFTA; + } else if (name == "shiftr") { + fptr = &Scalar::SHIFTR; + } else if (name == "shiftl") { + fptr = &Scalar::SHIFTL; + } else { + common::die("missing case to fold intrinsic function %s", name.c_str()); + } + return FoldElementalIntrinsic(context, std::move(funcRef), + ScalarFunc([&](const Scalar &i, + const Scalar &pos) -> Scalar { + auto posVal{static_cast(pos.ToInt64())}; + if (posVal < 0) { + context.messages().Say( + "shift count for %s (%d) is negative"_err_en_US, name, posVal); + } else if (posVal > i.bits) { + context.messages().Say( + "shift count for %s (%d) is greater than %d"_err_en_US, name, + posVal, i.bits); + } + return std::invoke(fptr, i, posVal); + })); } else if (name == "lbound") { return LBOUND(context, std::move(funcRef)); } else if (name == "leadz" || name == "trailz" || name == "poppar" ||