1// RUN: %check_clang_tidy %s abseil-str-cat-append %t
2
3typedef unsigned __INT16_TYPE__ char16;
4typedef unsigned __INT32_TYPE__ char32;
5typedef __SIZE_TYPE__ size;
6
7namespace std {
8template <typename T>
9class allocator {};
10template <typename T>
11class char_traits {};
12template <typename C, typename T, typename A>
13struct basic_string {
14 typedef basic_string<C, T, A> _Type;
15 basic_string();
16 basic_string(const C* p, const A& a = A());
17
18 const C* c_str() const;
19 const C* data() const;
20
21 _Type& append(const C* s);
22 _Type& append(const C* s, size n);
23 _Type& assign(const C* s);
24 _Type& assign(const C* s, size n);
25
26 int compare(const _Type&) const;
27 int compare(const C* s) const;
28 int compare(size pos, size len, const _Type&) const;
29 int compare(size pos, size len, const C* s) const;
30
31 size find(const _Type& str, size pos = 0) const;
32 size find(const C* s, size pos = 0) const;
33 size find(const C* s, size pos, size n) const;
34
35 _Type& insert(size pos, const _Type& str);
36 _Type& insert(size pos, const C* s);
37 _Type& insert(size pos, const C* s, size n);
38
39 _Type& operator+=(const _Type& str);
40 _Type& operator+=(const C* s);
41 _Type& operator=(const _Type& str);
42 _Type& operator=(const C* s);
43};
44
45typedef basic_string<char, std::char_traits<char>, std::allocator<char>> string;
46typedef basic_string<wchar_t, std::char_traits<wchar_t>,
47 std::allocator<wchar_t>>
48 wstring;
49typedef basic_string<char16, std::char_traits<char16>, std::allocator<char16>>
50 u16string;
51typedef basic_string<char32, std::char_traits<char32>, std::allocator<char32>>
52 u32string;
53} // namespace std
54
55std::string operator+(const std::string&, const std::string&);
56std::string operator+(const std::string&, const char*);
57std::string operator+(const char*, const std::string&);
58
59bool operator==(const std::string&, const std::string&);
60bool operator==(const std::string&, const char*);
61bool operator==(const char*, const std::string&);
62
63namespace llvm {
64struct StringRef {
65 StringRef(const char* p);
66 StringRef(const std::string&);
67};
68} // namespace llvm
69
70namespace absl {
71
72struct AlphaNum {
73 AlphaNum(int i);
74 AlphaNum(double f);
75 AlphaNum(const char* c_str);
76 AlphaNum(const std::string& str);
77
78 private:
79 AlphaNum(const AlphaNum&);
80 AlphaNum& operator=(const AlphaNum&);
81};
82
83std::string StrCat(const AlphaNum& A);
84std::string StrCat(const AlphaNum& A, const AlphaNum& B);
85
86template <typename A>
87void Foo(A& a) {
88 a = StrCat(a);
89}
90
91void Bar() {
92 std::string A, B;
93 Foo<std::string>(a&: A);
94
95 std::string C = StrCat(A);
96 A = StrCat(A);
97 // CHECK-MESSAGES: [[@LINE-1]]:3: warning: call to 'absl::StrCat' has no effect
98 A = StrCat(A, B);
99// CHECK-MESSAGES: [[@LINE-1]]:3: warning: call 'absl::StrAppend' instead of 'absl::StrCat' when appending to a string to avoid a performance penalty
100// CHECK-FIXES: {{^}} absl::StrAppend(&A, B);
101 B = StrCat(A, B);
102
103#define M(X) X = StrCat(X, A)
104 M(B);
105// CHECK-MESSAGES: [[@LINE-1]]:5: warning: call 'absl::StrAppend' instead of 'absl::StrCat' when appending to a string to avoid a performance penalty
106// CHECK-FIXES: #define M(X) X = StrCat(X, A)
107}
108
109void Regression_SelfAppend() {
110 std::string A;
111 A = StrCat(A, B: A);
112}
113
114} // namespace absl
115
116void OutsideAbsl() {
117 std::string A, B;
118 A = absl::StrCat(A, B);
119// CHECK-MESSAGES: [[@LINE-1]]:3: warning: call 'absl::StrAppend' instead of 'absl::StrCat' when appending to a string to avoid a performance penalty
120// CHECK-FIXES: {{^}} absl::StrAppend(&A, B);
121}
122
123void OutsideUsingAbsl() {
124 std::string A, B;
125 using absl::StrCat;
126 A = StrCat(A, B);
127// CHECK-MESSAGES: [[@LINE-1]]:3: warning: call 'absl::StrAppend' instead of 'absl::StrCat' when appending to a string to avoid a performance penalty
128// CHECK-FIXES: {{^}} absl::StrAppend(&A, B);
129}
130

source code of clang-tools-extra/test/clang-tidy/checkers/abseil/str-cat-append.cpp