xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/throw-keyword-missing.cpp (revision 69fb9bcde0312e672e6f2280f8662784731d79e6)
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 {
40   RegularException() {}
41 
42   // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
43   RegularException(int) {}
44 };
45 
46 // --------------
47 
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 
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 
66 void regularClassNotThrownTest(int i) {
67   if (i < 0)
68     RegularClass();
69 }
70 
71 void regularClassThrownTest(int i) {
72   if (i < 0)
73     throw RegularClass();
74 }
75 
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 
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>
95 void f(int i, Exception excToBeThrown) {}
96 
97 template <class SomeType>
98 void templ(int i) {
99   if (i > 0)
100     SomeType();
101 }
102 
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 
114 void localVariableInitTest() {
115   RegularException exc = RegularException();
116   RegularException *excptr = new RegularException();
117 }
118 
119 class CtorInitializerListTest {
120   RegularException exc;
121   RegularException exc2{};
122 
123   CtorInitializerListTest() : exc(RegularException()) {}
124 
125   CtorInitializerListTest(int) try : exc(RegularException()) {
126     // Constructor body
127   } catch (...) {
128     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
129     RegularException();
130   }
131 
132   CtorInitializerListTest(float);
133 };
134 
135 CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
136   // Constructor body
137 } catch (...) {
138   // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
139   RegularException();
140 }
141 
142 namespace GH115055 {
143 class CtorInitializerListTest2 {
144  public:
145   CtorInitializerListTest2() {}
146  private:
147   RegularException exc{};
148 };
149 }  // namespace GH115055
150 
151 RegularException funcReturningExceptionTest(int i) {
152   return RegularException();
153 }
154 
155 void returnedValueTest() {
156   funcReturningExceptionTest(3);
157 }
158 
159 struct ClassBracedInitListTest {
160   ClassBracedInitListTest(RegularException exc) {}
161 };
162 
163 void foo(RegularException, ClassBracedInitListTest) {}
164 
165 void bracedInitListTest() {
166   RegularException exc{};
167   ClassBracedInitListTest test = {RegularException()};
168   foo({}, {RegularException()});
169 }
170 
171 typedef std::exception ERROR_BASE;
172 class RegularError : public ERROR_BASE {};
173 
174 void typedefTest() {
175   // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
176   RegularError();
177 }
178 
179 struct ExceptionRAII {
180   ExceptionRAII() {}
181   ~ExceptionRAII() {}
182 };
183 
184 void exceptionRAIITest() {
185   ExceptionRAII E;
186 }
187 
188 namespace std {
189 typedef decltype(sizeof(void*)) size_t;
190 }
191 
192 void* operator new(std::size_t, void*);
193 
194 void placeMentNewTest() {
195   alignas(RegularException) unsigned char expr[sizeof(RegularException)];
196   new (expr) RegularException{};
197 }
198