https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127756

            Bug ID: 127756
           Summary: constrained protected subtype deallocation omits
                    protected-object finalization
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ada
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hodong at nimfsoft dot com
                CC: dkm at gcc dot gnu.org
  Target Milestone: ---

Created attachment 65768
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65768&action=edit
Standalone Ada reproducer for constrained protected subtype cleanup

Environment
-----------

  Host:      FreeBSD 15.1 amd64
  Compiler:  GCC/GNAT 16.2.0
  Target:    x86_64-portbld-freebsd15.1
  Runtime:   POSIX/pthread GNAT tasking runtime

Files
-----

  protected_subtype_cleanup.adb
  gnat-protected-subtype-reproducer.c

The Ada reproducer declares a discriminated protected type with
Lock_Free => False, creates a constrained subtype, allocates 10,000 objects of
that subtype, and deallocates them with Ada.Unchecked_Deallocation.

The C helper uses GNU ld --wrap to count successful pthread_mutex_init and
pthread_mutex_destroy calls during the measured loop.

Build and run
-------------

  cc -std=c11 -O2 -Wall -Wextra -Werror \
      -c gnat-protected-subtype-reproducer.c -o mutex-counts.o

  gnatmake16 -q -f -gnat2022 -O2 protected_subtype_cleanup.adb \
      -o protected_subtype_cleanup \
      -largs mutex-counts.o \
      -Wl,--wrap=pthread_mutex_init \
      -Wl,--wrap=pthread_mutex_destroy

  ./protected_subtype_cleanup

With the affected GCC/GNAT 16.2.0 build, the output was:

  FAIL: initialized=10000 destroyed=0 errors=0 expected=10000

With a locally corrected GCC/GNAT 16.2.0 build, the output was:

  PASS: initialized=10000 destroyed=10000 errors=0 expected=10000

The corrected compiler was also tested with the same reproducer at -O0 and
-O2; both runs produced 10,000 successful initializations and 10,000
successful destructions.

Generated cleanup
-----------------

The generated Ada can be inspected with:

  gcc16 -c -gnat2022 -gnatG protected_subtype_cleanup.adb \
      > expanded.txt 2>&1

  grep -i 'initialize_protection\|finalize_protection' expanded.txt

In the affected build used for the reduction, Initialize_Protection was present
and Finalize_Protection was absent on the constrained-subtype deallocation
path.

With the locally corrected compiler, both calls are present. The deallocation
path contains a Finalize_Protection call for the generated _object field before
the object is freed.

Compiler source
---------------

The relevant GCC 16.2.0 code is Is_Simple_Protected_Type in
gcc/ada/exp_ch7.adb:

  function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
  begin
     return
       Is_Protected_Type (T)
         and then not Uses_Lock_Free (T)
         and then not Has_Entries (T)
         and then Is_RTE (Find_Protection_Type (T), RE_Protection);
  end Is_Simple_Protected_Type;

On the failing deallocation path, T is a constrained protected subtype. In the
locally corrected compiler used for comparison, the queried type is normalized
with Base_Type (T), and the protected-object representation checks are
performed
on that base type.

AI assistance disclosure
------------------------

This report and the standalone reproducer were prepared with assistance from
OpenAI ChatGPT (GPT-5.6 Sol, xhigh). All commands and reported results were
verified on the system described above.

Reply via email to