1 // RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions
2
3 namespace std {
4
5 // std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
6 template <typename T>
7 class allocator {};
8 template <typename T>
9 class char_traits {};
10 template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
11 struct basic_string {
12 basic_string();
13 basic_string(const basic_string &);
14 // MSVC headers define two constructors instead of using optional arguments.
15 basic_string(const C *);
16 basic_string(const C *, const A &);
17 ~basic_string();
18 };
19 typedef basic_string<char> string;
20 typedef basic_string<wchar_t> wstring;
21
22 // std::exception and std::runtime_error declaration.
23 struct exception {
24 exception();
25 exception(const exception &other);
26 virtual ~exception();
27 };
28
29 struct runtime_error : public exception {
30 explicit runtime_error(const std::string &what_arg);
31 };
32
33 } // namespace std
34
35 // The usage of this class should never emit a warning.
36 struct RegularClass {};
37
38 // Class name contains the substring "exception", in certain cases using this class should emit a warning.
39 struct RegularException {
RegularExceptionRegularException40 RegularException() {}
41
42 // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
RegularExceptionRegularException43 RegularException(int) {}
44 };
45
46 // --------------
47
stdExceptionNotTrownTest(int i)48 void stdExceptionNotTrownTest(int i) {
49 if (i < 0)
50 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
51 std::exception();
52
53 if (i > 0)
54 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
55 std::runtime_error("Unexpected argument");
56 }
57
stdExceptionThrownTest(int i)58 void stdExceptionThrownTest(int i) {
59 if (i < 0)
60 throw std::exception();
61
62 if (i > 0)
63 throw std::runtime_error("Unexpected argument");
64 }
65
regularClassNotThrownTest(int i)66 void regularClassNotThrownTest(int i) {
67 if (i < 0)
68 RegularClass();
69 }
70
regularClassThrownTest(int i)71 void regularClassThrownTest(int i) {
72 if (i < 0)
73 throw RegularClass();
74 }
75
nameContainsExceptionNotThrownTest(int i)76 void nameContainsExceptionNotThrownTest(int i) {
77 if (i < 0)
78 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
79 RegularException();
80
81 if (i > 0)
82 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
83 RegularException(5);
84 }
85
nameContainsExceptionThrownTest(int i)86 void nameContainsExceptionThrownTest(int i) {
87 if (i < 0)
88 throw RegularException();
89
90 if (i > 0)
91 throw RegularException(5);
92 }
93
94 template <class Exception>
f(int i,Exception excToBeThrown)95 void f(int i, Exception excToBeThrown) {}
96
97 template <class SomeType>
templ(int i)98 void templ(int i) {
99 if (i > 0)
100 SomeType();
101 }
102
funcCallWithTempExcTest()103 void funcCallWithTempExcTest() {
104 f(5, RegularException());
105
106 templ<RegularException>(4);
107 templ<RegularClass>(4);
108 }
109
110 // Global variable initialization test.
111 RegularException exc = RegularException();
112 RegularException *excptr = new RegularException();
113
localVariableInitTest()114 void localVariableInitTest() {
115 RegularException exc = RegularException();
116 RegularException *excptr = new RegularException();
117 }
118
119 class CtorInitializerListTest {
120 RegularException exc;
121
CtorInitializerListTest()122 CtorInitializerListTest() : exc(RegularException()) {}
123
CtorInitializerListTest(int)124 CtorInitializerListTest(int) try : exc(RegularException()) {
125 // Constructor body
126 } catch (...) {
127 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
128 RegularException();
129 }
130
131 CtorInitializerListTest(float);
132 };
133
CtorInitializerListTest(float)134 CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
135 // Constructor body
136 } catch (...) {
137 // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
138 RegularException();
139 }
140
funcReturningExceptionTest(int i)141 RegularException funcReturningExceptionTest(int i) {
142 return RegularException();
143 }
144
returnedValueTest()145 void returnedValueTest() {
146 funcReturningExceptionTest(3);
147 }
148
149 struct ClassBracedInitListTest {
ClassBracedInitListTestClassBracedInitListTest150 ClassBracedInitListTest(RegularException exc) {}
151 };
152
foo(RegularException,ClassBracedInitListTest)153 void foo(RegularException, ClassBracedInitListTest) {}
154
bracedInitListTest()155 void bracedInitListTest() {
156 RegularException exc{};
157 ClassBracedInitListTest test = {RegularException()};
158 foo({}, {RegularException()});
159 }
160
161 typedef std::exception ERROR_BASE;
162 class RegularError : public ERROR_BASE {};
163
typedefTest()164 void typedefTest() {
165 // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
166 RegularError();
167 }
168
169 struct ExceptionRAII {
ExceptionRAIIExceptionRAII170 ExceptionRAII() {}
~ExceptionRAIIExceptionRAII171 ~ExceptionRAII() {}
172 };
173
exceptionRAIITest()174 void exceptionRAIITest() {
175 ExceptionRAII E;
176 }
177