Skip to content

Commit 0c0bece

Browse files
committed
fbc: sf.net #699: fix new[0] causing infinite loop when calling constructor/destructor list
1 parent 402520c commit 0c0bece

File tree

5 files changed

+240
-10
lines changed

5 files changed

+240
-10
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Version 1.06.0
7373
- #801: *@(expr) solved to (expr) did not cleanly remove null ptr checks allowing invalid datatype assignment with -exx. *PTRCHK(@expr) solves to (expr).
7474
- #880: Overload binary operators now support covariant arguments, overloaded procedure resolution changed especially with respect to CONST and non-CONST parameters
7575
- Fix for debugging lines in include files but not in procedures. Filename debugging information added for module level statements in included files.
76+
- #699: fix new[0] causing infinite loop when calling constructor/destructor list
7677

7778

7879
Version 1.05.0

src/compiler/ast-helper.bas

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,70 @@ end function
284284
'' loops
285285
''
286286

287+
'' While Counter:
288+
''
289+
'' CNT = INIVALUE
290+
'' WHILE( CNT )
291+
'' CNT -= 1
292+
'' <user code>
293+
'' WEND
294+
295+
function astBuildWhileCounterBegin _
296+
( _
297+
byval tree as ASTNODE ptr, _
298+
byval cnt as FBSYMBOL ptr, _
299+
byval label as FBSYMBOL ptr, _
300+
byval exitlabel as FBSYMBOL ptr, _
301+
byval initexpr as ASTNODE ptr, _
302+
byval flush_label as integer _
303+
) as ASTNODE ptr
304+
305+
'' counter = initvalue
306+
tree = astNewLINK( tree, astBuildVarAssign( cnt, initexpr ) )
307+
308+
'' do
309+
tree = astNewLINK( tree, astNewLABEL( label, flush_label ) )
310+
311+
'' if( counter = 0 ) then
312+
'' goto exitlabel
313+
'' end if
314+
tree = astNewLINK( tree, _
315+
astBuildBranch( _
316+
astNewBOP( AST_OP_EQ, astNewVAR( cnt ), astNewCONSTi( 0 ) ), _
317+
exitlabel, TRUE ) )
318+
319+
function = tree
320+
end function
321+
322+
function astBuildWhileCounterEnd _
323+
( _
324+
byval tree as ASTNODE ptr, _
325+
byval cnt as FBSYMBOL ptr, _
326+
byval label as FBSYMBOL ptr, _
327+
byval exitlabel as FBSYMBOL ptr, _
328+
byval flush_label as integer _
329+
) as ASTNODE ptr
330+
331+
'' counter -= 1
332+
tree = astNewLINK( tree, astBuildVarInc( cnt, -1 ) )
333+
334+
'' goto label
335+
tree = astNewLINK( tree, astNewBranch( AST_OP_JMP, label ) )
336+
337+
'' loop
338+
tree = astNewLINK( tree, astNewLABEL( exitlabel, flush_label ) )
339+
340+
function = tree
341+
end function
342+
343+
'' For:
344+
''
345+
'' CNT = INIVALUE
346+
'' DO
347+
'' <user code>
348+
'' CNT += 1
349+
'' LOOP UNTIL CNT=ENDVALUE
350+
287351
function astBuildForBegin _
288352
( _
289353
byval tree as ASTNODE ptr, _

src/compiler/ast-node-mem.bas

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,29 +60,30 @@ private function hCallCtorList _
6060
byval subtype as FBSYMBOL ptr _
6161
) as ASTNODE ptr
6262

63-
dim as FBSYMBOL ptr cnt = any, label = any, iter = any
63+
dim as FBSYMBOL ptr cnt = any, label = any, exitlabel = any, iter = any
6464
dim as ASTNODE ptr tree = any
6565

6666
cnt = symbAddTempVar( FB_DATATYPE_UINT )
6767
label = symbAddLabel( NULL )
68+
exitlabel = symbAddLabel( NULL )
6869
iter = symbAddTempVar( typeAddrOf( dtype ), subtype )
6970

7071
'' iter = @vector[0]
7172
tree = astBuildVarAssign( iter, astNewVAR( tmp ), AST_OPOPT_ISINI )
7273

73-
'' for cnt = 0 to elements-1
74+
'' while( cnt )
7475
'' Note: Using a non-flushing LABEL here because the LABEL node will
7576
'' end up as part of an expression tree, not as a "standalone statement"
76-
tree = astBuildForBegin( tree, cnt, label, 0, FALSE /' non-flushing '/ )
77+
tree = astBuildWhileCounterBegin( tree, cnt, label, exitlabel, elementsexpr, FALSE /' non-flushing '/ )
7778

7879
'' ctor( *iter )
7980
tree = astNewLINK( tree, astBuildCtorCall( subtype, astBuildVarDeref( iter ) ) )
8081

8182
'' iter += 1
8283
tree = astNewLINK( tree, astBuildVarInc( iter, 1 ) )
8384

84-
'' next
85-
tree = astBuildForEnd( tree, cnt, label, elementsexpr )
85+
'' wend
86+
tree = astBuildWhileCounterEnd( tree, cnt, label, exitlabel )
8687

8788
'' Wrap into LOOP node so astCloneTree() can clone the label and update
8889
'' the loop code, because it's part of the new[] expression, and not
@@ -261,11 +262,12 @@ function astBuildNewOp _
261262
end function
262263

263264
private function hCallDtorList( byval ptrexpr as ASTNODE ptr ) as ASTNODE ptr
264-
dim as FBSYMBOL ptr cnt = any, label = any, iter = any, elmts = any
265+
dim as FBSYMBOL ptr cnt = any, label = any, exitlabel = any, iter = any, elmts = any
265266
dim as ASTNODE ptr tree = any, expr = any
266267

267268
cnt = symbAddTempVar( FB_DATATYPE_INTEGER )
268269
label = symbAddLabel( NULL )
270+
exitlabel = symbAddLabel( NULL )
269271
iter = symbAddTempVar( ptrexpr->dtype, ptrexpr->subtype )
270272
elmts = symbAddTempVar( FB_DATATYPE_INTEGER )
271273

@@ -291,17 +293,17 @@ private function hCallDtorList( byval ptrexpr as ASTNODE ptr ) as ASTNODE ptr
291293
AST_OPOPT_DEFAULT or AST_OPOPT_DOPTRARITH ), _
292294
AST_OPOPT_ISINI ) )
293295

294-
'' for cnt = 0 to elmts-1
295-
tree = astBuildForBegin( tree, cnt, label, 0 )
296+
'' while( counter )
297+
tree = astBuildWhileCounterBegin( tree, cnt, label, exitlabel, astNewVAR( elmts ) )
296298

297299
'' iter -= 1
298300
tree = astNewLINK( tree, astBuildVarInc( iter, -1 ) )
299301

300302
'' dtor( *iter )
301303
tree = astNewLINK( tree, astBuildVarDtorCall( astBuildVarDeref( iter ) ) )
302304

303-
'' next
304-
tree = astBuildForEnd( tree, cnt, label, astNewVAR( elmts ) )
305+
'' wend
306+
tree = astBuildWhileCounterEnd( tree, cnt, label, exitlabel )
305307

306308
function = tree
307309
end function

src/compiler/ast.bi

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,25 @@ declare function astBuildDtorCall _
11741174
byval ignore_virtual as integer = FALSE _
11751175
) as ASTNODE ptr
11761176

1177+
declare function astBuildWhileCounterBegin _
1178+
( _
1179+
byval tree as ASTNODE ptr, _
1180+
byval cnt as FBSYMBOL ptr, _
1181+
byval label as FBSYMBOL ptr, _
1182+
byval exitlabel as FBSYMBOL ptr, _
1183+
byval initexpr as ASTNODE ptr, _
1184+
byval flush_label as integer = TRUE _
1185+
) as ASTNODE ptr
1186+
1187+
declare function astBuildWhileCounterEnd _
1188+
( _
1189+
byval tree as ASTNODE ptr, _
1190+
byval cnt as FBSYMBOL ptr, _
1191+
byval label as FBSYMBOL ptr, _
1192+
byval exitlabel as FBSYMBOL ptr, _
1193+
byval flush_label as integer = TRUE _
1194+
) as ASTNODE ptr
1195+
11771196
declare function astBuildForBegin _
11781197
( _
11791198
byval tree as ASTNODE ptr, _

tests/pointers/new-delete.bas

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,34 +404,41 @@ SUITE( fbc_tests.pointers.new_delete )
404404
end type
405405

406406
dim shared as integer T2_ctor_count = 0
407+
dim shared as integer T2_ctor_count_x = 0
407408
type T2
408409
as integer i
409410
declare constructor( )
410411
end type
411412
constructor T2( )
412413
T2_ctor_count += 1
414+
T2_ctor_count_x += 1
413415
end constructor
414416

415417
dim shared as integer T3_dtor_count = 0
418+
dim shared as integer T3_dtor_count_x = 0
416419
type T3
417420
as integer i
418421
declare destructor( )
419422
end type
420423
destructor T3( )
421424
T3_dtor_count += 1
425+
T3_dtor_count_x += 1
422426
end destructor
423427

424428
dim shared as integer T4_ctor_count = 0, T4_dtor_count = 0
429+
dim shared as integer T4_ctor_count_x = 0, T4_dtor_count_x = 0
425430
type T4
426431
as integer i
427432
declare constructor( )
428433
declare destructor( )
429434
end type
430435
constructor T4( )
431436
T4_ctor_count += 1
437+
T4_ctor_count_x += 1
432438
end constructor
433439
destructor T4( )
434440
T4_dtor_count += 1
441+
T4_dtor_count_x += 1
435442
end destructor
436443

437444
TEST( default )
@@ -557,6 +564,18 @@ SUITE( fbc_tests.pointers.new_delete )
557564
delete[] p
558565
end scope
559566

567+
scope
568+
var p = new T1[0]
569+
CU_ASSERT( p <> NULL )
570+
delete[] p
571+
end scope
572+
573+
scope
574+
var p = new T1[1]
575+
CU_ASSERT( p[0].i = 0 )
576+
delete[] p
577+
end scope
578+
560579
scope
561580
var p = new T1[2]
562581
CU_ASSERT( p[0].i = 0 )
@@ -572,13 +591,54 @@ SUITE( fbc_tests.pointers.new_delete )
572591
delete[] p
573592
end scope
574593

594+
for n as integer = 0 to 2
595+
var p = new T1[n]
596+
CU_ASSERT( p <> NULL )
597+
delete[] p
598+
next
599+
600+
'' new T2[N]
601+
CU_ASSERT( T2_ctor_count_x = 0 )
575602
scope
576603
CU_ASSERT( T2_ctor_count = 0 )
577604
var p = new T2[2]
578605
CU_ASSERT( T2_ctor_count = 2 )
579606
delete[] p
580607
end scope
581608

609+
scope
610+
T2_ctor_count_x = 0
611+
var p = new T2[0]
612+
CU_ASSERT( p <> NULL )
613+
CU_ASSERT( T2_ctor_count_x = 0 )
614+
delete[] p
615+
end scope
616+
617+
scope
618+
T2_ctor_count_x = 0
619+
var p = new T2[1]
620+
CU_ASSERT( T2_ctor_count_x = 1 )
621+
delete[] p
622+
end scope
623+
624+
scope
625+
T2_ctor_count_x = 0
626+
var p = new T2[2]
627+
CU_ASSERT( T2_ctor_count_x = 2 )
628+
delete[] p
629+
end scope
630+
631+
for n as integer = 0 to 2
632+
T2_ctor_count_x = 0
633+
var p = new T2[n]
634+
CU_ASSERT( p <> NULL )
635+
CU_ASSERT( T2_ctor_count_x = n )
636+
delete[] p
637+
next
638+
639+
'' new T3[N]
640+
CU_ASSERT( T3_dtor_count_x = 0 )
641+
582642
scope
583643
CU_ASSERT( T3_dtor_count = 0 )
584644
var p = new T3[2]
@@ -587,6 +647,43 @@ SUITE( fbc_tests.pointers.new_delete )
587647
CU_ASSERT( T3_dtor_count = 2 )
588648
end scope
589649

650+
scope
651+
T3_dtor_count_x = 0
652+
var p = new T3[0]
653+
CU_ASSERT( p <> NULL )
654+
CU_ASSERT( T3_dtor_count_x = 0 )
655+
delete[] p
656+
CU_ASSERT( T3_dtor_count_x = 0 )
657+
end scope
658+
659+
scope
660+
T3_dtor_count_x = 0
661+
var p = new T3[1]
662+
CU_ASSERT( T3_dtor_count_x = 0 )
663+
delete[] p
664+
CU_ASSERT( T3_dtor_count_x = 1 )
665+
end scope
666+
667+
scope
668+
T3_dtor_count_x = 0
669+
var p = new T3[2]
670+
CU_ASSERT( T3_dtor_count_x = 0 )
671+
delete[] p
672+
CU_ASSERT( T3_dtor_count_x = 2 )
673+
end scope
674+
675+
for n as integer = 0 to 2
676+
T3_dtor_count_x = 0
677+
var p = new T3[n]
678+
CU_ASSERT( p <> NULL )
679+
CU_ASSERT( T3_dtor_count_x = 0 )
680+
delete[] p
681+
CU_ASSERT( T3_dtor_count_x = n )
682+
next
683+
684+
'' new T4[N]
685+
CU_ASSERT( T4_ctor_count_x = 0 )
686+
590687
scope
591688
CU_ASSERT( T4_ctor_count = 0 )
592689
CU_ASSERT( T4_dtor_count = 0 )
@@ -597,6 +694,53 @@ SUITE( fbc_tests.pointers.new_delete )
597694
CU_ASSERT( T4_ctor_count = 2 )
598695
CU_ASSERT( T4_dtor_count = 2 )
599696
end scope
697+
698+
scope
699+
T4_ctor_count_x = 0
700+
T4_dtor_count_x = 0
701+
var p = new T4[0]
702+
CU_ASSERT( p <> NULL )
703+
CU_ASSERT( T4_ctor_count_x = 0 )
704+
CU_ASSERT( T4_dtor_count_x = 0 )
705+
delete[] p
706+
CU_ASSERT( T4_ctor_count_x = 0 )
707+
CU_ASSERT( T4_dtor_count_x = 0 )
708+
end scope
709+
710+
scope
711+
T4_ctor_count_x = 0
712+
T4_dtor_count_x = 0
713+
var p = new T4[1]
714+
CU_ASSERT( T4_ctor_count_x = 1 )
715+
CU_ASSERT( T4_dtor_count_x = 0 )
716+
delete[] p
717+
CU_ASSERT( T4_ctor_count_x = 1 )
718+
CU_ASSERT( T4_dtor_count_x = 1 )
719+
end scope
720+
721+
scope
722+
T4_ctor_count_x = 0
723+
T4_dtor_count_x = 0
724+
var p = new T4[2]
725+
CU_ASSERT( T4_ctor_count_x = 2 )
726+
CU_ASSERT( T4_dtor_count_x = 0 )
727+
delete[] p
728+
CU_ASSERT( T4_ctor_count_x = 2 )
729+
CU_ASSERT( T4_dtor_count_x = 2 )
730+
end scope
731+
732+
for n as integer = 0 to 2
733+
T4_ctor_count_x = 0
734+
T4_dtor_count_x = 0
735+
var p = new T4[n]
736+
CU_ASSERT( p <> NULL )
737+
CU_ASSERT( T4_ctor_count_x = n )
738+
CU_ASSERT( T4_dtor_count_x = 0 )
739+
delete[] p
740+
CU_ASSERT( T4_ctor_count_x = n )
741+
CU_ASSERT( T4_dtor_count_x = n )
742+
next
743+
600744
END_TEST
601745
END_TEST_GROUP
602746

0 commit comments

Comments
 (0)