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.
5 void pr6884_abort() __attribute__((noreturn));
6 
7 struct pr6884_abort_struct {
8   pr6884_abort_struct() {}
9   ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
10 };
11 
12 struct 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.
17 namespace 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
111 struct PR9380 {
112   ~PR9380();
113 };
114 struct PR9380_B : public PR9380 {
115   PR9380_B( const PR9380& str );
116 };
117 void 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.
122 void 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().
128 void 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.
135 enum PR9412_MatchType { PR9412_Exact };
136 
137 template <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 
145 void PR9412_f() {
146     PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_Exact>' requested here}}
147 }
148 
149 struct NoReturn {
150   ~NoReturn() __attribute__((noreturn));
151   operator bool() const;
152 };
153 struct Return {
154   ~Return();
155   operator bool() const;
156 };
157 
158 int testTernaryUnconditionalNoreturn() {
159   true ? NoReturn() : NoReturn();
160 }
161 
162 int testTernaryStaticallyConditionalNoretrunOnTrue() {
163   true ? NoReturn() : Return();
164 }
165 
166 int testTernaryStaticallyConditionalRetrunOnTrue() {
167   true ? Return() : NoReturn();
168 } // expected-warning {{control reaches end of non-void function}}
169 
170 int testTernaryStaticallyConditionalNoretrunOnFalse() {
171   false ? Return() : NoReturn();
172 }
173 
174 int testTernaryStaticallyConditionalRetrunOnFalse() {
175   false ? NoReturn() : Return();
176 } // expected-warning {{control reaches end of non-void function}}
177 
178 int testTernaryConditionalNoreturnTrueBranch(bool value) {
179   value ? (NoReturn() || NoReturn()) : Return();
180 } // expected-warning {{control may reach end of non-void function}}
181 
182 int testTernaryConditionalNoreturnFalseBranch(bool value) {
183   value ? Return() : (NoReturn() || NoReturn());
184 } // expected-warning {{control may reach end of non-void function}}
185 
186 int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
187   value || (true ? NoReturn() : true);
188 } // expected-warning {{control may reach end of non-void function}}
189 
190 int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
191   value || (false ? true : NoReturn());
192 } // expected-warning {{control may reach end of non-void function}}
193 
194 int testStaticallyExecutedLogicalOrBranch() {
195   false || NoReturn();
196 }
197 
198 int testStaticallyExecutedLogicalAndBranch() {
199   true && NoReturn();
200 }
201 
202 int testStaticallySkippedLogicalOrBranch() {
203   true || NoReturn();
204 } // expected-warning {{control reaches end of non-void function}}
205 
206 int testStaticallySkppedLogicalAndBranch() {
207   false && NoReturn();
208 } // expected-warning {{control reaches end of non-void function}}
209 
210 int testConditionallyExecutedComplexLogicalBranch(bool value) {
211   value || (true && NoReturn());
212 } // expected-warning {{control may reach end of non-void function}}
213 
214 int testConditionallyExecutedComplexLogicalBranch2(bool value) {
215   (true && value) || (true && NoReturn());
216 } // expected-warning {{control may reach end of non-void function}}
217 
218 int testConditionallyExecutedComplexLogicalBranch3(bool value) {
219   (false && (Return() || true)) || (true && NoReturn());
220 }
221 
222 int testConditionallyExecutedComplexLogicalBranch4(bool value) {
223   false || ((Return() || true) && (true && NoReturn()));
224 }
225 
226 #if __cplusplus >= 201103L
227 namespace 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.
250 int functionTryBlock1(int s) try {
251   return 0;
252 } catch (...) {
253 } // expected-warning {{control may reach end of non-void function}}
254 
255 int functionTryBlock2(int s) try {
256 } catch (...) {
257   return 0;
258 } // expected-warning {{control may reach end of non-void function}}
259 
260 int functionTryBlock3(int s) try {
261   return 0;
262 } catch (...) {
263   return 0;
264 } // ok, both paths return.
265