From 6d1fdb793fec34d728bfd194b13df176a7f8c2cf Mon Sep 17 00:00:00 2001
From: Iain Sandoe <iain@sandoe.co.uk>
Date: Sun, 18 Dec 2016 14:42:02 +0000
Subject: [PATCH] [llvm] Chi-Hua's strnlen patch

diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index 18977d9950f..92f902af31f 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -212,6 +212,7 @@ check_symbol_exists(sbrk unistd.h HAVE_SBRK)
 check_symbol_exists(strerror string.h HAVE_STRERROR)
 check_symbol_exists(strerror_r string.h HAVE_STRERROR_R)
 check_symbol_exists(strerror_s string.h HAVE_DECL_STRERROR_S)
+check_symbol_exists(strnlen string.h HAVE_STRNLEN)
 check_symbol_exists(setenv stdlib.h HAVE_SETENV)
 if( PURE_WINDOWS )
   check_symbol_exists(_chsize_s io.h HAVE__CHSIZE_S)
diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake
index e934617d7ec..60264069b2d 100644
--- a/llvm/include/llvm/Config/config.h.cmake
+++ b/llvm/include/llvm/Config/config.h.cmake
@@ -184,6 +184,15 @@
 /* Define to 1 if you have the `strerror_r' function. */
 #cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R}
 
+/* Define to 1 if you have the `strtoll' function. */
+#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL}
+
+/* Define to 1 if you have the `strtoq' function. */
+#cmakedefine HAVE_STRTOQ ${HAVE_STRTOQ}
+
+/* Define to 1 if you have the `strnlen' function. */
+#cmakedefine HAVE_STRNLEN ${HAVE_STRNLEN}
+
 /* Define to 1 if you have the `sysconf' function. */
 #cmakedefine HAVE_SYSCONF ${HAVE_SYSCONF}
 
diff --git a/llvm/include/llvm/Support/string_compat.h b/llvm/include/llvm/Support/string_compat.h
new file mode 100644
index 00000000000..84b30232b33
--- /dev/null
+++ b/llvm/include/llvm/Support/string_compat.h
@@ -0,0 +1,20 @@
+#ifndef LLVM_SUPPORT_STRING_COMPAT_H
+#define LLVM_SUPPORT_STRING_COMPAT_H
+
+#include <stdlib.h>
+
+#include "llvm/Config/llvm-config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !HAVE_STRNLEN
+size_t strnlen(const char *s, size_t maxlen);
+#endif /* LLVM_HAS_STRNLEN */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LLVM_SUPPORT_STRING_COMPAT_H */
diff --git a/llvm/lib/ObjectYAML/MachOYAML.cpp b/llvm/lib/ObjectYAML/MachOYAML.cpp
index e00a4ea9307..12c55365394 100644
--- a/llvm/lib/ObjectYAML/MachOYAML.cpp
+++ b/llvm/lib/ObjectYAML/MachOYAML.cpp
@@ -16,6 +16,7 @@
 #include "llvm/BinaryFormat/MachO.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Host.h"
+#include "llvm/Support/string_compat.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cinttypes>
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 5688c1a8aef..a04164f1fd4 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -109,6 +109,7 @@ add_llvm_library(LLVMSupport
   SourceMgr.cpp
   SpecialCaseList.cpp
   Statistic.cpp
+  strnlen.c
   StringExtras.cpp
   StringMap.cpp
   StringPool.cpp
diff --git a/llvm/lib/Support/strnlen.c b/llvm/lib/Support/strnlen.c
new file mode 100644
index 00000000000..f72fe1157dd
--- /dev/null
+++ b/llvm/lib/Support/strnlen.c
@@ -0,0 +1,10 @@
+#include "llvm/Support/string_compat.h"
+
+#if !HAVE_STRNLEN
+size_t strnlen(const char *s, size_t maxlen) {
+  size_t rv = 0;
+  while (maxlen-- > 0 && *s++)
+    ++rv;
+  return rv;
+}
+#endif
diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp
index fa81ce974ec..2d68699f112 100644
--- a/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -14,8 +14,9 @@
 #include "llvm/ObjectYAML/ObjectYAML.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/LEB128.h"
+#include "llvm/Support/string_compat.h"
 
-#include <string.h> // for memcpy
+#include <cstring>
 
 using namespace llvm;
 
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index 4e08d7df7ad..c0a95f7f888 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -52,6 +52,7 @@ add_llvm_unittest(SupportTests
   SourceMgrTest.cpp
   SpecialCaseListTest.cpp
   StringPool.cpp
+  StrnlenTest.cpp
   SwapByteOrderTest.cpp
   TarWriterTest.cpp
   TargetParserTest.cpp
diff --git a/llvm/unittests/Support/StrnlenTest.cpp b/llvm/unittests/Support/StrnlenTest.cpp
new file mode 100644
index 00000000000..d2da57ec9fc
--- /dev/null
+++ b/llvm/unittests/Support/StrnlenTest.cpp
@@ -0,0 +1,22 @@
+#include "llvm/Support/string_compat.h"
+#include "gtest/gtest.h"
+
+#if !HAVE_STRNLEN
+using namespace llvm;
+namespace {
+
+class StrnlenTest : public ::testing::Test {};
+
+TEST_F(StrnlenTest, Basics) {
+  EXPECT_EQ(0u, strnlen("", 0));
+  EXPECT_EQ(0u, strnlen("", 1));
+  EXPECT_EQ(0u, strnlen("a", 0));
+  EXPECT_EQ(1u, strnlen("a", 1));
+  EXPECT_EQ(1u, strnlen("a", 2));
+  EXPECT_EQ(1u, strnlen("aa", 1));
+  EXPECT_EQ(2u, strnlen("aa", 2));
+  EXPECT_EQ(2u, strnlen("aabbcc", 2));
+  EXPECT_EQ(0u, strnlen("aabbcc", 0));
+}
+}
+#endif
