=?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

Reply via email to