brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.2 KiB · b5e405a Raw
285 lines · cpp
1// RUN: %check_clang_tidy %s hicpp-exception-baseclass %t -- -- -fcxx-exceptions2 3namespace std {4class exception {};5class invalid_argument : public exception {};6} // namespace std7 8class derived_exception : public std::exception {};9class deep_hierarchy : public derived_exception {};10class non_derived_exception {};11class terrible_idea : public non_derived_exception, public derived_exception {};12 13// FIXME: More complicated kinds of inheritance should be checked later, but there is14// currently no way use ASTMatchers for this kind of task.15#if 016class bad_inheritance : private std::exception {};17class no_good_inheritance : protected std::exception {};18class really_creative : public non_derived_exception, private std::exception {};19#endif20 21void problematic() {22  try {23    throw int(42);24    // CHECK-NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'25  } catch (int e) {26  }27  throw int(42);28  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'29 30  try {31    throw 12;32    // CHECK-NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'33  } catch (...) {34    throw; // Ok, even if the type is not known, conforming code can never rethrow a non-std::exception object.35  }36 37  try {38    throw non_derived_exception();39    // CHECK-NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'40    // CHECK-NOTES: 10:1: note: type defined here41  } catch (non_derived_exception &e) {42  }43  throw non_derived_exception();44  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'45  // CHECK-NOTES: 10:1: note: type defined here46 47// FIXME: More complicated kinds of inheritance should be checked later, but there is48// currently no way use ASTMatchers for this kind of task.49#if 050  // Handle private inheritance cases correctly.51  try {52    throw bad_inheritance();53    // CHECK NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'54    // CHECK NOTES: 11:1: note: type defined here55    throw no_good_inheritance();56    // CHECK NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'57    // CHECK NOTES: 12:1: note: type defined here58    throw really_creative();59    // CHECK NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'60    // CHECK NOTES: 13:1: note: type defined here61  } catch (...) {62  }63  throw bad_inheritance();64  // CHECK NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'65  // CHECK NOTES: 11:1: note: type defined here66  throw no_good_inheritance();67  // CHECK NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'68  // CHECK NOTES: 12:1: note: type defined here69  throw really_creative();70  // CHECK NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'71  // CHECK NOTES: 13:1: note: type defined here72#endif73}74 75void allowed_throws() {76  try {77    throw std::exception();     // Ok78  } catch (std::exception &e) { // Ok79  }80  throw std::exception();81 82  try {83    throw derived_exception();     // Ok84  } catch (derived_exception &e) { // Ok85  }86  throw derived_exception(); // Ok87 88  try {89    throw deep_hierarchy();     // Ok, multiple levels of inheritance90  } catch (deep_hierarchy &e) { // Ok91  }92  throw deep_hierarchy(); // Ok93 94  try {95    throw terrible_idea();      // Ok, but multiple inheritance isn't clean96  } catch (std::exception &e) { // Can be caught as std::exception, even with multiple inheritance97  }98  throw terrible_idea(); // Ok, but multiple inheritance99}100 101void test_lambdas() {102  auto BadLambda = []() { throw int(42); };103  // CHECK-NOTES: [[@LINE-1]]:33: warning: throwing an exception whose type 'int' is not derived from 'std::exception'104  auto GoodLambda = []() { throw derived_exception(); };105}106 107// Templated function that throws exception based on template type108template <typename T>109void ThrowException() { throw T(); }110// CHECK-NOTES: [[@LINE-1]]:31: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'111// CHECK-NOTES: [[@LINE-2]]:31: note: type 'bad_generic_exception<int>' is a template instantiation of 'T'112// CHECK-NOTES: [[@LINE+25]]:1: note: type defined here113 114// CHECK-NOTES: [[@LINE-5]]:31: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'115// CHECK-NOTES: [[@LINE-6]]:31: note: type 'bad_generic_exception<std::exception>' is a template instantiation of 'T'116// CHECK-NOTES: [[@LINE+21]]:1: note: type defined here117 118// CHECK-NOTES: [[@LINE-9]]:31: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'119// CHECK-NOTES: [[@LINE-10]]:31: note: type 'exotic_exception<non_derived_exception>' is a template instantiation of 'T'120// CHECK-NOTES: [[@LINE+20]]:1: note: type defined here121 122// CHECK-NOTES: [[@LINE-13]]:31: warning: throwing an exception whose type 'int' is not derived from 'std::exception'123// CHECK-NOTES: [[@LINE-14]]:31: note: type 'int' is a template instantiation of 'T'124 125// CHECK-NOTES: [[@LINE-16]]:31: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'126// CHECK-NOTES: [[@LINE-17]]:31: note: type 'non_derived_exception' is a template instantiation of 'T'127// CHECK-NOTES: 10:1: note: type defined here128 129#define THROW_EXCEPTION(CLASS) ThrowException<CLASS>()130#define THROW_BAD_EXCEPTION throw int(42);131#define THROW_GOOD_EXCEPTION throw std::exception();132#define THROW_DERIVED_EXCEPTION throw deep_hierarchy();133 134template <typename T>135class generic_exception : std::exception {};136 137template <typename T>138class bad_generic_exception {};139 140template <typename T>141class exotic_exception : public T {};142 143void generic_exceptions() {144  THROW_EXCEPTION(int);145  THROW_EXCEPTION(non_derived_exception);146  THROW_EXCEPTION(std::exception);    // Ok147  THROW_EXCEPTION(derived_exception); // Ok148  THROW_EXCEPTION(deep_hierarchy);    // Ok149 150  THROW_BAD_EXCEPTION;151  // CHECK-NOTES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'152  // CHECK-NOTES: [[@LINE-22]]:35: note: expanded from macro 'THROW_BAD_EXCEPTION'153  THROW_GOOD_EXCEPTION;154  THROW_DERIVED_EXCEPTION;155 156  throw generic_exception<int>();            // Ok,157  THROW_EXCEPTION(generic_exception<float>); // Ok158 159  throw bad_generic_exception<int>();160  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'161  // CHECK-NOTES: [[@LINE-24]]:1: note: type defined here162  throw bad_generic_exception<std::exception>();163  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'164  // CHECK-NOTES: [[@LINE-27]]:1: note: type defined here165  THROW_EXCEPTION(bad_generic_exception<int>);166  THROW_EXCEPTION(bad_generic_exception<std::exception>);167 168  throw exotic_exception<non_derived_exception>();169  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'170  // CHECK-NOTES: [[@LINE-30]]:1: note: type defined here171  THROW_EXCEPTION(exotic_exception<non_derived_exception>);172 173  throw exotic_exception<derived_exception>();          // Ok174  THROW_EXCEPTION(exotic_exception<derived_exception>); // Ok175}176 177// Test for typedefed exception types178typedef int TypedefedBad;179typedef derived_exception TypedefedGood;180using UsingBad = int;181using UsingGood = deep_hierarchy;182 183void typedefed() {184  throw TypedefedBad();185  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'TypedefedBad' (aka 'int') is not derived from 'std::exception'186  // CHECK-NOTES: [[@LINE-8]]:1: note: type defined here187  throw TypedefedGood(); // Ok188 189  throw UsingBad();190  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'UsingBad' (aka 'int') is not derived from 'std::exception'191  // CHECK-NOTES: [[@LINE-11]]:1: note: type defined here192  throw UsingGood(); // Ok193}194 195// Fix PR37913196struct invalid_argument_maker {197  ::std::invalid_argument operator()() const;198};199struct int_maker {200  int operator()() const;201};202 203template <typename T>204void templated_thrower() {205  throw T{}();206  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'207}208template <typename T>209void templated_thrower2() {210  T ExceptionFactory; // This test found a <dependant-type> which did not happend with 'throw T{}()'211  throw ExceptionFactory();212  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'213}214 215void exception_created_with_function() {216  templated_thrower<invalid_argument_maker>();217  templated_thrower<int_maker>();218 219  templated_thrower2<invalid_argument_maker>();220  templated_thrower2<int_maker>();221 222  throw invalid_argument_maker{}();223  throw int_maker{}();224  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'225}226 227struct invalid_argument_factory {228  ::std::invalid_argument make_exception() const;229};230 231struct int_factory {232  int make_exception() const;233};234 235template <typename T>236void templated_factory() {237  T f;238  throw f.make_exception();239  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'240}241template <typename T>242void templated_factory2() {243  throw T().make_exception();244  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'245}246 247void exception_from_factory() {248  templated_factory<invalid_argument_factory>();249  templated_factory<int_factory>();250 251  templated_factory2<invalid_argument_factory>();252  templated_factory2<int_factory>();253 254  throw invalid_argument_factory().make_exception();255  throw int_factory().make_exception();256  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'257 258  invalid_argument_factory inv_f;259  throw inv_f.make_exception();260 261  int_factory int_f;262  throw int_f.make_exception();263  // CHECK-NOTES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'264}265 266template <typename T>267struct ThrowClassTemplateParam {268  ThrowClassTemplateParam() { throw T(); }269  // CHECK-NOTES: [[@LINE-1]]:37: warning: throwing an exception whose type 'int' is not derived from 'std::exception'270  // CHECK-NOTES: [[@LINE-2]]:37: note: type 'int' is a template instantiation of 'T'271};272 273template <int V>274struct ThrowValueTemplate {275  ThrowValueTemplate() { throw V; }276  // CHECK-NOTES: [[@LINE-1]]:32: warning: throwing an exception whose type 'int' is not derived from 'std::exception'277};278 279void class_templates() {280  ThrowClassTemplateParam<int> IntThrow;281  ThrowClassTemplateParam<std::invalid_argument> ArgThrow;282 283  ThrowValueTemplate<42> ValueThrow;284}285