File: hicpp-exception-baseclass.cpp

package info (click to toggle)
llvm-toolchain-6.0 1%3A6.0.1-10
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 598,080 kB
  • sloc: cpp: 3,046,253; ansic: 595,057; asm: 271,965; python: 128,926; objc: 106,554; sh: 21,906; lisp: 10,191; pascal: 6,094; ml: 5,544; perl: 5,265; makefile: 2,227; cs: 2,027; xml: 686; php: 212; csh: 117
file content (179 lines) | stat: -rw-r--r-- 8,398 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// RUN: %check_clang_tidy %s hicpp-exception-baseclass %t -- -- -fcxx-exceptions

namespace std {
class exception {};
} // namespace std

class derived_exception : public std::exception {};
class deep_hierarchy : public derived_exception {};
class non_derived_exception {};
class terrible_idea : public non_derived_exception, public derived_exception {};

// FIXME: More complicated kinds of inheritance should be checked later, but there is
// currently no way use ASTMatchers for this kind of task.
#if 0
class bad_inheritance : private std::exception {};
class no_good_inheritance : protected std::exception {};
class really_creative : public non_derived_exception, private std::exception {};
#endif

void problematic() {
  try {
    throw int(42);
    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
  } catch (int e) {
  }
  throw int(42);
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'int' is not derived from 'std::exception'

  try {
    throw 12;
    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
  } catch (...) {
    throw; // Ok, even if the type is not known, conforming code can never rethrow a non-std::exception object.
  }

  try {
    throw non_derived_exception();
    // CHECK-MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
    // CHECK-MESSAGES: 9:1: note: type defined here
  } catch (non_derived_exception &e) {
  }
  throw non_derived_exception();
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
  // CHECK-MESSAGES: 9:1: note: type defined here

// FIXME: More complicated kinds of inheritance should be checked later, but there is
// currently no way use ASTMatchers for this kind of task.
#if 0
  // Handle private inheritance cases correctly.
  try {
    throw bad_inheritance();
    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
    // CHECK MESSAGES: 10:1: note: type defined here
    throw no_good_inheritance();
    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
    // CHECK MESSAGES: 11:1: note: type defined here
    throw really_creative();
    // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
    // CHECK MESSAGES: 12:1: note: type defined here
  } catch (...) {
  }
  throw bad_inheritance();
  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
  // CHECK MESSAGES: 10:1: note: type defined here
  throw no_good_inheritance();
  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
  // CHECK MESSAGES: 11:1: note: type defined here
  throw really_creative();
  // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
  // CHECK MESSAGES: 12:1: note: type defined here
#endif
}

void allowed_throws() {
  try {
    throw std::exception();     // Ok
  } catch (std::exception &e) { // Ok
  }
  throw std::exception();

  try {
    throw derived_exception();     // Ok
  } catch (derived_exception &e) { // Ok
  }
  throw derived_exception(); // Ok

  try {
    throw deep_hierarchy();     // Ok, multiple levels of inheritance
  } catch (deep_hierarchy &e) { // Ok
  }
  throw deep_hierarchy(); // Ok

  try {
    throw terrible_idea();     // Ok, but multiple inheritance isn't clean
  } catch (std::exception &e) { // Can be caught as std::exception, even with multiple inheritance
  }
  throw terrible_idea(); // Ok, but multiple inheritance
}

// Templated function that throws exception based on template type
template <typename T>
void ThrowException() { throw T(); }
// CHECK-MESSAGES: [[@LINE-1]]:31: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
// CHECK-MESSAGES: 120:1: note: type defined here
// CHECK-MESSAGES: [[@LINE-3]]:31: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
// CHECK-MESSAGES: 120:1: note: type defined here
// CHECK-MESSAGES: [[@LINE-5]]:31: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
// CHECK-MESSAGES: 123:1: note: type defined here
// CHECK-MESSAGES: [[@LINE-7]]:31: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
// CHECK-MESSAGES: [[@LINE-8]]:31: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
// CHECK-MESSAGES: 9:1: note: type defined here
#define THROW_EXCEPTION(CLASS) ThrowException<CLASS>()
#define THROW_BAD_EXCEPTION throw int(42);
#define THROW_GOOD_EXCEPTION throw std::exception();
#define THROW_DERIVED_EXCEPTION throw deep_hierarchy();

template <typename T>
class generic_exception : std::exception {};

template <typename T>
class bad_generic_exception {};

template <typename T>
class exotic_exception : public T {};

void generic_exceptions() {
  THROW_EXCEPTION(int);
  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
  THROW_EXCEPTION(non_derived_exception);
  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
  // CHECK MESSAGES: 9:1: note: type defined here
  THROW_EXCEPTION(std::exception);    // Ok
  THROW_EXCEPTION(derived_exception); // Ok
  THROW_EXCEPTION(deep_hierarchy);    // Ok

  THROW_BAD_EXCEPTION;
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
  // CHECK-MESSAGES: [[@LINE-25]]:35: note: expanded from macro 'THROW_BAD_EXCEPTION'
  THROW_GOOD_EXCEPTION;
  THROW_DERIVED_EXCEPTION;

  throw generic_exception<int>();            // Ok,
  THROW_EXCEPTION(generic_exception<float>); // Ok

  throw bad_generic_exception<int>();
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
  throw bad_generic_exception<std::exception>();
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'
  THROW_EXCEPTION(bad_generic_exception<int>);
  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<int>' is not derived from 'std::exception'
  THROW_EXCEPTION(bad_generic_exception<std::exception>);
  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'bad_generic_exception<std::exception>' is not derived from 'std::exception'

  throw exotic_exception<non_derived_exception>();
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'
  THROW_EXCEPTION(exotic_exception<non_derived_exception>);
  // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'exotic_exception<non_derived_exception>' is not derived from 'std::exception'

  throw exotic_exception<derived_exception>();          // Ok
  THROW_EXCEPTION(exotic_exception<derived_exception>); // Ok
}

// Test for typedefed exception types
typedef int TypedefedBad;
typedef derived_exception TypedefedGood;
using UsingBad = int;
using UsingGood = deep_hierarchy;

void typedefed() {
  throw TypedefedBad();
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'TypedefedBad' (aka 'int') is not derived from 'std::exception'
  // CHECK-MESSAGES: 164:1: note: type defined here
  throw TypedefedGood(); // Ok

  throw UsingBad();
  // CHECK-MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'UsingBad' (aka 'int') is not derived from 'std::exception'
  // CHECK-MESSAGES: 166:1: note: type defined here
  throw UsingGood(); // Ok
}