[clang] [clang][bytecode] Implement __builtin_{memchr,strchr,char_memchr} (PR #130420)
Nikolas Klauser via cfe-commits
cfe-commits at lists.llvm.org
Sun Mar 9 04:20:49 PDT 2025
================
@@ -1960,13 +1960,103 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
// However, if we read all the available bytes but were instructed to read
// even more, diagnose this as a "read of dereferenced one-past-the-end
- // pointer". This is what would happen if we called CheckRead() on every array
+ // pointer". This is what would happen if we called CheckLoad() on every array
// element.
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
<< AK_Read << S.Current->getRange(OpPC);
return false;
}
+static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const Function *Func, const CallExpr *Call) {
+ unsigned ID = Func->getBuiltinID();
+ if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
+ ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
+ diagnoseNonConstexprBuiltin(S, OpPC, ID);
+
+ const Pointer &Ptr = getParam<Pointer>(Frame, 0);
+ APSInt Desired;
+ std::optional<APSInt> MaxLength;
+ if (Call->getNumArgs() == 3) {
+ MaxLength =
+ peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)), 0);
+ Desired = peekToAPSInt(
+ S.Stk, *S.getContext().classify(Call->getArg(1)),
+ align(primSize(*S.getContext().classify(Call->getArg(2)))) +
+ align(primSize(*S.getContext().classify(Call->getArg(1)))));
+ } else {
+ Desired = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(1)));
+ }
+
+ if (MaxLength && MaxLength->isZero()) {
+ S.Stk.push<Pointer>();
+ return true;
+ }
+
+ if (Ptr.isDummy())
+ return false;
+
+ // Null is only okay if the given size is 0.
+ if (Ptr.isZero()) {
+ S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
+ << AK_Read;
+ return false;
+ }
+
+ QualType ElemTy = Ptr.getFieldDesc()->isArray()
+ ? Ptr.getFieldDesc()->getElemQualType()
+ : Ptr.getFieldDesc()->getType();
+ bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;
+
+ // Give up on byte-oriented matching against multibyte elements.
+ if (IsRawByte && !isOneByteCharacterType(ElemTy)) {
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_memchr_unsupported)
+ << S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;
+ return false;
+ }
+
+ if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {
+ // strchr compares directly to the passed integer, and therefore
+ // always fails if given an int that is not a char.
+ if (Desired !=
+ Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue()) {
----------------
philnik777 wrote:
Are you sure about this? cppreference seems to disagree with you: https://en.cppreference.com/w/cpp/string/byte/strchr
https://github.com/llvm/llvm-project/pull/130420
More information about the cfe-commits
mailing list