]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
C++-ify hashutil functions
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 29 Jul 2020 18:31:53 +0000 (20:31 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 30 Jul 2020 19:04:01 +0000 (21:04 +0200)
src/ccache.cpp
src/hashutil.cpp
src/hashutil.hpp
src/manifest.cpp
unittest/test_hashutil.cpp

index eb2f3f1c39b9b1fed0fc84422a29d702b1f93a9a..626a6e96b584ade2e85f3e9049c30afcc658dcf5 100644 (file)
@@ -344,7 +344,7 @@ do_remember_include_file(Context& ctx,
       }
     }
 
-    if (!hash_binary_file(ctx, fhash, path.c_str())) {
+    if (!hash_binary_file(ctx, fhash, path)) {
       return false;
     }
     cpp_hash.hash_delimiter(using_pch_sum ? "pch_sum_hash" : "pch_hash");
@@ -353,7 +353,7 @@ do_remember_include_file(Context& ctx,
 
   if (ctx.config.direct_mode()) {
     if (!is_pch) { // else: the file has already been hashed.
-      int result = hash_source_code_file(ctx, fhash, path.c_str());
+      int result = hash_source_code_file(ctx, fhash, path);
       if (result & HASH_SOURCE_CODE_ERROR
           || result & HASH_SOURCE_CODE_FOUND_TIME) {
         return false;
@@ -1073,7 +1073,7 @@ get_result_name_from_cpp(Context& ctx, Args& args, Hash& hash)
 
   hash.hash_delimiter("cppstderr");
   if (!ctx.args_info.direct_i_file
-      && !hash_binary_file(ctx, hash, stderr_path.c_str())) {
+      && !hash_binary_file(ctx, hash, stderr_path)) {
     // Somebody removed the temporary file?
     cc_log("Failed to open %s: %s", stderr_path.c_str(), strerror(errno));
     failed(STATS_ERROR);
@@ -1123,9 +1123,8 @@ hash_compiler(const Context& ctx,
     hash.hash_delimiter("cc_content");
     hash_binary_file(ctx, hash, path);
   } else { // command string
-    if (!hash_multicommand_output(hash,
-                                  ctx.config.compiler_check().c_str(),
-                                  ctx.orig_args[0].c_str())) {
+    if (!hash_multicommand_output(
+          hash, ctx.config.compiler_check(), ctx.orig_args[0])) {
       cc_log("Failure running compiler check command: %s",
              ctx.config.compiler_check().c_str());
       failed(STATS_COMPCHECK);
@@ -1294,7 +1293,7 @@ hash_common_info(const Context& ctx,
   for (const auto& sanitize_blacklist : args_info.sanitize_blacklists) {
     cc_log("Hashing sanitize blacklist %s", sanitize_blacklist.c_str());
     hash.hash("sanitizeblacklist");
-    if (!hash_binary_file(ctx, hash, sanitize_blacklist.c_str())) {
+    if (!hash_binary_file(ctx, hash, sanitize_blacklist)) {
       failed(STATS_BADEXTRAFILE);
     }
   }
@@ -1304,7 +1303,7 @@ hash_common_info(const Context& ctx,
            ctx.config.extra_files_to_hash(), PATH_DELIM)) {
       cc_log("Hashing extra file %s", path.c_str());
       hash.hash_delimiter("extrafile");
-      if (!hash_binary_file(ctx, hash, path.c_str())) {
+      if (!hash_binary_file(ctx, hash, path)) {
         failed(STATS_BADEXTRAFILE);
       }
     }
@@ -1348,7 +1347,7 @@ hash_profile_data_file(const Context& ctx, Hash& hash)
     if (st && !st.is_directory()) {
       cc_log("Adding profile data %s to the hash", p.c_str());
       hash.hash_delimiter("-fprofile-use");
-      if (hash_binary_file(ctx, hash, p.c_str())) {
+      if (hash_binary_file(ctx, hash, p)) {
         found = true;
       }
     }
@@ -1622,8 +1621,7 @@ calculate_result_name(Context& ctx,
     hash.hash(ctx.args_info.input_file);
 
     hash.hash_delimiter("sourcecode");
-    int result =
-      hash_source_code_file(ctx, hash, ctx.args_info.input_file.c_str());
+    int result = hash_source_code_file(ctx, hash, ctx.args_info.input_file);
     if (result & HASH_SOURCE_CODE_ERROR) {
       failed(STATS_ERROR);
     }
index e09a349cb9b66e31bb1d2ff48e8b08a39635e107..12f5761c87edf63e2ab0d13ded76c82b929af866 100644 (file)
 #  include "Win32Util.hpp"
 #endif
 
-#include "third_party/xxhash.h"
-
 // With older GCC (libgcc), __builtin_cpu_supports("avx2) returns true if AVX2
 // is supported by the CPU but disabled by the OS. This was fixed in GCC 8, 7.4
 // and 6.5 (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85100).
 //
 // For Clang it seems to be correct if compiler-rt is used as -rtlib, at least
-// as of 3.9 (see https://bugs.llvm.org/show_bug.cgi?id=25510). But if libgcc
-// is used we have the same problem as mentioned above. Unfortunately there
-// doesn't seem to be a way to detect which one is used, or the version of
-// libgcc when used by Clang, so assume that it works with Clang >= 3.9.
+// as of 3.9 (see https://bugs.llvm.org/show_bug.cgi?id=25510). But if libgcc is
+// used we have the same problem as mentioned above. Unfortunately there doesn't
+// seem to be a way to detect which one is used, or the version of libgcc when
+// used by Clang, so assume that it works with Clang >= 3.9.
 #if !(__GNUC__ >= 8 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 4)                  \
       || (__GNUC__ == 6 && __GNUC_MINOR__ >= 5) || __clang_major__ > 3         \
       || (__clang_major__ == 3 && __clang_minor__ >= 9))
 #  include <immintrin.h>
 #endif
 
+using nonstd::string_view;
+
+namespace {
+
 // Returns one of HASH_SOURCE_CODE_FOUND_DATE, HASH_SOURCE_CODE_FOUND_TIME or
 // HASH_SOURCE_CODE_FOUND_TIMESTAMP if "_DATE__", "_TIME__" or "_TIMESTAMP__"
 // starts at str[pos].
 //
 // Pre-condition: str[pos - 1] == '_'
-static int
-check_for_temporal_macros_helper(const char* str, size_t len, size_t pos)
+int
+check_for_temporal_macros_helper(string_view str, size_t pos)
 {
-  if (pos + 7 > len) {
+  if (pos + 7 > str.length()) {
     return 0;
   }
 
   int found = 0;
   int macro_len = 7;
-  if (memcmp(str + pos, "_DATE__", 7) == 0) {
+  if (memcmp(&str[pos], "_DATE__", 7) == 0) {
     found = HASH_SOURCE_CODE_FOUND_DATE;
-  } else if (memcmp(str + pos, "_TIME__", 7) == 0) {
+  } else if (memcmp(&str[pos], "_TIME__", 7) == 0) {
     found = HASH_SOURCE_CODE_FOUND_TIME;
-  } else if (pos + 12 <= len && memcmp(str + pos, "_TIMESTAMP__", 12) == 0) {
+  } else if (pos + 12 <= str.length()
+             && memcmp(&str[pos], "_TIMESTAMP__", 12) == 0) {
     found = HASH_SOURCE_CODE_FOUND_TIMESTAMP;
     macro_len = 12;
   } else {
     return 0;
   }
 
-  // Check char before and after macro to verify that the found macro isn't
-  // part of another identifier.
+  // Check char before and after macro to verify that the found macro isn't part
+  // of another identifier.
   if ((pos == 1 || (str[pos - 2] != '_' && !isalnum(str[pos - 2])))
-      && (pos + macro_len == len
+      && (pos + macro_len == str.length()
           || (str[pos + macro_len] != '_' && !isalnum(str[pos + macro_len])))) {
     return found;
   }
@@ -94,8 +97,8 @@ check_for_temporal_macros_helper(const char* str, size_t len, size_t pos)
   return 0;
 }
 
-static int
-check_for_temporal_macros_bmh(const char* str, size_t len)
+int
+check_for_temporal_macros_bmh(string_view str)
 {
   int result = 0;
 
@@ -104,12 +107,12 @@ check_for_temporal_macros_bmh(const char* str, size_t len)
   // starts at 7.
   size_t i = 7;
 
-  while (i < len) {
+  while (i < str.length()) {
     // Check whether the substring ending at str[i] has the form "_....E..". On
     // the assumption that 'E' is less common in source than '_', we check
     // str[i-2] first.
     if (str[i - 2] == 'E' && str[i - 7] == '_') {
-      result |= check_for_temporal_macros_helper(str, len, i - 6);
+      result |= check_for_temporal_macros_helper(str, i - 6);
     }
 
     // macro_skip tells us how far we can skip forward upon seeing str[i] at
@@ -121,14 +124,14 @@ check_for_temporal_macros_bmh(const char* str, size_t len)
 }
 
 #ifdef HAVE_AVX2
-static int check_for_temporal_macros_avx2(const char* str, size_t len)
+int check_for_temporal_macros_avx2(string_view str)
   __attribute__((target("avx2")));
 
 // The following algorithm, which uses AVX2 instructions to find __DATE__,
 // __TIME__ and __TIMESTAMP__, is heavily inspired by
 // <http://0x80.pl/articles/simd-strfind.html>.
-static int
-check_for_temporal_macros_avx2(const char* str, size_t len)
+int
+check_for_temporal_macros_avx2(string_view str)
 {
   int result = 0;
 
@@ -137,14 +140,14 @@ check_for_temporal_macros_avx2(const char* str, size_t len)
   const __m256i last = _mm256_set1_epi8('E');
 
   size_t pos = 0;
-  for (; pos + 5 + 32 <= len; pos += 32) {
+  for (; pos + 5 + 32 <= str.length(); pos += 32) {
     // Load 32 bytes from the current position in the input string, with
     // block_last being offset 5 bytes (i.e. the offset of 'E' in all three
     // macros).
     const __m256i block_first =
-      _mm256_loadu_si256(reinterpret_cast<const __m256i*>(str + pos));
+      _mm256_loadu_si256(reinterpret_cast<const __m256i*>(&str[pos]));
     const __m256i block_last =
-      _mm256_loadu_si256(reinterpret_cast<const __m256i*>(str + pos + 5));
+      _mm256_loadu_si256(reinterpret_cast<const __m256i*>(&str[pos + 5]));
 
     // For i in 0..31:
     //   eq_X[i] = 0xFF if X[i] == block_X[i] else 0
@@ -163,50 +166,87 @@ check_for_temporal_macros_avx2(const char* str, size_t len)
       // Clear the least significant bit set.
       mask = mask & (mask - 1);
 
-      result |= check_for_temporal_macros_helper(str, len, start);
+      result |= check_for_temporal_macros_helper(str, start);
     }
   }
 
-  result |= check_for_temporal_macros_bmh(str + pos, len - pos);
+  result |= check_for_temporal_macros_bmh(str.substr(pos));
 
   return result;
 }
 #endif
 
-// Search for the strings "__DATE__", "__TIME__" and "__TIMESTAMP__" in str.
-//
-// Returns a bitmask with HASH_SOURCE_CODE_FOUND_DATE,
-// HASH_SOURCE_CODE_FOUND_TIME and HASH_SOURCE_CODE_FOUND_TIMESTAMP set
-// appropriately.
 int
-check_for_temporal_macros(const char* str, size_t len)
+hash_source_code_file_nocache(const Context& ctx,
+                              Hash& hash,
+                              const std::string& path,
+                              size_t size_hint,
+                              bool is_precompiled)
+{
+  if (is_precompiled) {
+    if (hash.hash_file(path)) {
+      return HASH_SOURCE_CODE_OK;
+    } else {
+      return HASH_SOURCE_CODE_ERROR;
+    }
+  } else {
+    std::string data;
+    try {
+      data = Util::read_file(path, size_hint);
+    } catch (Error&) {
+      return HASH_SOURCE_CODE_ERROR;
+    }
+    int result = hash_source_code_string(ctx, hash, data, path);
+    return result;
+  }
+}
+
+#ifdef INODE_CACHE_SUPPORTED
+InodeCache::ContentType
+get_content_type(const Config& config, const std::string& path)
+{
+  if (Util::is_precompiled_header(path)) {
+    return InodeCache::ContentType::precompiled_header;
+  }
+  if (config.sloppiness() & SLOPPY_TIME_MACROS) {
+    return InodeCache::ContentType::code_with_sloppy_time_macros;
+  }
+  return InodeCache::ContentType::code;
+}
+#endif
+
+} // namespace
+
+int
+check_for_temporal_macros(string_view str)
 {
 #ifdef HAVE_AVX2
   if (__builtin_cpu_supports("avx2")) {
-    return check_for_temporal_macros_avx2(str, len);
+    return check_for_temporal_macros_avx2(str);
   }
 #endif
-  return check_for_temporal_macros_bmh(str, len);
+  return check_for_temporal_macros_bmh(str);
 }
 
-// Hash a string. Returns a bitmask of HASH_SOURCE_CODE_* results.
 int
-hash_source_code_string(
-  const Context& ctx, Hash& hash, const char* str, size_t len, const char* path)
+hash_source_code_string(const Context& ctx,
+                        Hash& hash,
+                        string_view str,
+                        const std::string& path)
 {
   int result = HASH_SOURCE_CODE_OK;
 
   // Check for __DATE__, __TIME__ and __TIMESTAMP__if the sloppiness
   // configuration tells us we should.
   if (!(ctx.config.sloppiness() & SLOPPY_TIME_MACROS)) {
-    result |= check_for_temporal_macros(str, len);
+    result |= check_for_temporal_macros(str);
   }
 
   // Hash the source string.
-  hash.hash(str, len);
+  hash.hash(str);
 
   if (result & HASH_SOURCE_CODE_FOUND_DATE) {
-    cc_log("Found __DATE__ in %s", path);
+    cc_log("Found __DATE__ in %s", path.c_str());
 
     // Make sure that the hash sum changes if the (potential) expansion of
     // __DATE__ changes.
@@ -221,16 +261,15 @@ hash_source_code_string(
     hash.hash(now.tm_mday);
   }
   if (result & HASH_SOURCE_CODE_FOUND_TIME) {
-    // We don't know for sure that the program actually uses the __TIME__
-    // macro, but we have to assume it anyway and hash the time stamp. However,
-    // that's not very useful since the chance that we get a cache hit later
-    // the same second should be quite slim... So, just signal back to the
-    // caller that __TIME__ has been found so that the direct mode can be
-    // disabled.
-    cc_log("Found __TIME__ in %s", path);
+    // We don't know for sure that the program actually uses the __TIME__ macro,
+    // but we have to assume it anyway and hash the time stamp. However, that's
+    // not very useful since the chance that we get a cache hit later the same
+    // second should be quite slim... So, just signal back to the caller that
+    // __TIME__ has been found so that the direct mode can be disabled.
+    cc_log("Found __TIME__ in %s", path.c_str());
   }
   if (result & HASH_SOURCE_CODE_FOUND_TIMESTAMP) {
-    cc_log("Found __TIMESTAMP__ in %s", path);
+    cc_log("Found __TIMESTAMP__ in %s", path.c_str());
 
     // Make sure that the hash sum changes if the (potential) expansion of
     // __TIMESTAMP__ changes.
@@ -261,52 +300,10 @@ hash_source_code_string(
   return result;
 }
 
-static int
-hash_source_code_file_nocache(const Context& ctx,
-                              Hash& hash,
-                              const char* path,
-                              size_t size_hint,
-                              bool is_precompiled)
-{
-  if (is_precompiled) {
-    if (hash.hash_file(path)) {
-      return HASH_SOURCE_CODE_OK;
-    } else {
-      return HASH_SOURCE_CODE_ERROR;
-    }
-  } else {
-    std::string data;
-    try {
-      data = Util::read_file(path, size_hint);
-    } catch (Error&) {
-      return HASH_SOURCE_CODE_ERROR;
-    }
-    int result =
-      hash_source_code_string(ctx, hash, data.data(), data.size(), path);
-    return result;
-  }
-}
-
-#ifdef INODE_CACHE_SUPPORTED
-static InodeCache::ContentType
-get_content_type(const Config& config, const char* path)
-{
-  if (Util::is_precompiled_header(path)) {
-    return InodeCache::ContentType::precompiled_header;
-  }
-  if (config.sloppiness() & SLOPPY_TIME_MACROS) {
-    return InodeCache::ContentType::code_with_sloppy_time_macros;
-  }
-  return InodeCache::ContentType::code;
-}
-#endif
-
-// Hash a file ignoring comments. Returns a bitmask of HASH_SOURCE_CODE_*
-// results.
 int
 hash_source_code_file(const Context& ctx,
                       Hash& hash,
-                      const char* path,
+                      const std::string& path,
                       size_t size_hint)
 {
 #ifdef INODE_CACHE_SUPPORTED
@@ -343,11 +340,8 @@ hash_source_code_file(const Context& ctx,
 #endif
 }
 
-// Hash a binary file using the inode cache if enabled.
-//
-// Returns true on success, otherwise false.
 bool
-hash_binary_file(const Context& ctx, Hash& hash, const char* path)
+hash_binary_file(const Context& ctx, Hash& hash, const std::string& path)
 {
   if (!ctx.config.inode_cache()) {
     return hash.hash_file(path);
@@ -374,33 +368,30 @@ hash_binary_file(const Context& ctx, Hash& hash, const char* path)
 }
 
 bool
-hash_command_output(Hash& hash, const char* command, const char* compiler)
+hash_command_output(Hash& hash,
+                    const std::string& command,
+                    const std::string& compiler)
 {
 #ifdef _WIN32
-  // Trim leading space.
-  while (isspace(*command)) {
-    command++;
-  }
+  std::string adjusted_command = Util::strip_whitespace(command);
 
   // Add "echo" command.
   bool using_cmd_exe;
-  std::string adjusted_command;
-  if (str_startswith(command, "echo")) {
-    adjusted_command = fmt::format("cmd.exe /c \"{}\"", command);
+  if (Util::starts_with(adjusted_command, "echo")) {
+    adjusted_command = fmt::format("cmd.exe /c \"{}\"", adjusted_command);
     using_cmd_exe = true;
-  } else if (str_startswith(command, "%compiler%")
-             && str_eq(compiler, "echo")) {
+  } else if (Util::starts_with(adjusted_command, "%compiler%")
+             && compiler == "echo") {
     adjusted_command =
-      fmt::format("cmd.exe /c \"{}{}\"", compiler, command + 10);
+      fmt::format("cmd.exe /c \"{}{}\"", compiler, adjusted_command.substr(10));
     using_cmd_exe = true;
   } else {
-    adjusted_command = command;
     using_cmd_exe = false;
   }
-  command = adjusted_command.c_str();
-#endif
-
+  Args args = Args::from_string(adjusted_command);
+#else
   Args args = Args::from_string(command);
+#endif
 
   for (size_t i = 0; i < args.size(); i++) {
     if (args[i] == "%compiler%") {
@@ -439,7 +430,7 @@ hash_command_output(Hash& hash, const char* command, const char* compiler)
 
   std::string win32args;
   if (using_cmd_exe) {
-    win32args = command; // quoted
+    win32args = adjusted_command; // quoted
   } else {
     win32args = Win32Util::argv_to_string(argv.data(), sh);
   }
@@ -517,13 +508,14 @@ hash_command_output(Hash& hash, const char* command, const char* compiler)
 }
 
 bool
-hash_multicommand_output(Hash& hash, const char* commands, const char* compiler)
+hash_multicommand_output(Hash& hash,
+                         const std::string& commands,
+                         const std::string& compiler)
 {
-  bool ok = true;
   for (const std::string& cmd : Util::split_into_strings(commands, ";")) {
-    if (!hash_command_output(hash, cmd.c_str(), compiler)) {
-      ok = false;
+    if (!hash_command_output(hash, cmd, compiler)) {
+      return false;
     }
   }
-  return ok;
+  return true;
 }
index bb10d87969290a005f0a7c02881bd3267a1751ca..aa85cd554418182360d70c77ec309a860cdf396d 100644 (file)
 
 #include "system.hpp"
 
-#include <inttypes.h>
+#include "third_party/nonstd/string_view.hpp"
+
+#include <string>
 
 class Config;
 class Context;
 class Hash;
 
-#define HASH_SOURCE_CODE_OK 0
-#define HASH_SOURCE_CODE_ERROR 1
-#define HASH_SOURCE_CODE_FOUND_DATE 2
-#define HASH_SOURCE_CODE_FOUND_TIME 4
-#define HASH_SOURCE_CODE_FOUND_TIMESTAMP 8
+const int HASH_SOURCE_CODE_OK = 0;
+const int HASH_SOURCE_CODE_ERROR = (1 << 0);
+const int HASH_SOURCE_CODE_FOUND_DATE = (1 << 1);
+const int HASH_SOURCE_CODE_FOUND_TIME = (1 << 2);
+const int HASH_SOURCE_CODE_FOUND_TIMESTAMP = (1 << 3);
+
+// Search for the strings "__DATE__", "__TIME__" and "__TIMESTAMP__" in `str`.
+//
+// Returns a bitmask with HASH_SOURCE_CODE_FOUND_DATE,
+// HASH_SOURCE_CODE_FOUND_TIME and HASH_SOURCE_CODE_FOUND_TIMESTAMP set
+// appropriately.
+int check_for_temporal_macros(nonstd::string_view str);
 
-int check_for_temporal_macros(const char* str, size_t len);
+// Hash a string. Returns a bitmask of HASH_SOURCE_CODE_* results.
 int hash_source_code_string(const Context& ctx,
                             Hash& hash,
-                            const char* str,
-                            size_t len,
-                            const char* path);
+                            nonstd::string_view str,
+                            const std::string& path);
+
+// Hash a file ignoring comments. Returns a bitmask of HASH_SOURCE_CODE_*
+// results.
 int hash_source_code_file(const Context& ctx,
                           Hash& hash,
-                          const char* path,
+                          const std::string& path,
                           size_t size_hint = 0);
-bool hash_binary_file(const Context& ctx, Hash& hash, const char* path);
-bool hash_command_output(Hash& hash, const char* command, const char* compiler);
-bool
-hash_multicommand_output(Hash& hash, const char* command, const char* compiler);
+
+// Hash a binary file using the inode cache if enabled.
+//
+// Returns true on success, otherwise false.
+bool hash_binary_file(const Context& ctx, Hash& hash, const std::string& path);
+
+// Hash the output of `command` (not executed via a shell). A "%compiler%"
+// string in `command` will be replaced with `compiler`.
+bool hash_command_output(Hash& hash,
+                         const std::string& command,
+                         const std::string& compiler);
+
+// Like `hash_command_output` but for each semicolon-separated command in
+// `command`.
+bool hash_multicommand_output(Hash& hash,
+                              const std::string& command,
+                              const std::string& compiler);
index 04decc6ed60656dfe3baf688d794e33b40cfabf8..6238f08823317701a708e1821bd7cd40bad2c8cb 100644 (file)
@@ -452,7 +452,7 @@ verify_result(const Context& ctx,
     auto hashed_files_iter = hashed_files.find(path);
     if (hashed_files_iter == hashed_files.end()) {
       Hash hash;
-      int ret = hash_source_code_file(ctx, hash, path.c_str(), fs.size);
+      int ret = hash_source_code_file(ctx, hash, path, fs.size);
       if (ret & HASH_SOURCE_CODE_ERROR) {
         cc_log("Failed hashing %s", path.c_str());
         return false;
index 9ca6678bb769152e10a50f2961fc8120e975052d..8f76516573b65eb988680f04bb4f261de4648de3 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "third_party/doctest.h"
 
+using nonstd::string_view;
 using TestUtil::TestContext;
 
 TEST_SUITE_BEGIN("hashutil");
@@ -117,31 +118,31 @@ TEST_CASE("hash_multicommand_output_error_handling")
 
 TEST_CASE("check_for_temporal_macros")
 {
-  const char time_start[] =
+  const string_view time_start =
     "__TIME__\n"
     "int a;\n";
-  const char time_middle[] =
+  const string_view time_middle =
     "#define a __TIME__\n"
     "int a;\n";
-  const char time_end[] = "#define a __TIME__";
+  const string_view time_end = "#define a __TIME__";
 
-  const char date_start[] =
+  const string_view date_start =
     "__DATE__\n"
     "int ab;\n";
-  const char date_middle[] =
+  const string_view date_middle =
     "#define ab __DATE__\n"
     "int ab;\n";
-  const char date_end[] = "#define ab __DATE__";
+  const string_view date_end = "#define ab __DATE__";
 
-  const char timestamp_start[] =
+  const string_view timestamp_start =
     "__TIMESTAMP__\n"
     "int c;\n";
-  const char timestamp_middle[] =
+  const string_view timestamp_middle =
     "#define c __TIMESTAMP__\n"
     "int c;\n";
-  const char timestamp_end[] = "#define c __TIMESTAMP__";
+  const string_view timestamp_end = "#define c __TIMESTAMP__";
 
-  const char no_temporal[] =
+  const string_view no_temporal =
     "#define ab a__DATE__\n"
     "#define ab  __DATE__a\n"
     "#define ab A__DATE__\n"
@@ -164,83 +165,71 @@ TEST_CASE("check_for_temporal_macros")
     "#define ab __TIME __\n"
     "#define ab __TIME_ _\n";
 
-  const char temporal_at_avx_boundary[] =
+  const string_view temporal_at_avx_boundary =
     "#define alphabet abcdefghijklmnopqrstuvwxyz\n"
     "__DATE__";
 
-  CHECK(check_for_temporal_macros(time_start + 0, sizeof(time_start) - 0));
-  CHECK(!check_for_temporal_macros(time_start + 1, sizeof(time_start) - 1));
-
-  CHECK(check_for_temporal_macros(time_middle + 0, sizeof(time_middle) - 0));
-  CHECK(check_for_temporal_macros(time_middle + 1, sizeof(time_middle) - 1));
-  CHECK(check_for_temporal_macros(time_middle + 2, sizeof(time_middle) - 2));
-  CHECK(check_for_temporal_macros(time_middle + 3, sizeof(time_middle) - 3));
-  CHECK(check_for_temporal_macros(time_middle + 4, sizeof(time_middle) - 4));
-  CHECK(check_for_temporal_macros(time_middle + 5, sizeof(time_middle) - 5));
-  CHECK(check_for_temporal_macros(time_middle + 6, sizeof(time_middle) - 6));
-  CHECK(check_for_temporal_macros(time_middle + 7, sizeof(time_middle) - 7));
-
-  CHECK(check_for_temporal_macros(time_end + 0, sizeof(time_end) - 0));
-  CHECK(check_for_temporal_macros(time_end + sizeof(time_end) - 9, 9));
-  CHECK(!check_for_temporal_macros(time_end + sizeof(time_end) - 8, 8));
-
-  CHECK(check_for_temporal_macros(date_start + 0, sizeof(date_start) - 0));
-  CHECK(!check_for_temporal_macros(date_start + 1, sizeof(date_start) - 1));
-
-  CHECK(check_for_temporal_macros(date_middle + 0, sizeof(date_middle) - 0));
-  CHECK(check_for_temporal_macros(date_middle + 1, sizeof(date_middle) - 1));
-  CHECK(check_for_temporal_macros(date_middle + 2, sizeof(date_middle) - 2));
-  CHECK(check_for_temporal_macros(date_middle + 3, sizeof(date_middle) - 3));
-  CHECK(check_for_temporal_macros(date_middle + 4, sizeof(date_middle) - 4));
-  CHECK(check_for_temporal_macros(date_middle + 5, sizeof(date_middle) - 5));
-  CHECK(check_for_temporal_macros(date_middle + 6, sizeof(date_middle) - 6));
-  CHECK(check_for_temporal_macros(date_middle + 7, sizeof(date_middle) - 7));
-
-  CHECK(check_for_temporal_macros(date_end + 0, sizeof(date_end) - 0));
-  CHECK(check_for_temporal_macros(date_end + sizeof(date_end) - 9, 9));
-  CHECK(!check_for_temporal_macros(date_end + sizeof(date_end) - 8, 8));
-
-  CHECK(check_for_temporal_macros(timestamp_start + 0,
-                                  sizeof(timestamp_start) - 0));
-  CHECK(!check_for_temporal_macros(timestamp_start + 1,
-                                   sizeof(timestamp_start) - 1));
-
-  CHECK(check_for_temporal_macros(timestamp_middle + 0,
-                                  sizeof(timestamp_middle) - 0));
-  CHECK(check_for_temporal_macros(timestamp_middle + 1,
-                                  sizeof(timestamp_middle) - 1));
-  CHECK(check_for_temporal_macros(timestamp_middle + 2,
-                                  sizeof(timestamp_middle) - 2));
-  CHECK(check_for_temporal_macros(timestamp_middle + 3,
-                                  sizeof(timestamp_middle) - 3));
-  CHECK(check_for_temporal_macros(timestamp_middle + 4,
-                                  sizeof(timestamp_middle) - 4));
-  CHECK(check_for_temporal_macros(timestamp_middle + 5,
-                                  sizeof(timestamp_middle) - 5));
-  CHECK(check_for_temporal_macros(timestamp_middle + 6,
-                                  sizeof(timestamp_middle) - 6));
-  CHECK(check_for_temporal_macros(timestamp_middle + 7,
-                                  sizeof(timestamp_middle) - 7));
-
-  CHECK(
-    check_for_temporal_macros(timestamp_end + 0, sizeof(timestamp_end) - 0));
-  CHECK(
-    check_for_temporal_macros(timestamp_end + sizeof(timestamp_end) - 14, 14));
-  CHECK(
-    !check_for_temporal_macros(timestamp_end + sizeof(timestamp_end) - 13, 13));
-
-  CHECK(!check_for_temporal_macros(no_temporal + 0, sizeof(no_temporal) - 0));
-  CHECK(!check_for_temporal_macros(no_temporal + 1, sizeof(no_temporal) - 1));
-  CHECK(!check_for_temporal_macros(no_temporal + 2, sizeof(no_temporal) - 2));
-  CHECK(!check_for_temporal_macros(no_temporal + 3, sizeof(no_temporal) - 3));
-  CHECK(!check_for_temporal_macros(no_temporal + 4, sizeof(no_temporal) - 4));
-  CHECK(!check_for_temporal_macros(no_temporal + 5, sizeof(no_temporal) - 5));
-  CHECK(!check_for_temporal_macros(no_temporal + 6, sizeof(no_temporal) - 6));
-  CHECK(!check_for_temporal_macros(no_temporal + 7, sizeof(no_temporal) - 7));
+  CHECK(check_for_temporal_macros(time_start));
+  CHECK(!check_for_temporal_macros(time_start.substr(1)));
+
+  CHECK(check_for_temporal_macros(time_middle.substr(0)));
+  CHECK(check_for_temporal_macros(time_middle.substr(1)));
+  CHECK(check_for_temporal_macros(time_middle.substr(2)));
+  CHECK(check_for_temporal_macros(time_middle.substr(3)));
+  CHECK(check_for_temporal_macros(time_middle.substr(4)));
+  CHECK(check_for_temporal_macros(time_middle.substr(5)));
+  CHECK(check_for_temporal_macros(time_middle.substr(6)));
+  CHECK(check_for_temporal_macros(time_middle.substr(7)));
+
+  CHECK(check_for_temporal_macros(time_end));
+  CHECK(check_for_temporal_macros(time_end.substr(time_end.length() - 8)));
+  CHECK(!check_for_temporal_macros(time_end.substr(time_end.length() - 7)));
+
+  CHECK(check_for_temporal_macros(date_start));
+  CHECK(!check_for_temporal_macros(date_start.substr(1)));
+
+  CHECK(check_for_temporal_macros(date_middle.substr(0)));
+  CHECK(check_for_temporal_macros(date_middle.substr(1)));
+  CHECK(check_for_temporal_macros(date_middle.substr(2)));
+  CHECK(check_for_temporal_macros(date_middle.substr(3)));
+  CHECK(check_for_temporal_macros(date_middle.substr(4)));
+  CHECK(check_for_temporal_macros(date_middle.substr(5)));
+  CHECK(check_for_temporal_macros(date_middle.substr(6)));
+  CHECK(check_for_temporal_macros(date_middle.substr(7)));
+
+  CHECK(check_for_temporal_macros(date_end));
+  CHECK(check_for_temporal_macros(date_end.substr(date_end.length() - 8)));
+  CHECK(!check_for_temporal_macros(date_end.substr(date_end.length() - 7)));
+
+  CHECK(check_for_temporal_macros(timestamp_start));
+  CHECK(!check_for_temporal_macros(timestamp_start.substr(1)));
+
+  CHECK(check_for_temporal_macros(timestamp_middle));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(1)));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(2)));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(3)));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(4)));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(5)));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(6)));
+  CHECK(check_for_temporal_macros(timestamp_middle.substr(7)));
+
+  CHECK(check_for_temporal_macros(timestamp_end));
+  CHECK(check_for_temporal_macros(
+    timestamp_end.substr(timestamp_end.length() - 13)));
+  CHECK(!check_for_temporal_macros(
+    timestamp_end.substr(timestamp_end.length() - 12)));
+
+  CHECK(!check_for_temporal_macros(no_temporal.substr(0)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(1)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(2)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(3)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(4)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(5)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(6)));
+  CHECK(!check_for_temporal_macros(no_temporal.substr(7)));
 
   for (size_t i = 0; i < sizeof(temporal_at_avx_boundary) - 8; ++i) {
-    CHECK(check_for_temporal_macros(temporal_at_avx_boundary + i,
-                                    sizeof(temporal_at_avx_boundary) - i));
+    CHECK(check_for_temporal_macros(temporal_at_avx_boundary.substr(i)));
   }
 }