@@ -1917,7 +1917,7 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
1917
1917
const APSInt &Size =
1918
1918
peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
1919
1919
1920
- if (ID == Builtin::BImemcmp)
1920
+ if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp )
1921
1921
diagnoseNonConstexprBuiltin (S, OpPC, ID);
1922
1922
1923
1923
if (Size .isZero ()) {
@@ -1952,15 +1952,34 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
1952
1952
BufferB.byteSize ().getQuantity ());
1953
1953
size_t CmpSize =
1954
1954
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) {
1957
1972
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
+ }
1962
1975
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 ;
1964
1983
}
1965
1984
1966
1985
bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const Function *F,
@@ -2438,6 +2457,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
2438
2457
2439
2458
case Builtin::BI__builtin_memcmp:
2440
2459
case Builtin::BImemcmp:
2460
+ case Builtin::BI__builtin_bcmp:
2461
+ case Builtin::BIbcmp:
2441
2462
if (!interp__builtin_memcmp (S, OpPC, Frame, F, Call))
2442
2463
return false ;
2443
2464
break ;
0 commit comments