// 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 class allocator {}; template class char_traits {}; template , typename A = std::allocator> 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 string; typedef basic_string 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 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; }