1// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
2// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
3
4// A destructor may be marked noreturn and should still influence the CFG.
5void pr6884_abort() __attribute__((noreturn));
6
7struct pr6884_abort_struct {
8  pr6884_abort_struct() {}
9  ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
10};
11
12struct other { ~other() {} };
13
14// Ensure that destructors from objects are properly modeled in the CFG despite
15// the presence of switches, case statements, labels, and blocks. These tests
16// try to cover bugs reported in both PR6884 and PR10063.
17namespace abort_struct_complex_cfgs {
18  int basic(int x) {
19    switch (x) { default: pr6884_abort(); }
20  }
21  int f1(int x) {
22    switch (x) default: pr6884_abort_struct();
23  }
24  int f2(int x) {
25    switch (x) { default: pr6884_abort_struct(); }
26  }
27  int f2_positive(int x) {
28    switch (x) { default: ; }
29  } // expected-warning {{control reaches end of non-void function}}
30  int f3(int x) {
31    switch (x) { default: { pr6884_abort_struct(); } }
32  }
33  int f4(int x) {
34    switch (x) default: L1: L2: case 4: pr6884_abort_struct();
35  }
36  int f5(int x) {
37    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
38  }
39  int f6(int x) {
40    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
41  }
42
43  // FIXME: detect noreturn destructors triggered by calls to delete.
44  int f7(int x) {
45    switch (x) default: L1: L2: case 4: {
46      pr6884_abort_struct *p = new pr6884_abort_struct();
47      delete p;
48    }
49  } // expected-warning {{control reaches end of non-void function}}
50
51  // Test that these constructs work even when extraneous blocks are created
52  // before and after the switch due to implicit destructors.
53  int g1(int x) {
54    other o;
55    switch (x) default: pr6884_abort_struct();
56  }
57  int g2(int x) {
58    other o;
59    switch (x) { default: pr6884_abort_struct(); }
60  }
61  int g2_positive(int x) {
62    other o;
63    switch (x) { default: ; }
64  } // expected-warning {{control reaches end of non-void function}}
65  int g3(int x) {
66    other o;
67    switch (x) { default: { pr6884_abort_struct(); } }
68  }
69  int g4(int x) {
70    other o;
71    switch (x) default: L1: L2: case 4: pr6884_abort_struct();
72  }
73  int g5(int x) {
74    other o;
75    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
76  }
77  int g6(int x) {
78    other o;
79    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
80  }
81
82  // Test that these constructs work even with variables carrying the no-return
83  // destructor instead of temporaries.
84  int h1(int x) {
85    other o;
86    switch (x) default: pr6884_abort_struct a;
87  }
88  int h2(int x) {
89    other o;
90    switch (x) { default: pr6884_abort_struct a; }
91  }
92  int h3(int x) {
93    other o;
94    switch (x) { default: { pr6884_abort_struct a; } }
95  }
96  int h4(int x) {
97    other o;
98    switch (x) default: L1: L2: case 4: pr6884_abort_struct a;
99  }
100  int h5(int x) {
101    other o;
102    switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; }
103  }
104  int h6(int x) {
105    other o;
106    switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; }
107  }
108}
109
110// PR9380
111struct PR9380 {
112  ~PR9380();
113};
114struct PR9380_B : public PR9380 {
115  PR9380_B( const PR9380& str );
116};
117void test_PR9380(const PR9380& aKey) {
118  const PR9380& flatKey = PR9380_B(aKey);
119}
120
121// Array of objects with destructors.  This is purely a coverage test case.
122void test_array() {
123  PR9380 a[2];
124}
125
126// Test classes wrapped in typedefs.  This is purely a coverage test case
127// for CFGImplictDtor::getDestructorDecl().
128void test_typedefs() {
129  typedef PR9380 PR9380_Ty;
130  PR9380_Ty test;
131  PR9380_Ty test2[20];
132}
133
134// PR9412 - Handle CFG traversal with null successors.
135enum PR9412_MatchType { PR9412_Exact };
136
137template <PR9412_MatchType type> int PR9412_t() {
138  switch (type) {
139    case PR9412_Exact:
140    default:
141        break;
142  }
143} // expected-warning {{control reaches end of non-void function}}
144
145void PR9412_f() {
146    PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_MatchType::PR9412_Exact>' requested here}}
147}
148
149struct NoReturn {
150  ~NoReturn() __attribute__((noreturn));
151  operator bool() const;
152};
153struct Return {
154  ~Return();
155  operator bool() const;
156};
157
158int testTernaryUnconditionalNoreturn() {
159  true ? NoReturn() : NoReturn();
160}
161
162int testTernaryStaticallyConditionalNoretrunOnTrue() {
163  true ? NoReturn() : Return();
164}
165
166int testTernaryStaticallyConditionalRetrunOnTrue() {
167  true ? Return() : NoReturn();
168} // expected-warning {{control reaches end of non-void function}}
169
170int testTernaryStaticallyConditionalNoretrunOnFalse() {
171  false ? Return() : NoReturn();
172}
173
174int testTernaryStaticallyConditionalRetrunOnFalse() {
175  false ? NoReturn() : Return();
176} // expected-warning {{control reaches end of non-void function}}
177
178int testTernaryConditionalNoreturnTrueBranch(bool value) {
179  value ? (NoReturn() || NoReturn()) : Return();
180} // expected-warning {{control may reach end of non-void function}}
181
182int testTernaryConditionalNoreturnFalseBranch(bool value) {
183  value ? Return() : (NoReturn() || NoReturn());
184} // expected-warning {{control may reach end of non-void function}}
185
186int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
187  value || (true ? NoReturn() : true);
188} // expected-warning {{control may reach end of non-void function}}
189
190int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
191  value || (false ? true : NoReturn());
192} // expected-warning {{control may reach end of non-void function}}
193
194int testStaticallyExecutedLogicalOrBranch() {
195  false || NoReturn();
196}
197
198int testStaticallyExecutedLogicalAndBranch() {
199  true && NoReturn();
200}
201
202int testStaticallySkippedLogicalOrBranch() {
203  true || NoReturn();
204} // expected-warning {{control reaches end of non-void function}}
205
206int testStaticallySkppedLogicalAndBranch() {
207  false && NoReturn();
208} // expected-warning {{control reaches end of non-void function}}
209
210int testConditionallyExecutedComplexLogicalBranch(bool value) {
211  value || (true && NoReturn());
212} // expected-warning {{control may reach end of non-void function}}
213
214int testConditionallyExecutedComplexLogicalBranch2(bool value) {
215  (true && value) || (true && NoReturn());
216} // expected-warning {{control may reach end of non-void function}}
217
218int testConditionallyExecutedComplexLogicalBranch3(bool value) {
219  (false && (Return() || true)) || (true && NoReturn());
220}
221
222int testConditionallyExecutedComplexLogicalBranch4(bool value) {
223  false || ((Return() || true) && (true && NoReturn()));
224}
225
226#if __cplusplus >= 201103L
227namespace LambdaVsTemporaryDtor {
228  struct Y { ~Y(); };
229  struct X { template<typename T> X(T, Y = Y()) {} };
230
231  struct Fatal { ~Fatal() __attribute__((noreturn)); };
232  struct FatalCopy { FatalCopy(); FatalCopy(const FatalCopy&, Fatal F = Fatal()); };
233
234  void foo();
235
236  int bar() {
237    X work([](){ Fatal(); });
238    foo();
239  } // expected-warning {{control reaches end of non-void function}}
240
241  int baz() {
242    FatalCopy fc;
243    X work([fc](){});
244    foo();
245  } // ok, initialization of lambda does not return
246}
247#endif
248
249// Ensure that function-try-blocks also check for return values properly.
250int functionTryBlock1(int s) try {
251  return 0;
252} catch (...) {
253} // expected-warning {{control may reach end of non-void function}}
254
255int functionTryBlock2(int s) try {
256} catch (...) {
257  return 0;
258} // expected-warning {{control may reach end of non-void function}}
259
260int functionTryBlock3(int s) try {
261  return 0;
262} catch (...) {
263  return 0;
264} // ok, both paths return.
265