• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %check_clang_tidy %s bugprone-throw-keyword-missing %t -- -- -fexceptions
2 
3 namespace std {
4 
5 // std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp).
6 template <typename T>
7 class allocator {};
8 template <typename T>
9 class char_traits {};
10 template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
11 struct basic_string {
12   basic_string();
13   basic_string(const basic_string &);
14   // MSVC headers define two constructors instead of using optional arguments.
15   basic_string(const C *);
16   basic_string(const C *, const A &);
17   ~basic_string();
18 };
19 typedef basic_string<char> string;
20 typedef basic_string<wchar_t> wstring;
21 
22 // std::exception and std::runtime_error declaration.
23 struct exception {
24   exception();
25   exception(const exception &other);
26   virtual ~exception();
27 };
28 
29 struct runtime_error : public exception {
30   explicit runtime_error(const std::string &what_arg);
31 };
32 
33 } // namespace std
34 
35 // The usage of this class should never emit a warning.
36 struct RegularClass {};
37 
38 // Class name contains the substring "exception", in certain cases using this class should emit a warning.
39 struct RegularException {
RegularExceptionRegularException40   RegularException() {}
41 
42   // Constructors with a single argument are treated differently (cxxFunctionalCastExpr).
RegularExceptionRegularException43   RegularException(int) {}
44 };
45 
46 // --------------
47 
stdExceptionNotTrownTest(int i)48 void stdExceptionNotTrownTest(int i) {
49   if (i < 0)
50     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception object created but not thrown; did you mean 'throw {{.*}}'? [bugprone-throw-keyword-missing]
51     std::exception();
52 
53   if (i > 0)
54     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
55     std::runtime_error("Unexpected argument");
56 }
57 
stdExceptionThrownTest(int i)58 void stdExceptionThrownTest(int i) {
59   if (i < 0)
60     throw std::exception();
61 
62   if (i > 0)
63     throw std::runtime_error("Unexpected argument");
64 }
65 
regularClassNotThrownTest(int i)66 void regularClassNotThrownTest(int i) {
67   if (i < 0)
68     RegularClass();
69 }
70 
regularClassThrownTest(int i)71 void regularClassThrownTest(int i) {
72   if (i < 0)
73     throw RegularClass();
74 }
75 
nameContainsExceptionNotThrownTest(int i)76 void nameContainsExceptionNotThrownTest(int i) {
77   if (i < 0)
78     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
79     RegularException();
80 
81   if (i > 0)
82     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
83     RegularException(5);
84 }
85 
nameContainsExceptionThrownTest(int i)86 void nameContainsExceptionThrownTest(int i) {
87   if (i < 0)
88     throw RegularException();
89 
90   if (i > 0)
91     throw RegularException(5);
92 }
93 
94 template <class Exception>
f(int i,Exception excToBeThrown)95 void f(int i, Exception excToBeThrown) {}
96 
funcCallWithTempExcTest()97 void funcCallWithTempExcTest() {
98   f(5, RegularException());
99 }
100 
101 // Global variable initialization test.
102 RegularException exc = RegularException();
103 RegularException *excptr = new RegularException();
104 
localVariableInitTest()105 void localVariableInitTest() {
106   RegularException exc = RegularException();
107   RegularException *excptr = new RegularException();
108 }
109 
110 class CtorInitializerListTest {
111   RegularException exc;
112 
CtorInitializerListTest()113   CtorInitializerListTest() : exc(RegularException()) {}
114 
CtorInitializerListTest(int)115   CtorInitializerListTest(int) try : exc(RegularException()) {
116     // Constructor body
117   } catch (...) {
118     // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: suspicious exception
119     RegularException();
120   }
121 
122   CtorInitializerListTest(float);
123 };
124 
CtorInitializerListTest(float)125 CtorInitializerListTest::CtorInitializerListTest(float) try : exc(RegularException()) {
126   // Constructor body
127 } catch (...) {
128   // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
129   RegularException();
130 }
131 
funcReturningExceptionTest(int i)132 RegularException funcReturningExceptionTest(int i) {
133   return RegularException();
134 }
135 
returnedValueTest()136 void returnedValueTest() {
137   funcReturningExceptionTest(3);
138 }
139 
140 struct ClassBracedInitListTest {
ClassBracedInitListTestClassBracedInitListTest141   ClassBracedInitListTest(RegularException exc) {}
142 };
143 
foo(RegularException,ClassBracedInitListTest)144 void foo(RegularException, ClassBracedInitListTest) {}
145 
bracedInitListTest()146 void bracedInitListTest() {
147   RegularException exc{};
148   ClassBracedInitListTest test = {RegularException()};
149   foo({}, {RegularException()});
150 }
151 
152 typedef std::exception ERROR_BASE;
153 class RegularError : public ERROR_BASE {};
154 
typedefTest()155 void typedefTest() {
156   // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: suspicious exception
157   RegularError();
158 }
159 
160 struct ExceptionRAII {
ExceptionRAIIExceptionRAII161   ExceptionRAII() {}
~ExceptionRAIIExceptionRAII162   ~ExceptionRAII() {}
163 };
164 
exceptionRAIITest()165 void exceptionRAIITest() {
166   ExceptionRAII E;
167 }
168