Skip to content

Commit 0587fb7

Browse files
committed
[move-function] Add var conditional control flow reinit tests.
I already had tests for these in Swift itself that check at the IR level things look correct. This just provides a true end<->end test that these continue to work as expected.
1 parent a93d9fe commit 0587fb7

File tree

2 files changed

+188
-23
lines changed

2 files changed

+188
-23
lines changed

lldb/test/API/lang/swift/variables/move_function/TestSwiftMoveFunction.py

Lines changed: 139 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ def test_swift_move_function(self):
5555
# ccf is conditional control flow
5656
self.do_check_copyable_value_ccf_true()
5757
self.do_check_copyable_value_ccf_false()
58+
self.do_check_copyable_var_ccf_true_reinit_out_block()
59+
self.do_check_copyable_var_ccf_true_reinit_in_block()
60+
self.do_check_copyable_var_ccf_false_reinit_out_block()
61+
self.do_check_copyable_var_ccf_false_reinit_in_block()
5862

5963
def setUp(self):
6064
TestBase.setUp(self)
@@ -71,6 +75,11 @@ def add_breakpoints(self, name, num_breakpoints):
7175
self.assertGreater(brk.GetNumLocations(), 0, VALID_BREAKPOINT)
7276
yield brk
7377

78+
def get_var(self, name):
79+
frame = self.thread.frames[0]
80+
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
81+
return frame.FindVariable(name)
82+
7483
def do_setup_breakpoints(self):
7584
self.breakpoints = []
7685

@@ -88,13 +97,21 @@ def do_setup_breakpoints(self):
8897
self.breakpoints.extend(
8998
self.add_breakpoints('copyableValueCCFFalseTest',
9099
3))
100+
self.breakpoints.extend(
101+
self.add_breakpoints('copyableVarTestCCFlowTrueReinitOutOfBlockTest',
102+
5))
103+
self.breakpoints.extend(
104+
self.add_breakpoints('copyableVarTestCCFlowTrueReinitInBlockTest',
105+
5))
106+
self.breakpoints.extend(
107+
self.add_breakpoints('copyableVarTestCCFlowFalseReinitOutOfBlockTest',
108+
4))
109+
self.breakpoints.extend(
110+
self.add_breakpoints('copyableVarTestCCFlowFalseReinitInBlockTest', 3))
91111

92112
def do_check_copyable_value_test(self):
93-
frame = self.thread.frames[0]
94-
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
95-
96113
# We haven't defined varK yet.
97-
varK = frame.FindVariable('k')
114+
varK = self.get_var('k')
98115

99116
self.assertIsNone(varK.value, "varK initialized too early?!")
100117

@@ -111,11 +128,8 @@ def do_check_copyable_value_test(self):
111128
self.runCmd('continue')
112129

113130
def do_check_copyable_var_test(self):
114-
frame = self.thread.frames[0]
115-
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
116-
117131
# We haven't defined varK yet.
118-
varK = frame.FindVariable('k')
132+
varK = self.get_var('k')
119133
self.assertIsNone(varK.value, "varK initialized too early?!")
120134

121135
# Go to break point 2. k should be valid.
@@ -135,11 +149,8 @@ def do_check_copyable_var_test(self):
135149
self.runCmd('continue')
136150

137151
def do_check_addressonly_value_test(self):
138-
frame = self.thread.frames[0]
139-
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
140-
141-
# We haven't defined varK or varM yet... so we shouldn't have a summary.
142-
varK = frame.FindVariable('k')
152+
# We haven't defined varK yet.
153+
varK = self.get_var('k')
143154

144155
# Go to break point 2. k should be valid and m should not be. Since M is
145156
# a dbg.declare it is hard to test robustly that it is not initialized
@@ -158,10 +169,7 @@ def do_check_addressonly_value_test(self):
158169
self.runCmd('continue')
159170

160171
def do_check_addressonly_var_test(self):
161-
frame = self.thread.frames[0]
162-
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
163-
164-
varK = frame.FindVariable('k')
172+
varK = self.get_var('k')
165173

166174
# Go to break point 2. k should be valid.
167175
self.runCmd('continue')
@@ -180,9 +188,7 @@ def do_check_addressonly_var_test(self):
180188
self.runCmd('continue')
181189

182190
def do_check_copyable_value_ccf_true(self):
183-
frame = self.thread.frames[0]
184-
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
185-
varK = frame.FindVariable('k')
191+
varK = self.get_var('k')
186192

187193
# Check at our start point that we do not have any state for varK and
188194
# then continue to our next breakpoint.
@@ -211,9 +217,7 @@ def do_check_copyable_value_ccf_true(self):
211217
self.runCmd('continue')
212218

213219
def do_check_copyable_value_ccf_false(self):
214-
frame = self.thread.frames[0]
215-
self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
216-
varK = frame.FindVariable('k')
220+
varK = self.get_var('k')
217221

218222
# Check at our start point that we do not have any state for varK and
219223
# then continue to our next breakpoint.
@@ -233,3 +237,115 @@ def do_check_copyable_value_ccf_false(self):
233237

234238
# Run again so we go and run to the next test.
235239
self.runCmd('continue')
240+
241+
def do_check_copyable_var_ccf_true_reinit_out_block(self):
242+
varK = self.get_var('k')
243+
244+
# At first we should not have a value for k.
245+
self.assertEqual(varK.unsigned, 0, "varK should be nullptr!")
246+
self.runCmd('continue')
247+
248+
# Now we are in the conditional true block. K should be defined since we
249+
# are on the move itself.
250+
self.assertGreater(varK.unsigned, 0, "varK should not be nullptr!")
251+
self.runCmd('continue')
252+
253+
# Now we have executed the move and we are about to run code using
254+
# m. Make sure that K is not available!
255+
self.assertEqual(varK.unsigned, 0,
256+
"varK was already moved! Should be nullptr")
257+
self.runCmd('continue')
258+
259+
# We are now out of the conditional lexical block on the line of code
260+
# that redefines k. k should still be not available.
261+
self.assertEqual(varK.unsigned, 0,
262+
"varK was already moved! Should be nullptr")
263+
self.runCmd('continue')
264+
265+
# Ok, we have now reinit k and are about to call a method on it. We
266+
# should be valid now.
267+
self.assertGreater(varK.unsigned, 0,
268+
"varK should have be reinitialized?!")
269+
270+
# Run again so we go and run to the next test.
271+
self.runCmd('continue')
272+
273+
def do_check_copyable_var_ccf_true_reinit_in_block(self):
274+
varK = self.get_var('k')
275+
276+
# At first we should not have a value for k.
277+
self.assertEqual(varK.unsigned, 0, "varK should be nullptr!")
278+
self.runCmd('continue')
279+
280+
# Now we are in the conditional true block. K should be defined since we
281+
# are on the move itself.
282+
self.assertGreater(varK.unsigned, 0, "varK should not be nullptr!")
283+
self.runCmd('continue')
284+
285+
# Now we have executed the move and we are about to reinit k but have
286+
# not yet. Make sure we are not available!
287+
self.assertEqual(varK.unsigned, 0,
288+
"varK was already moved! Should be nullptr")
289+
self.runCmd('continue')
290+
291+
# We are now still inside the conditional part of the code, but have
292+
# reinitialized varK.
293+
self.assertGreater(varK.unsigned, 0,
294+
"varK was reinit! Should be valid value!")
295+
self.runCmd('continue')
296+
297+
# We now have left the conditional part of the function. k should still
298+
# be available.
299+
self.assertGreater(varK.unsigned, 0,
300+
"varK should have be reinitialized?!")
301+
302+
# Run again so we go and run to the next test.
303+
self.runCmd('continue')
304+
305+
def do_check_copyable_var_ccf_false_reinit_out_block(self):
306+
varK = self.get_var('k')
307+
308+
# At first we should not have a value for k.
309+
self.assertEqual(varK.unsigned, 0, "varK should be nullptr!")
310+
self.runCmd('continue')
311+
312+
# Now we are right above the beginning of the false check. varK should
313+
# still be valid.
314+
self.assertGreater(varK.unsigned, 0, "varK should not be nullptr!")
315+
self.runCmd('continue')
316+
317+
# Now we are after the conditional part of the code on the reinit
318+
# line. Since this is reachable from the move and we haven't reinit yet,
319+
# k should not be available.
320+
self.assertEqual(varK.unsigned, 0,
321+
"varK was already moved! Should be nullptr")
322+
self.runCmd('continue')
323+
324+
# Ok, we have now reinit k and are about to call a method on it. We
325+
# should be valid now.
326+
self.assertGreater(varK.unsigned, 0,
327+
"varK should have be reinitialized?!")
328+
329+
# Run again so we go and run to the next test.
330+
self.runCmd('continue')
331+
332+
def do_check_copyable_var_ccf_false_reinit_in_block(self):
333+
varK = self.get_var('k')
334+
335+
# At first we should not have a value for k.
336+
self.assertEqual(varK.unsigned, 0, "varK should be nullptr!")
337+
self.runCmd('continue')
338+
339+
# Now we are on the doSomething above the false check. So varK should be
340+
# valid.
341+
self.assertGreater(varK.unsigned, 0, "varK should not be nullptr!")
342+
self.runCmd('continue')
343+
344+
# Now we are after the conditional scope. Since k was reinitialized in
345+
# the conditional scope, along all paths we are valid so varK should
346+
# still be available.
347+
self.assertGreater(varK.unsigned, 0,
348+
"varK should not be nullptr?!")
349+
350+
# Run again so we go and run to the next test.
351+
self.runCmd('continue')

lldb/test/API/lang/swift/variables/move_function/main.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,51 @@ public func copyableValueCCFFalseTest() {
9191
// Set breakpoint copyableValueCCFFalseTest here 3
9292
}
9393

94+
public func copyableVarTestCCFlowTrueReinitOutOfBlockTest() {
95+
var k = Klass() // Set breakpoint copyableVarTestCCFlowTrueReinitOutOfBlockTest here 1
96+
k.doSomething()
97+
if trueBoolValue {
98+
let m = _move(k) // Set breakpoint copyableVarTestCCFlowTrueReinitOutOfBlockTest here 2
99+
m.doSomething() // Set breakpoint copyableVarTestCCFlowTrueReinitOutOfBlockTest here 3
100+
}
101+
k = Klass() // Set breakpoint copyableVarTestCCFlowTrueReinitOutOfBlockTest here 4
102+
k.doSomething() // Set breakpoint copyableVarTestCCFlowTrueReinitOutOfBlockTest here 5
103+
}
104+
105+
public func copyableVarTestCCFlowTrueReinitInBlockTest() {
106+
var k = Klass() // Set breakpoint copyableVarTestCCFlowTrueReinitInBlockTest here 1
107+
k.doSomething()
108+
if trueBoolValue {
109+
let m = _move(k) // Set breakpoint copyableVarTestCCFlowTrueReinitInBlockTest here 2
110+
m.doSomething()
111+
k = Klass() // Set breakpoint copyableVarTestCCFlowTrueReinitInBlockTest here 3
112+
k.doSomething() // Set breakpoint copyableVarTestCCFlowTrueReinitInBlockTest here 4
113+
}
114+
k.doSomething() // Set breakpoint copyableVarTestCCFlowTrueReinitInBlockTest here 5
115+
}
116+
117+
public func copyableVarTestCCFlowFalseReinitOutOfBlockTest() {
118+
var k = Klass() // Set breakpoint copyableVarTestCCFlowFalseReinitOutOfBlockTest here 1
119+
k.doSomething() // Set breakpoint copyableVarTestCCFlowFalseReinitOutOfBlockTest here 2
120+
if falseBoolValue {
121+
let m = _move(k)
122+
m.doSomething()
123+
}
124+
k = Klass() // Set breakpoint copyableVarTestCCFlowFalseReinitOutOfBlockTest here 3
125+
k.doSomething() // Set breakpoint copyableVarTestCCFlowFalseReinitOutOfBlockTest here 4
126+
}
127+
128+
public func copyableVarTestCCFlowFalseReinitInBlockTest() {
129+
var k = Klass() // Set breakpoint copyableVarTestCCFlowFalseReinitInBlockTest here 1
130+
k.doSomething() // Set breakpoint copyableVarTestCCFlowFalseReinitInBlockTest here 2
131+
if falseBoolValue {
132+
let m = _move(k)
133+
m.doSomething()
134+
k = Klass()
135+
}
136+
k.doSomething() // Set breakpoint copyableVarTestCCFlowFalseReinitInBlockTest here 3
137+
}
138+
94139
//////////////////////////
95140
// Top Level Entrypoint //
96141
//////////////////////////
@@ -102,6 +147,10 @@ func main() {
102147
addressOnlyVarTest(Klass())
103148
copyableValueCCFTrueTest()
104149
copyableValueCCFFalseTest()
150+
copyableVarTestCCFlowTrueReinitOutOfBlockTest()
151+
copyableVarTestCCFlowTrueReinitInBlockTest()
152+
copyableVarTestCCFlowFalseReinitOutOfBlockTest()
153+
copyableVarTestCCFlowFalseReinitInBlockTest()
105154
}
106155

107156
main()

0 commit comments

Comments
 (0)