=?utf-8?q?Félix?= Cloutier <fclout...@apple.com>, =?utf-8?q?Félix?= Cloutier <fclout...@apple.com>, =?utf-8?q?Félix?= Cloutier <fclout...@apple.com>, =?utf-8?q?Félix?= Cloutier <fclout...@apple.com>, =?utf-8?q?Félix?= Cloutier <fclout...@apple.com>, =?utf-8?q?Félix?= Cloutier <fclout...@apple.com>, =?utf-8?q?Félix?= Cloutier <fclout...@apple.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/135...@github.com>
================ @@ -17971,46 +18006,117 @@ static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result, S->getCharByteWidth() == 1 && // FIXME: Add fast-path for wchar_t too. Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) { - Str = Str.substr(Off); - - StringRef::size_type Pos = Str.find(0); - if (Pos != StringRef::npos) - Str = Str.substr(0, Pos); - - Result = Str.size(); - if (StringResult) - *StringResult = Str; - return true; + Offset = static_cast<uint64_t>(Off); + return S; } - - // Fall through to slow path. } + return nullptr; +} - // Slow path: scan the bytes of the string looking for the terminating 0. - for (uint64_t Strlen = 0; /**/; ++Strlen) { +template <typename CharAction> +static bool IterateStringLValue(EvalInfo &Info, const Expr *E, QualType CharTy, + LValue &String, CharAction &&Action) { + while (true) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || !Char.isInt()) return false; - if (!Char.getInt()) { - Result = Strlen; + if (!Action(Char.getInt().getExtValue())) return true; - } else if (StringResult) - StringResult->push_back(Char.getInt().getExtValue()); if (!HandleLValueArrayAdjustment(Info, E, String, CharTy, 1)) return false; } } -std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const { +static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result, + EvalInfo &Info) { + LValue String; + QualType CharTy; + if (!EvaluateStringAsLValue(Info, E, CharTy, String)) + return false; + + // Fast path: if it's a string literal, search the string value. + uint64_t Off; + if (const auto *S = StringLValueIsLiteral(Info, String, CharTy, Off)) { + StringRef Str = S->getBytes().substr(Off); + + StringRef::size_type Pos = Str.find(0); + if (Pos != StringRef::npos) + Str = Str.substr(0, Pos); + + Result = Str.size(); + return true; + } + + // Slow path: scan the bytes of the string looking for the terminating 0. + Result = 0; + return IterateStringLValue(Info, E, CharTy, String, [&](int Char) { + if (Char) { + Result++; + return true; + } else + return false; + }); +} + +Expr::StringEvalResult::StringEvalResult(const StringLiteral *SL, + uint64_t Offset) + : SL(SL), Offset(Offset) {} + +Expr::StringEvalResult::StringEvalResult(std::string Contents) + : Storage(std::move(Contents)), SL(nullptr), Offset(0) {} + +llvm::StringRef Expr::StringEvalResult::getString() const { + return SL ? SL->getBytes().substr(Offset) : Storage; +} + +bool Expr::StringEvalResult::getStringLiteral(const StringLiteral *&SL, + uint64_t &Offset) const { + if (this->SL) { + SL = this->SL; + Offset = this->Offset; + return true; + } + return false; +} + +std::optional<Expr::StringEvalResult> +Expr::tryEvaluateString(ASTContext &Ctx, bool *NullTerminated, + bool InConstantContext) const { + if (NullTerminated) + *NullTerminated = false; ---------------- cor3ntin wrote: Can we put that in StringEvalResult instead? https://github.com/llvm/llvm-project/pull/135864 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits