forked from OSchip/llvm-project
157 lines
4.7 KiB
C++
157 lines
4.7 KiB
C++
// RUN: %check_clang_tidy %s misc-throw-by-value-catch-by-reference %t -- -- -std=c++11 -fcxx-exceptions
|
|
|
|
|
|
class logic_error {
|
|
public:
|
|
logic_error(const char *message) {}
|
|
};
|
|
|
|
typedef logic_error *logic_ptr;
|
|
typedef logic_ptr logic_double_typedef;
|
|
|
|
int lastException;
|
|
|
|
template <class T> struct remove_reference { typedef T type; };
|
|
template <class T> struct remove_reference<T &> { typedef T type; };
|
|
template <class T> struct remove_reference<T &&> { typedef T type; };
|
|
|
|
template <typename T> typename remove_reference<T>::type &&move(T &&arg) {
|
|
return static_cast<typename remove_reference<T>::type &&>(arg);
|
|
}
|
|
|
|
logic_error CreateException() { return logic_error("created"); }
|
|
|
|
void testThrowFunc() {
|
|
throw new logic_error("by pointer");
|
|
// 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]
|
|
logic_ptr tmp = new logic_error("by pointer");
|
|
throw tmp;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
|
|
// 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]
|
|
throw logic_error("by value");
|
|
auto *literal = "test";
|
|
throw logic_error(literal);
|
|
throw "test string literal";
|
|
throw L"throw wide string literal";
|
|
const char *characters = 0;
|
|
throw characters;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
|
|
// 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]
|
|
logic_error lvalue("lvalue");
|
|
throw lvalue;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
|
|
|
|
throw move(lvalue);
|
|
int &ex = lastException;
|
|
throw ex;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
|
|
throw CreateException();
|
|
}
|
|
|
|
void throwReferenceFunc(logic_error &ref) { throw ref; }
|
|
|
|
void catchByPointer() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (logic_error *e) {
|
|
// 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]
|
|
}
|
|
}
|
|
|
|
void catchByValue() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (logic_error e) {
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: catch handler catches by value; should catch by reference instead [misc-throw-by-value-catch-by-reference]
|
|
}
|
|
}
|
|
|
|
void catchByReference() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (logic_error &e) {
|
|
}
|
|
}
|
|
|
|
void catchByConstReference() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (const logic_error &e) {
|
|
}
|
|
}
|
|
|
|
void catchTypedef() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (logic_ptr) {
|
|
// 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]
|
|
}
|
|
}
|
|
|
|
void catchAll() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (...) {
|
|
}
|
|
}
|
|
|
|
void catchLiteral() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (const char *) {
|
|
} catch (const wchar_t *) {
|
|
// disabled for now until it is clear
|
|
// how to enable them in the test
|
|
//} catch (const char16_t*) {
|
|
//} catch (const char32_t*) {
|
|
}
|
|
}
|
|
|
|
// catching fundamentals should not warn
|
|
void catchFundamental() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (int) {
|
|
} catch (double) {
|
|
} catch (unsigned long) {
|
|
}
|
|
}
|
|
|
|
struct TrivialType {
|
|
double x;
|
|
double y;
|
|
};
|
|
|
|
void catchTrivial() {
|
|
try {
|
|
testThrowFunc();
|
|
} catch (TrivialType) {
|
|
}
|
|
}
|
|
|
|
typedef logic_error &fine;
|
|
void additionalTests() {
|
|
try {
|
|
} catch (int i) { // ok
|
|
throw i; // ok
|
|
} catch (fine e) { // ok
|
|
throw e; // ok
|
|
} catch (logic_error *e) {
|
|
// 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]
|
|
throw e; // ok, despite throwing a pointer
|
|
} catch (...) { // ok
|
|
throw; // ok
|
|
}
|
|
}
|
|
|
|
struct S {};
|
|
|
|
S &returnByReference();
|
|
S returnByValue();
|
|
|
|
void f() {
|
|
throw returnByReference(); // Should diagnose
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: throw expression should throw anonymous temporary values instead [misc-throw-by-value-catch-by-reference]
|
|
throw returnByValue(); // Should not diagnose
|
|
}
|