[libc++] Add test for bug that had been introduced in D98573 and fixed in D119633
authorLouis Dionne <ldionne.2@gmail.com>
Wed, 5 Oct 2022 18:03:31 +0000 (14:03 -0400)
committerLouis Dionne <ldionne.2@gmail.com>
Wed, 12 Oct 2022 19:05:04 +0000 (15:05 -0400)
Differential Revision: https://reviews.llvm.org/D135297

libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.infinite_recursion.pass.cpp [new file with mode: 0644]

diff --git a/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.infinite_recursion.pass.cpp b/libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.infinite_recursion.pass.cpp
new file mode 100644 (file)
index 0000000..f5c492f
--- /dev/null
@@ -0,0 +1,107 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <string>
+
+// Make sure basic_string::insert does not cause infinite recursion.
+// This is a regression test for a bug that had been introduced in D98573.
+
+#include <algorithm>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+struct char_ascii {
+    char char_;
+
+    char_ascii() = default;
+    char_ascii(char ch) : char_(ch) {
+        assert(ch <= 0x7f);
+    }
+};
+
+template <>
+struct std::char_traits<char_ascii> {
+    using char_type = char_ascii;
+    using int_type = typename std::char_traits<char>::int_type;
+    using off_type = typename std::char_traits<char>::off_type;
+    using pos_type = typename std::char_traits<char>::pos_type;
+    using state_type = typename std::char_traits<char>::state_type;
+
+    static void assign(char_type& r, char_type const& a) TEST_NOEXCEPT {
+        r = a;
+    }
+
+    static char_type* assign(char_type* p, std::size_t count, char_type a) {
+        std::fill(p, p + count, a);
+        return p;
+    }
+
+    static bool eq(char_type a, char_type b) TEST_NOEXCEPT {
+        return a.char_ == b.char_;
+    }
+
+    static bool lt(char_type a, char_type b) TEST_NOEXCEPT {
+        return a.char_ < b.char_;
+    }
+
+    static std::size_t length(char_type const* s) {
+        std::size_t n = 0;
+        if (s) {
+            while (s->char_)
+                ++n;
+        }
+        return n;
+    }
+
+    static const char_type* find(char_type const* p, std::size_t count, char_type const& ch) {
+        while (count > 0) {
+            if (p->char_ == ch.char_) {
+                return p;
+            } else {
+                ++p;
+                --count;
+            }
+        }
+        return nullptr;
+    }
+
+    static int compare(char_type const* s1, char_type const* s2, std::size_t count) {
+        for (std::size_t i = 0; i < count; ++i) {
+            if (s1->char_ < s2->char_)
+                return -1;
+            else if (s2->char_ < s1->char_)
+                return 1;
+        }
+        return 0;
+    }
+
+    static char_type* move(char_type* dest, char_type const* src, std::size_t count) {
+        if (src <= dest && dest < src + count) {
+            std::copy_backward(src, src + count, dest + count);
+        } else {
+            std::copy(src, src + count, dest);
+        }
+        return dest;
+    }
+
+    static char_type* copy(char_type* dest, char_type const* src, std::size_t count) {
+        return char_traits::move(dest, src, count);
+    }
+};
+
+int main(int, char**) {
+    std::basic_string<char_ascii> str;
+
+    char_ascii ch('A');
+    str.insert(str.begin(), &ch, &ch + 1);
+    assert(str.size() == 1);
+    assert(str[0].char_ == 'A');
+    return 0;
+}