-- C761002.A -- -- Grant of Unlimited Rights -- -- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687, -- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained -- unlimited rights in the software and documentation contained herein. -- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making -- this public release, the Government intends to confer upon all -- recipients unlimited rights equal to those held by the Government. -- These rights include rights to use, duplicate, release or disclose the -- released technical data and computer software in whole or in part, in -- any manner and for any purpose whatsoever, and to have or permit others -- to do so. -- -- DISCLAIMER -- -- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR -- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED -- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE -- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE -- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A -- PARTICULAR PURPOSE OF SAID MATERIAL. --* -- -- OBJECTIVE: -- Check that objects of a controlled type that are created -- by an allocator are finalized at the appropriate time. In -- particular, check that such objects are not finalized due to -- completion of the master in which they were allocated if the -- corresponding access type is declared outside of that master. -- -- Check that Unchecked_Deallocation of a controlled -- object causes finalization of that object. -- -- TEST DESCRIPTION: -- This test derives a type from Ada.Finalization.Controlled, and -- declares access types to that type in various scope scenarios. -- The dispatching procedure Finalize is redefined for the derived -- type to perform a check that it has been called at the -- correct time. This is accomplished using a global variable -- which indicates what state the software is currently -- executing. The test utilizes the TCTouch facilities to -- verify that Finalize is called the correct number of times, at -- the correct times. Several calls are made to validate passing -- the null string to check that Finalize has NOT been called at -- that point. -- -- -- CHANGE HISTORY: -- 06 Dec 94 SAIC ACVC 2.0 -- --! with Ada.Finalization; package C761002_0 is type Global is new Ada.Finalization.Controlled with null record; procedure Finalize( It: in out Global ); type Second is new Ada.Finalization.Limited_Controlled with null record; procedure Finalize( It: in out Second ); end C761002_0; with Report; with TCTouch; package body C761002_0 is procedure Finalize( It: in out Global ) is begin TCTouch.Touch('F'); ------------------------------------------------- F end Finalize; procedure Finalize( It: in out Second ) is begin TCTouch.Touch('S'); ------------------------------------------------- S end Finalize; end C761002_0; with Report; with TCTouch; with C761002_0; with Unchecked_Deallocation; procedure C761002 is -- check the straightforward case procedure Subtest_1 is type Access_1 is access C761002_0.Global; V1 : Access_1; procedure Allocate is V2 : Access_1; begin V2 := new C761002_0.Global; V1 := V2; -- "dead" assignment must not be optimized away due to -- finalization "side effects", many more of these follow end Allocate; begin Allocate; -- no calls to Finalize should have occurred at this point TCTouch.Validate("","Allocated nested, retained"); end Subtest_1; -- check Unchecked_Deallocation procedure Subtest_2 is type Access_2 is access C761002_0.Global; procedure Free is new Unchecked_Deallocation(C761002_0.Global, Access_2); V1 : Access_2; V2 : Access_2; procedure Allocate is begin V1 := new C761002_0.Global; V2 := new C761002_0.Global; end Allocate; begin Allocate; -- no calls to Finalize should have occurred at this point. TCTouch.Validate("","Allocated nested, non-local"); Free(V1); -- instance of Unchecked_Deallocation -- should cause the finalization of V1.all TCTouch.Validate("F","Unchecked Deallocation"); end Subtest_2; -- leaving this scope should cause the finalization of V2.all -- check various master-exit scenarios -- the "Fake" parameters are used to avoid unwanted optimizations procedure Subtest_3 is procedure With_Local_Block is type Access_3 is access C761002_0.Global; V1 : Access_3; begin declare V2 : Access_3 := new C761002_0.Global; begin V1 := V2; end; TCTouch.Validate("","Local Block, normal exit"); -- the allocated object should be finalized on leaving this scope end With_Local_Block; procedure With_Local_Block_Return(Fake: Integer) is type Access_4 is access C761002_0.Global; V1 : Access_4 := new C761002_0.Global; begin if Fake = 0 then declare V2 : Access_4; begin V2 := new C761002_0.Global; return; -- the two allocated objects should be finalized end; -- upon leaving this scope else V1 := null; end if; end With_Local_Block_Return; procedure With_Goto(Fake: Integer) is type Access_5 is access C761002_0.Global; V1 : Access_5 := new C761002_0.Global; V2 : Access_5; V3 : Access_5; begin if Fake = 0 then declare type Access_6 is access C761002_0.Second; V6 : Access_6; begin V6 := new C761002_0.Second; goto check; end; else V2 := V1; end if; V3 := V2; <> TCTouch.Validate("S","goto past master end"); end With_Goto; begin With_Local_Block; TCTouch.Validate("F","Local Block, normal exit, after master"); With_Local_Block_Return( Report.Ident_Int(0) ); TCTouch.Validate("FF","Local Block, return from block"); With_Goto( Report.Ident_Int(0) ); TCTouch.Validate("F","With Goto"); end Subtest_3; procedure Subtest_4 is Oops : exception; procedure Alley( Fake: Integer ) is type Access_1 is access C761002_0.Global; V1 : Access_1; begin V1 := new C761002_0.Global; if Fake = 1 then raise Oops; end if; V1 := null; end Alley; begin Catch: begin Alley( Report.Ident_Int(1) ); exception when Oops => TCTouch.Validate("F","leaving via exception"); when others => Report.Failed("Wrong exception"); end Catch; end Subtest_4; begin -- Main test procedure. Report.Test ("C761002", "Check that objects of a controlled type created " & "by an allocator are finalized appropriately. " & "Check that Unchecked_Deallocation of a " & "controlled object causes finalization " & "of that object" ); Subtest_1; -- leaving the scope of the access type should finalize the -- collection TCTouch.Validate("F","Allocated nested, Subtest 1"); Subtest_2; -- Unchecked_Deallocation already finalized one of the two -- objects allocated, the other should be the only one finalized -- at leaving the scope of the access type. TCTouch.Validate("F","Allocated non-local"); Subtest_3; -- there should be no remaining finalizations from this subtest TCTouch.Validate("","Localized objects"); Subtest_4; -- there should be no remaining finalizations from this subtest TCTouch.Validate("","Exception testing"); Report.Result; end C761002;