xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/throw-keyword-missing.cpp (revision 69fb9bcde0312e672e6f2280f8662784731d79e6)
189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions
289a1d03eSRichard 
389a1d03eSRichard namespace std {
489a1d03eSRichard 
589a1d03eSRichard // std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
689a1d03eSRichard template <typename T>
789a1d03eSRichard class allocator {};
889a1d03eSRichard template <typename T>
989a1d03eSRichard class char_traits {};
1089a1d03eSRichard template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
1189a1d03eSRichard struct basic_string {
1289a1d03eSRichard   basic_string();
1389a1d03eSRichard   basic_string(const basic_string &);
1489a1d03eSRichard   // MSVC headers define two constructors instead of using optional arguments.
1589a1d03eSRichard   basic_string(const C *);
1689a1d03eSRichard   basic_string(const C *, const A &);
1789a1d03eSRichard   ~basic_string();
1889a1d03eSRichard };
1989a1d03eSRichard typedef basic_string<char> string;
2089a1d03eSRichard typedef basic_string<wchar_t> wstring;
2189a1d03eSRichard 
2289a1d03eSRichard // std::exception and std::runtime_error declaration.
2389a1d03eSRichard struct exception {
2489a1d03eSRichard   exception();
2589a1d03eSRichard   exception(const exception &other);
2689a1d03eSRichard   virtual ~exception();
2789a1d03eSRichard };
2889a1d03eSRichard 
2989a1d03eSRichard struct runtime_error : public exception {
3089a1d03eSRichard   explicit runtime_error(const std::string &what_arg);
3189a1d03eSRichard };
3289a1d03eSRichard 
3389a1d03eSRichard } // namespace std
3489a1d03eSRichard 
3589a1d03eSRichard // The usage of this class should never emit a warning.
3689a1d03eSRichard struct RegularClass {};
3789a1d03eSRichard 
3889a1d03eSRichard // Class name contains the substring "exception", in certain cases using this class should emit a warning.
3989a1d03eSRichard struct RegularException {
4089a1d03eSRichard   RegularException() {}
4189a1d03eSRichard 
4289a1d03eSRichard   // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
4389a1d03eSRichard   RegularException(int) {}
4489a1d03eSRichard };
4589a1d03eSRichard 
4689a1d03eSRichard // --------------
4789a1d03eSRichard 
4889a1d03eSRichard void stdExceptionNotTrownTest(int i) {
4989a1d03eSRichard   if (i < 0)
5089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
5189a1d03eSRichard     std::exception();
5289a1d03eSRichard 
5389a1d03eSRichard   if (i > 0)
5489a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
5589a1d03eSRichard     std::runtime_error("Unexpected argument");
5689a1d03eSRichard }
5789a1d03eSRichard 
5889a1d03eSRichard void stdExceptionThrownTest(int i) {
5989a1d03eSRichard   if (i < 0)
6089a1d03eSRichard     throw std::exception();
6189a1d03eSRichard 
6289a1d03eSRichard   if (i > 0)
6389a1d03eSRichard     throw std::runtime_error("Unexpected argument");
6489a1d03eSRichard }
6589a1d03eSRichard 
6689a1d03eSRichard void regularClassNotThrownTest(int i) {
6789a1d03eSRichard   if (i < 0)
6889a1d03eSRichard     RegularClass();
6989a1d03eSRichard }
7089a1d03eSRichard 
7189a1d03eSRichard void regularClassThrownTest(int i) {
7289a1d03eSRichard   if (i < 0)
7389a1d03eSRichard     throw RegularClass();
7489a1d03eSRichard }
7589a1d03eSRichard 
7689a1d03eSRichard void nameContainsExceptionNotThrownTest(int i) {
7789a1d03eSRichard   if (i < 0)
7889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
7989a1d03eSRichard     RegularException();
8089a1d03eSRichard 
8189a1d03eSRichard   if (i > 0)
8289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
8389a1d03eSRichard     RegularException(5);
8489a1d03eSRichard }
8589a1d03eSRichard 
8689a1d03eSRichard void nameContainsExceptionThrownTest(int i) {
8789a1d03eSRichard   if (i < 0)
8889a1d03eSRichard     throw RegularException();
8989a1d03eSRichard 
9089a1d03eSRichard   if (i > 0)
9189a1d03eSRichard     throw RegularException(5);
9289a1d03eSRichard }
9389a1d03eSRichard 
9489a1d03eSRichard template <class Exception>
9589a1d03eSRichard void f(int i, Exception excToBeThrown) {}
9689a1d03eSRichard 
9789a1d03eSRichard template <class SomeType>
9889a1d03eSRichard void templ(int i) {
9989a1d03eSRichard   if (i > 0)
10089a1d03eSRichard     SomeType();
10189a1d03eSRichard }
10289a1d03eSRichard 
10389a1d03eSRichard void funcCallWithTempExcTest() {
10489a1d03eSRichard   f(5, RegularException());
10589a1d03eSRichard 
10689a1d03eSRichard   templ<RegularException>(4);
10789a1d03eSRichard   templ<RegularClass>(4);
10889a1d03eSRichard }
10989a1d03eSRichard 
11089a1d03eSRichard // Global variable initialization test.
11189a1d03eSRichard RegularException exc = RegularException();
11289a1d03eSRichard RegularException *excptr = new RegularException();
11389a1d03eSRichard 
11489a1d03eSRichard void localVariableInitTest() {
11589a1d03eSRichard   RegularException exc = RegularException();
11689a1d03eSRichard   RegularException *excptr = new RegularException();
11789a1d03eSRichard }
11889a1d03eSRichard 
11989a1d03eSRichard class CtorInitializerListTest {
12089a1d03eSRichard   RegularException exc;
12189a1d03eSRichard   RegularException exc2{};
12289a1d03eSRichard 
12389a1d03eSRichard   CtorInitializerListTest() : exc(RegularException()) {}
12489a1d03eSRichard 
12589a1d03eSRichard   CtorInitializerListTest(int) try : exc(RegularException()) {
12689a1d03eSRichard     // Constructor body
12789a1d03eSRichard   } catch (...) {
12889a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
12989a1d03eSRichard     RegularException();
13089a1d03eSRichard   }
13189a1d03eSRichard 
13289a1d03eSRichard   CtorInitializerListTest(float);
13389a1d03eSRichard };
13489a1d03eSRichard 
13589a1d03eSRichard CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
13689a1d03eSRichard   // Constructor body
13789a1d03eSRichard } catch (...) {
13889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
13989a1d03eSRichard   RegularException();
14089a1d03eSRichard }
14189a1d03eSRichard 
142*69fb9bcdSCarlos Galvez namespace GH115055 {
143*69fb9bcdSCarlos Galvez class CtorInitializerListTest2 {
144*69fb9bcdSCarlos Galvez  public:
145*69fb9bcdSCarlos Galvez   CtorInitializerListTest2() {}
146*69fb9bcdSCarlos Galvez  private:
147*69fb9bcdSCarlos Galvez   RegularException exc{};
148*69fb9bcdSCarlos Galvez };
149*69fb9bcdSCarlos Galvez }  // namespace GH115055
150*69fb9bcdSCarlos Galvez 
15189a1d03eSRichard RegularException funcReturningExceptionTest(int i) {
15289a1d03eSRichard   return RegularException();
15389a1d03eSRichard }
15489a1d03eSRichard 
15589a1d03eSRichard void returnedValueTest() {
15689a1d03eSRichard   funcReturningExceptionTest(3);
15789a1d03eSRichard }
15889a1d03eSRichard 
15989a1d03eSRichard struct ClassBracedInitListTest {
16089a1d03eSRichard   ClassBracedInitListTest(RegularException exc) {}
16189a1d03eSRichard };
16289a1d03eSRichard 
16389a1d03eSRichard void foo(RegularException, ClassBracedInitListTest) {}
16489a1d03eSRichard 
16589a1d03eSRichard void bracedInitListTest() {
16689a1d03eSRichard   RegularException exc{};
16789a1d03eSRichard   ClassBracedInitListTest test = {RegularException()};
16889a1d03eSRichard   foo({}, {RegularException()});
16989a1d03eSRichard }
17089a1d03eSRichard 
17189a1d03eSRichard typedef std::exception ERROR_BASE;
17289a1d03eSRichard class RegularError : public ERROR_BASE {};
17389a1d03eSRichard 
17489a1d03eSRichard void typedefTest() {
17589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
17689a1d03eSRichard   RegularError();
17789a1d03eSRichard }
17889a1d03eSRichard 
17989a1d03eSRichard struct ExceptionRAII {
18089a1d03eSRichard   ExceptionRAII() {}
18189a1d03eSRichard   ~ExceptionRAII() {}
18289a1d03eSRichard };
18389a1d03eSRichard 
18489a1d03eSRichard void exceptionRAIITest() {
18589a1d03eSRichard   ExceptionRAII E;
18689a1d03eSRichard }
18789a1d03eSRichard 
18889a1d03eSRichard namespace std {
18989a1d03eSRichard typedef decltype(sizeof(void*)) size_t;
19089a1d03eSRichard }
19189a1d03eSRichard 
19289a1d03eSRichard void* operator new(std::size_t, void*);
19389a1d03eSRichard 
19489a1d03eSRichard void placeMentNewTest() {
19589a1d03eSRichard   alignas(RegularException) unsigned char expr[sizeof(RegularException)];
19689a1d03eSRichard   new (expr) RegularException{};
19789a1d03eSRichard }
198