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