Home / Bundles / C++ Ada template nested types
cxx-ada-template-nested-types
C++ Ada template nested types
Concrete C++ class-template packages reference anonymous array field types without declaring them in the generated Ada specification.
Accepted Applies standalone Since 1.2.0
Explanation.
dump_ada_template writes each concrete class-template instance into a nested
Ada package, but it bypasses the nested-type prepass used for ordinary record
declarations. Array fields then refer to an anonymous Ada array type that the
package never declares.
Both a non-type argument and its defaulted form reach the same broken path:
template < typename T, unsigned N>
struct Buffer { T values[N]; };
template struct Buffer< int , 4 > ;
template < typename T = int , unsigned N = 2 >
struct Defaults { T values[N]; };
template struct Defaults< > ;The unpatched mapper emits references to internal anon_array... names but no
declarations for them (the numeric suffix is compiler-internal and varies):
package Buffer_int_4 is
type Buffer is limited record
values : aliased anon_array1712;
end record
with Convention => C_Pass_By_Copy;
end ;
package Defaults_int_2 is
type Defaults is limited record
values : aliased anon_array1713;
end record
with Convention => C_Pass_By_Copy;
end ;The corrected output declares each nested type before the record that uses it:
package Buffer_int_4 is
type anon_array1712 is array (0 .. 3 ) of aliased int;
type Buffer is limited record
values : aliased anon_array1712;
end record
with Convention => C_Pass_By_Copy;
end ;
package Defaults_int_2 is
type anon_array1713 is array (0 .. 1 ) of aliased int;
type Defaults is limited record
values : aliased anon_array1713;
end record
with Convention => C_Pass_By_Copy;
end ;The patch invokes the existing recursive nested-type prepass before printing a
concrete template record. The executable regression covers both template forms,
compiles their generated Ada, and passes both arrays to C++ at -O0 and -O2
to verify layout as well as syntax.
Run it against an unpatched or patched compiler root:
./bundles/cxx-ada-template-nested-types/run-test.sh \
TOOLCHAIN_ROOT GCC_VERSION unpatched
./bundles/cxx-ada-template-nested-types/run-test.sh \
TOOLCHAIN_ROOT GCC_VERSION patched
Patch.
SHA-256 85f8c81874baba2e24a5cbacd797935139790822eb7383d6d844d7a1c0de8044
Patch bundles/cxx-ada-template-nested-types/patches/gcc-13-14.patch
Download the patch
gcc/c-family/c-ada-spec.cc
+2 −0 modified
gcc/testsuite/g++.dg/ada-spec/template-nested-types.C
+37 −0 new file
SHA-256 a79edec02ccea6b8a2706132c55f358052c976906065a04ea4620de611fba0be
Patch bundles/cxx-ada-template-nested-types/patches/gcc-15-16.patch
Download the patch
gcc/c-family/c-ada-spec.cc
+2 −0 modified
gcc/testsuite/g++.dg/ada-spec/template-nested-types.C
+37 −0 new file
Tests.
Before the patch GNAT rejects both generated template packages because their anon_array field types are undefined.
After the patch Both packages declare their anonymous arrays, compile, and pass their records to C++ at -O0 and -O2.
template-nested-types.C
C++ · 37 lines
template < typename T, unsigned N>
struct Buffer
{
T values[N];
};
template struct Buffer< int , 4 > ;
template < typename T = int , unsigned N = 2 >
struct Defaults
{
T values[N];
};
template struct Defaults< > ;
extern "C" int
buffer_sum (const Buffer< int , 4 > * value)
{
return value-> values[0 ] + value-> values[1 ]
+ value-> values[2 ] + value-> values[3 ];
}
extern "C" int
defaults_sum (const Defaults< > * value)
{
return value-> values[0 ] + value-> values[1 ];
}
Download · View in repository
template_nested_types_consumer.adb
Ada · 17 lines
with Interfaces.C ; use Interfaces.C ;
with Template_Nested_Types_C;
procedure Template_Nested_Types_Consumer is
package Bindings renames Template_Nested_Types_C;
Buffer_Value : aliased Bindings.Buffer_Int_4.Buffer :=
(values => (1 , 2 , 3 , 4 ));
Defaults_Value : aliased Bindings.Defaults_Int_2.Defaults :=
(values => (5 , 6 ));
begin
if Bindings.buffer_sum (Buffer_Value'Access ) /= 10
or else Bindings.defaults_sum (Defaults_Value'Access ) /= 11
then
raise Program_Error with "template array layout or binding is wrong" ;
end if ;
end Template_Nested_Types_Consumer;
Download · View in repository
run-test.sh
shell · 79 lines
set -euo pipefail
if [[ $# -ne 3 ]]; then
echo "usage: $0 TOOLCHAIN_ROOT GCC_VERSION unpatched|patched" > & 2
exit 2
fi
root=$(cd "$(dirname " ${BASH_SOURCE[0 ]}")/../.." && pwd)
source "$root/scripts/regression-common.sh"
resolve_regression_toolchain "$1"
version=$2
state=$3
[[ "$state" == unpatched || "$state" == patched ]] || {
echo "error: state must be unpatched or patched" > & 2
exit 2
}
gxx="$REGRESSION_TOOLCHAIN/bin/g++"
[[ -x "$gxx" ]] || {
echo "error: no g++ in $REGRESSION_TOOLCHAIN" > & 2
exit 1
}
cxx_fixture="$root/bundles/cxx-ada-template-nested-types/tests/template-nested-types.C"
ada_fixture="$root/bundles/cxx-ada-template-nested-types/tests/template_nested_types_consumer.adb"
work=$(mktemp -d "${TMPDIR:-/tmp}/gnat-cxx-ada-template-nested.XXXXXX" )
trap 'rm -rf "$work"' EXIT
for optimization in 0 2 ; do
case_dir="$work/O$optimization"
mkdir -p "$case_dir"
cp "$cxx_fixture" "$ada_fixture" "$case_dir/"
(
cd "$case_dir"
"${REGRESSION_ENV[@]}" "$gxx" -std=gnu++20 -c "-O$optimization" \
-fdump-ada-spec-slim template-nested-types.C
)
spec="$case_dir/template_nested_types_c.ads"
[[ -f "$spec" ]] || {
echo "error: g++ did not generate $spec" > & 2
exit 1
}
set +e
(
cd "$case_dir"
"${REGRESSION_ENV[@]}" "$REGRESSION_GNATMAKE" -q -f \
"-O$optimization" template_nested_types_consumer.adb \
-largs template-nested-types.o -lstdc++
"${REGRESSION_ENV[@]}" ./template_nested_types_consumer
) > "$case_dir/run.log" 2 > & 1
run_status=$?
set -e
if [[ "$state" == unpatched ]]; then
[[ $run_status -ne 0 ]] || {
echo "error: unpatched template nested-type regression unexpectedly passed" > & 2
exit 1
}
grep -Eiq 'anon_array.*undefined' "$case_dir/run.log" || {
cat "$case_dir/run.log"
exit 1
}
echo "cxx-ada-template-nested-types -O$optimization: expected missing type (GCC $version)"
continue
fi
[[ $run_status -eq 0 ]] || {
cat "$case_dir/run.log"
exit 1
}
[[ $(grep -Ec 'type anon_array[0-9]+ is array' "$spec" ) -eq 2 ]] || {
echo "error: expected two package-local anonymous array declarations" > & 2
exit 1
}
echo "cxx-ada-template-nested-types -O$optimization: patched (GCC $version)"
done
Download · View in repository
Commands.
Apply the patch
patch --fuzz=0 -p1 -i bundles/cxx-ada-template-nested-types/patches/VARIANT.patchBuild the compiler
PATH=/path/to/bootstrap/bin:$PATH ./scripts/build-gnat.sh SOURCE BUILD INSTALLRun the regression
./scripts/run-regressions.sh INSTALL 1 .2 .0 GCC_MAJOR patched
Affected releases 13.2.014.2.015.3.016.1.016.2.0Files modified gcc/c-family/c-ada-spec.ccgcc/testsuite/g++.dg/ada-spec/template-nested-types.CRegression tests gcc/testsuite/g++.dg/ada-spec/template-nested-types.C
Before the patch GNAT rejects both generated template packages because their anon_array field types are undefined.
After the patch Both packages declare their anonymous arrays, compile, and pass their records to C++ at -O0 and -O2.
Upstream issue Pending GCC Bugzilla filing.
Upstream submission Not yet filed or submitted upstream.
Provenance Repository-authored GCC patch and executable regression; exact application verified locally against the pinned Darwin release identities. Pinned FSF release application is required by Linux CI.
Licensing GCC-derived compiler hunks remain GPL-3.0-or-later. The new test is proposed for the GCC testsuite under GCC project terms.
Repository fixture bundles/cxx-ada-template-nested-types/tests/template-nested-types.C
Fixture SHA-256 76e26b3452197d34e248b1739b50e9e78f51fd4cdca9bfd46e70b6b6c582a963
Test runner bundles/cxx-ada-template-nested-types/run-test.sh