@@ -93,6 +93,159 @@ TEST(CFG, DependantBaseAddImplicitDtors) {
9393 .getStatus ());
9494}
9595
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+
96249TEST (CFG, IsLinear) {
97250 auto expectLinear = [](bool IsLinear, const char *Code) {
98251 BuildResult B = BuildCFG (Code);
0 commit comments