| 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(i: 5, excToBeThrown: RegularException()); |
| 105 | |
| 106 | templ<RegularException>(i: 4); |
| 107 | templ<RegularClass>(i: 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(i: 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 | |