File: redundant-strcat-calls.cpp

package info (click to toggle)
llvm-toolchain-17 1%3A17.0.6-22
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,799,624 kB
  • sloc: cpp: 6,428,607; ansic: 1,383,196; asm: 793,408; python: 223,504; objc: 75,364; f90: 60,502; lisp: 33,869; pascal: 15,282; sh: 9,684; perl: 7,453; ml: 4,937; awk: 3,523; makefile: 2,889; javascript: 2,149; xml: 888; fortran: 619; cs: 573
file content (113 lines) | stat: -rw-r--r-- 4,127 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// RUN: %check_clang_tidy %s abseil-redundant-strcat-calls %t -- -- -isystem %clang_tidy_headers
#include <string>

int strlen(const char *);

namespace absl {

class string_view {
 public:
  typedef std::char_traits<char> traits_type;

  string_view();
  string_view(const char *);
  string_view(const std::string &);
  string_view(const char *, int);
  string_view(string_view, int);

  template <typename A>
  explicit operator std::basic_string<char, traits_type, A>() const;

  const char *data() const;
  int size() const;
  int length() const;
};

bool operator==(string_view A, string_view B);

struct AlphaNum {
  AlphaNum(int i);
  AlphaNum(double f);
  AlphaNum(const char *c_str);
  AlphaNum(const std::string &str);
  AlphaNum(const string_view &pc);

 private:
  AlphaNum(const AlphaNum &);
  AlphaNum &operator=(const AlphaNum &);
};

std::string StrCat();
std::string StrCat(const AlphaNum &A);
std::string StrCat(const AlphaNum &A, const AlphaNum &B);
std::string StrCat(const AlphaNum &A, const AlphaNum &B, const AlphaNum &C);
std::string StrCat(const AlphaNum &A, const AlphaNum &B, const AlphaNum &C,
                   const AlphaNum &D);

// Support 5 or more arguments
template <typename... AV>
std::string StrCat(const AlphaNum &A, const AlphaNum &B, const AlphaNum &C,
              const AlphaNum &D, const AlphaNum &E, const AV &... args);

void StrAppend(std::string *Dest, const AlphaNum &A);
void StrAppend(std::string *Dest, const AlphaNum &A, const AlphaNum &B);
void StrAppend(std::string *Dest, const AlphaNum &A, const AlphaNum &B,
                    const AlphaNum &C);
void StrAppend(std::string *Dest, const AlphaNum &A, const AlphaNum &B,
                    const AlphaNum &C, const AlphaNum &D);

// Support 5 or more arguments
template <typename... AV>
void StrAppend(std::string *Dest, const AlphaNum &A, const AlphaNum &B,
               const AlphaNum &C, const AlphaNum &D, const AlphaNum &E,
               const AV &... args);

}  // namespace absl

using absl::AlphaNum;
using absl::StrAppend;
using absl::StrCat;

void Positives() {
  std::string S = StrCat(1, StrCat("A", StrCat(1.1)));
  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
  // CHECK-FIXES: string S = StrCat(1, "A", 1.1);

  S = StrCat(StrCat(StrCat(StrCat(StrCat(1)))));
  // CHECK-MESSAGES: [[@LINE-1]]:7: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
  // CHECK-FIXES: S = StrCat(1);

  // TODO: should trigger. The issue here is that in the current
  // implementation we ignore any StrCat with StrCat ancestors. Therefore
  // inserting anything in between calls will disable triggering the deepest
  // ones.
  // s = StrCat(Identity(StrCat(StrCat(1, 2), StrCat(3, 4))));

  StrAppend(&S, 001, StrCat(1, 2, "3"), StrCat("FOO"));
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
  // CHECK-FIXES: StrAppend(&S, 001, 1, 2, "3", "FOO");

  StrAppend(&S, 001, StrCat(StrCat(1, 2), "3"), StrCat("FOO"));
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
  // CHECK-FIXES: StrAppend(&S, 001, 1, 2, "3", "FOO");

  // Too many args. Ignore for now.
  S = StrCat(1, 2, StrCat(3, 4, 5, 6, 7), 8, 9, 10,
             StrCat(11, 12, 13, 14, 15, 16, 17, 18), 19, 20, 21, 22, 23, 24, 25,
             26, 27);
  // CHECK-MESSAGES: :[[@LINE-3]]:7: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
  StrAppend(&S, StrCat(1, 2, 3, 4, 5), StrCat(6, 7, 8, 9, 10));
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
  // CHECK-FIXES: StrAppend(&S, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

  StrCat(1, StrCat());
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: multiple calls to 'absl::StrCat' can be flattened into a single call
}

void Negatives() {
  // One arg. It is used for conversion. Ignore.
  std::string S = StrCat(1);

#define A_MACRO(x, y, z) StrCat(x, y, z)
  S = A_MACRO(1, 2, StrCat("A", "B"));
}