@@ -93,6 +93,159 @@ TEST(CFG, DependantBaseAddImplicitDtors) {
93
93
.getStatus ());
94
94
}
95
95
96
+ TEST (CFG, SwitchCoveredEnumNoDefault) {
97
+ const char *Code = R"(
98
+ enum class E {E1, E2};
99
+ int f(E e) {
100
+ switch(e) {
101
+ case E::E1:
102
+ return 1;
103
+ case E::E2:
104
+ return 2;
105
+ }
106
+ return 0;
107
+ }
108
+ )" ;
109
+ CFG::BuildOptions Options;
110
+ Options.AssumeReachableDefaultInSwitchStatements = true ;
111
+ BuildResult B = BuildCFG (Code, Options);
112
+ ASSERT_EQ (BuildResult::BuiltCFG, B.getStatus ());
113
+
114
+ // [B5 (ENTRY)]
115
+ // Succs (1): B2
116
+ //
117
+ // [B1]
118
+ // 1: 0
119
+ // 2: return [B1.1];
120
+ // Preds (1): B2
121
+ // Succs (1): B0
122
+ //
123
+ // [B2]
124
+ // 1: e (ImplicitCastExpr, LValueToRValue, E)
125
+ // T: switch [B2.1]
126
+ // Preds (1): B5
127
+ // Succs (3): B3 B4 B1
128
+ //
129
+ // [B3]
130
+ // case E::E2:
131
+ // 1: 2
132
+ // 2: return [B3.1];
133
+ // Preds (1): B2
134
+ // Succs (1): B0
135
+ //
136
+ // [B4]
137
+ // case E::E1:
138
+ // 1: 1
139
+ // 2: return [B4.1];
140
+ // Preds (1): B2
141
+ // Succs (1): B0
142
+ //
143
+ // [B0 (EXIT)]
144
+ // Preds (3): B1 B3 B4
145
+
146
+ auto *CFG = B.getCFG ();
147
+ const auto &Entry = CFG->getEntry ();
148
+ ASSERT_EQ (1u , Entry.succ_size ());
149
+ // First successor of Entry is the switch
150
+ CFGBlock *SwitchBlock = *Entry.succ_begin ();
151
+ ASSERT_EQ (3u , SwitchBlock->succ_size ());
152
+ // Last successor of the switch is after the switch
153
+ auto NoCaseSucc = SwitchBlock->succ_rbegin ();
154
+ EXPECT_TRUE (NoCaseSucc->isReachable ());
155
+
156
+ // Checking that the same node is Unreachable without this setting
157
+ Options.AssumeReachableDefaultInSwitchStatements = false ;
158
+ B = BuildCFG (Code, Options);
159
+ ASSERT_EQ (BuildResult::BuiltCFG, B.getStatus ());
160
+
161
+ const auto &Entry2 = B.getCFG ()->getEntry ();
162
+ ASSERT_EQ (1u , Entry2.succ_size ());
163
+ CFGBlock *SwitchBlock2 = *Entry2.succ_begin ();
164
+ ASSERT_EQ (3u , SwitchBlock2->succ_size ());
165
+ auto NoCaseSucc2 = SwitchBlock2->succ_rbegin ();
166
+ EXPECT_FALSE (NoCaseSucc2->isReachable ());
167
+ }
168
+
169
+ TEST (CFG, SwitchCoveredEnumWithDefault) {
170
+ const char *Code = R"(
171
+ enum class E {E1, E2};
172
+ int f(E e) {
173
+ switch(e) {
174
+ case E::E1:
175
+ return 1;
176
+ case E::E2:
177
+ return 2;
178
+ default:
179
+ return 0;
180
+ }
181
+ return -1;
182
+ }
183
+ )" ;
184
+ CFG::BuildOptions Options;
185
+ Options.AssumeReachableDefaultInSwitchStatements = true ;
186
+ BuildResult B = BuildCFG (Code, Options);
187
+ ASSERT_EQ (BuildResult::BuiltCFG, B.getStatus ());
188
+
189
+ // [B6 (ENTRY)]
190
+ // Succs (1): B2
191
+ //
192
+ // [B1]
193
+ // 1: -1
194
+ // 2: return [B1.1];
195
+ // Succs (1): B0
196
+ //
197
+ // [B2]
198
+ // 1: e (ImplicitCastExpr, LValueToRValue, E)
199
+ // T: switch [B2.1]
200
+ // Preds (1): B6
201
+ // Succs (3): B4 B5 B3
202
+ //
203
+ // [B3]
204
+ // default:
205
+ // 1: 0
206
+ // 2: return [B3.1];
207
+ // Preds (1): B2
208
+ // Succs (1): B0
209
+ //
210
+ // [B4]
211
+ // case E::E2:
212
+ // 1: 2
213
+ // 2: return [B4.1];
214
+ // Preds (1): B2
215
+ // Succs (1): B0
216
+ //
217
+ // [B5]
218
+ // case E::E1:
219
+ // 1: 1
220
+ // 2: return [B5.1];
221
+ // Preds (1): B2
222
+ // Succs (1): B0
223
+ //
224
+ // [B0 (EXIT)]
225
+ // Preds (4): B1 B3 B4 B5
226
+
227
+ const auto &Entry = B.getCFG ()->getEntry ();
228
+ ASSERT_EQ (1u , Entry.succ_size ());
229
+ // First successor of Entry is the switch
230
+ CFGBlock *SwitchBlock = *Entry.succ_begin ();
231
+ ASSERT_EQ (3u , SwitchBlock->succ_size ());
232
+ // Last successor of the switch is the default branch
233
+ auto defaultBlock = SwitchBlock->succ_rbegin ();
234
+ EXPECT_TRUE (defaultBlock->isReachable ());
235
+
236
+ // Checking that the same node is Unreachable without this setting
237
+ Options.AssumeReachableDefaultInSwitchStatements = false ;
238
+ B = BuildCFG (Code, Options);
239
+ ASSERT_EQ (BuildResult::BuiltCFG, B.getStatus ());
240
+
241
+ const auto &Entry2 = B.getCFG ()->getEntry ();
242
+ ASSERT_EQ (1u , Entry2.succ_size ());
243
+ CFGBlock *SwitchBlock2 = *Entry2.succ_begin ();
244
+ ASSERT_EQ (3u , SwitchBlock2->succ_size ());
245
+ auto defaultBlock2 = SwitchBlock2->succ_rbegin ();
246
+ EXPECT_FALSE (defaultBlock2->isReachable ());
247
+ }
248
+
96
249
TEST (CFG, IsLinear) {
97
250
auto expectLinear = [](bool IsLinear, const char *Code) {
98
251
BuildResult B = BuildCFG (Code);
0 commit comments