summaryrefslogtreecommitdiff
path: root/clang-tools-extra/test/clang-tidy/bugprone-throw-keyword-missing.cpp
blob: 93ecf06ce97357f846e8c9b2dcb7f9f3a28e22b1 (plain)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions

namespace std {

// std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
template <typename T>
class allocator {};
template <typename T>
class char_traits {};
template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
struct basic_string {
  basic_string();
  basic_string(const basic_string &);
  // MSVC headers define two constructors instead of using optional arguments.
  basic_string(const C *);
  basic_string(const C *, const A &);
  ~basic_string();
};
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;

// std::exception and std::runtime_error declaration.
struct exception {
  exception();
  exception(const exception &other);
  virtual ~exception();
};

struct runtime_error : public exception {
  explicit runtime_error(const std::string &what_arg);
};

} // namespace std

// The usage of this class should never emit a warning.
struct RegularClass {};

// Class name contains the substring "exception", in certain cases using this class should emit a warning.
struct RegularException {
  RegularException() {}

  // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
  RegularException(int) {}
};

// --------------

void stdExceptionNotTrownTest(int i) {
  if (i < 0)
    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
    std::exception();

  if (i > 0)
    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
    std::runtime_error("Unexpected argument");
}

void stdExceptionThrownTest(int i) {
  if (i < 0)
    throw std::exception();

  if (i > 0)
    throw std::runtime_error("Unexpected argument");
}

void regularClassNotThrownTest(int i) {
  if (i < 0)
    RegularClass();
}

void regularClassThrownTest(int i) {
  if (i < 0)
    throw RegularClass();
}

void nameContainsExceptionNotThrownTest(int i) {
  if (i < 0)
    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
    RegularException();

  if (i > 0)
    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
    RegularException(5);
}

void nameContainsExceptionThrownTest(int i) {
  if (i < 0)
    throw RegularException();

  if (i > 0)
    throw RegularException(5);
}

template <class Exception>
void f(int i, Exception excToBeThrown) {}

void funcCallWithTempExcTest() {
  f(5, RegularException());
}

// Global variable initilization test.
RegularException exc = RegularException();
RegularException *excptr = new RegularException();

void localVariableInitTest() {
  RegularException exc = RegularException();
  RegularException *excptr = new RegularException();
}

class CtorInitializerListTest {
  RegularException exc;

  CtorInitializerListTest() : exc(RegularException()) {}

  CtorInitializerListTest(int) try : exc(RegularException()) {
    // Constructor body
  } catch (...) {
    // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
    RegularException();
  }

  CtorInitializerListTest(float);
};

CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
  // Constructor body
} catch (...) {
  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
  RegularException();
}

RegularException funcReturningExceptionTest(int i) {
  return RegularException();
}

void returnedValueTest() {
  funcReturningExceptionTest(3);
}

struct ClassBracedInitListTest {
  ClassBracedInitListTest(RegularException exc) {}
};

void foo(RegularException, ClassBracedInitListTest) {}

void bracedInitListTest() {
  RegularException exc{};
  ClassBracedInitListTest test = {RegularException()};
  foo({}, {RegularException()});
}

typedef std::exception ERROR_BASE;
class RegularError : public ERROR_BASE {};

void typedefTest() {
  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
  RegularError();
}

struct ExceptionRAII {
  ExceptionRAII() {}
  ~ExceptionRAII() {}
};

void exceptionRAIITest() {
  ExceptionRAII E;
}