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
funcCallWithTempExcTest()97 void funcCallWithTempExcTest() {
98 f(5, RegularException());
99 }
100
101 // Global variable initialization test.
102 RegularException exc = RegularException();
103 RegularException *excptr = new RegularException();
104
localVariableInitTest()105 void localVariableInitTest() {
106 RegularException exc = RegularException();
107 RegularException *excptr = new RegularException();
108 }
109
110 class CtorInitializerListTest {
111 RegularException exc;
112
CtorInitializerListTest()113 CtorInitializerListTest() : exc(RegularException()) {}
114
CtorInitializerListTest(int)115 CtorInitializerListTest(int) try : exc(RegularException()) {
116 // Constructor body
117 } catch (...) {
118 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
119 RegularException();
120 }
121
122 CtorInitializerListTest(float);
123 };
124
CtorInitializerListTest(float)125 CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
126 // Constructor body
127 } catch (...) {
128 // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
129 RegularException();
130 }
131
funcReturningExceptionTest(int i)132 RegularException funcReturningExceptionTest(int i) {
133 return RegularException();
134 }
135
returnedValueTest()136 void returnedValueTest() {
137 funcReturningExceptionTest(3);
138 }
139
140 struct ClassBracedInitListTest {
ClassBracedInitListTestClassBracedInitListTest141 ClassBracedInitListTest(RegularException exc) {}
142 };
143
foo(RegularException,ClassBracedInitListTest)144 void foo(RegularException, ClassBracedInitListTest) {}
145
bracedInitListTest()146 void bracedInitListTest() {
147 RegularException exc{};
148 ClassBracedInitListTest test = {RegularException()};
149 foo({}, {RegularException()});
150 }
151
152 typedef std::exception ERROR_BASE;
153 class RegularError : public ERROR_BASE {};
154
typedefTest()155 void typedefTest() {
156 // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
157 RegularError();
158 }
159
160 struct ExceptionRAII {
ExceptionRAIIExceptionRAII161 ExceptionRAII() {}
~ExceptionRAIIExceptionRAII162 ~ExceptionRAII() {}
163 };
164
exceptionRAIITest()165 void exceptionRAIITest() {
166 ExceptionRAII E;
167 }
168