| // RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions |
| |
| namespace std { |
| |
| // std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp). |
| template <typename T> |
| class allocator {}; |
| template <typename T> |
| class char_traits {}; |
| template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>> |
| struct basic_string { |
| basic_string(); |
| basic_string(const basic_string &); |
| // MSVC headers define two constructors instead of using optional arguments. |
| basic_string(const C *); |
| basic_string(const C *, const A &); |
| ~basic_string(); |
| }; |
| typedef basic_string<char> string; |
| typedef basic_string<wchar_t> wstring; |
| |
| // std::exception and std::runtime_error declaration. |
| struct exception { |
| exception(); |
| exception(const exception &other); |
| virtual ~exception(); |
| }; |
| |
| struct runtime_error : public exception { |
| explicit runtime_error(const std::string &what_arg); |
| }; |
| |
| } // namespace std |
| |
| // The usage of this class should never emit a warning. |
| struct RegularClass {}; |
| |
| // Class name contains the substring "exception", in certain cases using this class should emit a warning. |
| struct RegularException { |
| RegularException() {} |
| |
| // Constructors with a single argument are treated differently (cxxFunctionalCastExpr). |
| RegularException(int) {} |
| }; |
| |
| // -------------- |
| |
| void stdExceptionNotTrownTest(int i) { |
| if (i < 0) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing] |
| std::exception(); |
| |
| if (i > 0) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception |
| std::runtime_error("Unexpected argument"); |
| } |
| |
| void stdExceptionThrownTest(int i) { |
| if (i < 0) |
| throw std::exception(); |
| |
| if (i > 0) |
| throw std::runtime_error("Unexpected argument"); |
| } |
| |
| void regularClassNotThrownTest(int i) { |
| if (i < 0) |
| RegularClass(); |
| } |
| |
| void regularClassThrownTest(int i) { |
| if (i < 0) |
| throw RegularClass(); |
| } |
| |
| void nameContainsExceptionNotThrownTest(int i) { |
| if (i < 0) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception |
| RegularException(); |
| |
| if (i > 0) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception |
| RegularException(5); |
| } |
| |
| void nameContainsExceptionThrownTest(int i) { |
| if (i < 0) |
| throw RegularException(); |
| |
| if (i > 0) |
| throw RegularException(5); |
| } |
| |
| template <class Exception> |
| void f(int i, Exception excToBeThrown) {} |
| |
| void funcCallWithTempExcTest() { |
| f(5, RegularException()); |
| } |
| |
| // Global variable initilization test. |
| RegularException exc = RegularException(); |
| RegularException *excptr = new RegularException(); |
| |
| void localVariableInitTest() { |
| RegularException exc = RegularException(); |
| RegularException *excptr = new RegularException(); |
| } |
| |
| class CtorInitializerListTest { |
| RegularException exc; |
| |
| CtorInitializerListTest() : exc(RegularException()) {} |
| |
| CtorInitializerListTest(int) try : exc(RegularException()) { |
| // Constructor body |
| } catch (...) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception |
| RegularException(); |
| } |
| |
| CtorInitializerListTest(float); |
| }; |
| |
| CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) { |
| // Constructor body |
| } catch (...) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception |
| RegularException(); |
| } |
| |
| RegularException funcReturningExceptionTest(int i) { |
| return RegularException(); |
| } |
| |
| void returnedValueTest() { |
| funcReturningExceptionTest(3); |
| } |
| |
| struct ClassBracedInitListTest { |
| ClassBracedInitListTest(RegularException exc) {} |
| }; |
| |
| void foo(RegularException, ClassBracedInitListTest) {} |
| |
| void bracedInitListTest() { |
| RegularException exc{}; |
| ClassBracedInitListTest test = {RegularException()}; |
| foo({}, {RegularException()}); |
| } |
| |
| typedef std::exception ERROR_BASE; |
| class RegularError : public ERROR_BASE {}; |
| |
| void typedefTest() { |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception |
| RegularError(); |
| } |
| |
| struct ExceptionRAII { |
| ExceptionRAII() {} |
| ~ExceptionRAII() {} |
| }; |
| |
| void exceptionRAIITest() { |
| ExceptionRAII E; |
| } |