1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// <string>
10
11// Make sure basic_string::insert does not cause infinite recursion.
12// This is a regression test for a bug that had been introduced in D98573.
13
14#include <algorithm>
15#include <cassert>
16#include <string>
17
18#include "test_macros.h"
19#include "asan_testing.h"
20
21struct char_ascii {
22 char char_;
23
24 char_ascii() = default;
25 char_ascii(char ch) : char_(ch) { assert(ch <= 0x7f); }
26};
27
28template <>
29struct std::char_traits<char_ascii> {
30 using char_type = char_ascii;
31 using int_type = typename std::char_traits<char>::int_type;
32 using off_type = typename std::char_traits<char>::off_type;
33 using pos_type = typename std::char_traits<char>::pos_type;
34 using state_type = typename std::char_traits<char>::state_type;
35
36 static void assign(char_type& r, char_type const& a) TEST_NOEXCEPT { r = a; }
37
38 static char_type* assign(char_type* p, std::size_t count, char_type a) {
39 std::fill(p, p + count, a);
40 return p;
41 }
42
43 static bool eq(char_type a, char_type b) TEST_NOEXCEPT { return a.char_ == b.char_; }
44
45 static bool lt(char_type a, char_type b) TEST_NOEXCEPT { return a.char_ < b.char_; }
46
47 static std::size_t length(char_type const* s) {
48 std::size_t n = 0;
49 if (s) {
50 while (s->char_)
51 ++n;
52 }
53 return n;
54 }
55
56 static const char_type* find(char_type const* p, std::size_t count, char_type const& ch) {
57 while (count > 0) {
58 if (p->char_ == ch.char_) {
59 return p;
60 } else {
61 ++p;
62 --count;
63 }
64 }
65 return nullptr;
66 }
67
68 static int compare(char_type const* s1, char_type const* s2, std::size_t count) {
69 for (std::size_t i = 0; i < count; ++i) {
70 if (s1->char_ < s2->char_)
71 return -1;
72 else if (s2->char_ < s1->char_)
73 return 1;
74 }
75 return 0;
76 }
77
78 static char_type* move(char_type* dest, char_type const* src, std::size_t count) {
79 if (src <= dest && dest < src + count) {
80 std::copy_backward(src, src + count, dest + count);
81 } else {
82 std::copy(src, src + count, dest);
83 }
84 return dest;
85 }
86
87 static char_type* copy(char_type* dest, char_type const* src, std::size_t count) {
88 return char_traits::move(dest, src, count);
89 }
90};
91
92int main(int, char**) {
93 std::basic_string<char_ascii> str;
94
95 char_ascii ch('A');
96 str.insert(p: str.begin(), beg: &ch, end: &ch + 1);
97 assert(str.size() == 1);
98 assert(str[0].char_ == 'A');
99 LIBCPP_ASSERT(is_string_asan_correct(str));
100 return 0;
101}
102

source code of libcxx/test/std/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.infinite_recursion.pass.cpp