================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits