157 lines · cpp
1// RUN: %check_clang_tidy %s misc-throw-by-value-catch-by-reference %t -- -- -fcxx-exceptions2 3 4class logic_error {5public:6 logic_error(const char *message) {}7};8 9typedef logic_error *logic_ptr;10typedef logic_ptr logic_double_typedef;11 12int lastException;13 14template <class T> struct remove_reference { typedef T type; };15template <class T> struct remove_reference<T &> { typedef T type; };16template <class T> struct remove_reference<T &&> { typedef T type; };17 18template <typename T> typename remove_reference<T>::type &&move(T &&arg) {19 return static_cast<typename remove_reference<T>::type &&>(arg);20}21 22logic_error CreateException() { return logic_error("created"); }23 24void testThrowFunc() {25 throw new logic_error("by pointer");26 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]27 logic_ptr tmp = new logic_error("by pointer");28 throw tmp;29 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]30 // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]31 throw logic_error("by value");32 auto *literal = "test";33 throw logic_error(literal);34 throw "test string literal";35 throw L"throw wide string literal";36 const char *characters = 0;37 throw characters;38 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]39 // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: throw expression throws a pointer; it should throw a non-pointer value instead [misc-throw-by-value-catch-by-reference]40 logic_error lvalue("lvalue");41 throw lvalue;42 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]43 44 throw move(lvalue);45 int &ex = lastException;46 throw ex;47 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]48 throw CreateException();49}50 51void throwReferenceFunc(logic_error &ref) { throw ref; }52 53void catchByPointer() {54 try {55 testThrowFunc();56 } catch (logic_error *e) {57 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]58 }59}60 61void catchByValue() {62 try {63 testThrowFunc();64 } catch (logic_error e) {65 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches by value; should catch by reference instead [misc-throw-by-value-catch-by-reference]66 }67}68 69void catchByReference() {70 try {71 testThrowFunc();72 } catch (logic_error &e) {73 }74}75 76void catchByConstReference() {77 try {78 testThrowFunc();79 } catch (const logic_error &e) {80 }81}82 83void catchTypedef() {84 try {85 testThrowFunc();86 } catch (logic_ptr) {87 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]88 }89}90 91void catchAll() {92 try {93 testThrowFunc();94 } catch (...) {95 }96}97 98void catchLiteral() {99 try {100 testThrowFunc();101 } catch (const char *) {102 } catch (const wchar_t *) {103 // disabled for now until it is clear104 // how to enable them in the test105 //} catch (const char16_t*) {106 //} catch (const char32_t*) {107 }108}109 110// catching fundamentals should not warn111void catchFundamental() {112 try {113 testThrowFunc();114 } catch (int) {115 } catch (double) {116 } catch (unsigned long) {117 }118}119 120struct TrivialType {121 double x;122 double y;123};124 125void catchTrivial() {126 try {127 testThrowFunc();128 } catch (TrivialType) {129 }130}131 132typedef logic_error &fine;133void additionalTests() {134 try {135 } catch (int i) { // ok136 throw i; // ok137 } catch (fine e) { // ok138 throw e; // ok139 } catch (logic_error *e) {140 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches a pointer value; should throw a non-pointer value and catch by reference instead [misc-throw-by-value-catch-by-reference]141 throw e; // ok, despite throwing a pointer142 } catch (...) { // ok143 throw; // ok144 }145}146 147struct S {};148 149S &returnByReference();150S returnByValue();151 152void f() {153 throw returnByReference(); // Should diagnose154 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]155 throw returnByValue(); // Should not diagnose156}157