@@ -1917,7 +1917,7 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
19171917 const APSInt &Size =
19181918 peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
19191919
1920- if (ID == Builtin::BImemcmp)
1920+ if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp )
19211921 diagnoseNonConstexprBuiltin (S, OpPC, ID);
19221922
19231923 if (Size.isZero ()) {
@@ -1952,15 +1952,34 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
19521952 BufferB.byteSize ().getQuantity ());
19531953 size_t CmpSize =
19541954 std::min (MinBufferSize, static_cast <size_t >(Size.getZExtValue ()));
1955- int Result = std::memcmp (BufferA.Data .get (), BufferB.Data .get (), CmpSize);
1956- if (Result == 0 )
1955+
1956+ for (size_t I = 0 ; I != CmpSize; ++I) {
1957+ std::byte A = BufferA.Data [I];
1958+ std::byte B = BufferB.Data [I];
1959+
1960+ if (A < B) {
1961+ pushInteger (S, -1 , Call->getType ());
1962+ return true ;
1963+ } else if (A > B) {
1964+ pushInteger (S, 1 , Call->getType ());
1965+ return true ;
1966+ }
1967+ }
1968+
1969+ // We compared CmpSize bytes above. If the limiting factor was the Size
1970+ // passed, we're done and the result is equality (0).
1971+ if (Size.getZExtValue () <= CmpSize) {
19571972 pushInteger (S, 0 , Call->getType ());
1958- else if (Result < 0 )
1959- pushInteger (S, -1 , Call->getType ());
1960- else
1961- pushInteger (S, 1 , Call->getType ());
1973+ return true ;
1974+ }
19621975
1963- return true ;
1976+ // However, if we read all the available bytes but were instructed to read
1977+ // even more, diagnose this as a "read of dereferenced one-past-the-end
1978+ // pointer". This is what would happen if we called CheckRead() on every array
1979+ // element.
1980+ S.FFDiag (S.Current ->getSource (OpPC), diag::note_constexpr_access_past_end)
1981+ << AK_Read << S.Current ->getRange (OpPC);
1982+ return false ;
19641983}
19651984
19661985bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const Function *F,
@@ -2438,6 +2457,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
24382457
24392458 case Builtin::BI__builtin_memcmp:
24402459 case Builtin::BImemcmp:
2460+ case Builtin::BI__builtin_bcmp:
2461+ case Builtin::BIbcmp:
24412462 if (!interp__builtin_memcmp (S, OpPC, Frame, F, Call))
24422463 return false ;
24432464 break ;
0 commit comments