Panel cxx-ada-spec
C++ to Ada specification feature panel
This panel turns exploratory g++ -fdump-ada-spec observations into repeatable evidence. It separates three outcomes that need different treatment: Driver options: -fdump-ada-spec, -fdump-ada-spec-slim. Compilers: 13.2.0, 14.2.0, 15.3.0, 16.2.0.
45 features
63 atomic cases
16 pairwise cases
32 grammar cases
22 runtime suites
States.
- Verified working 15
- Exercised end to end. The generated Ada compiles and behaves as the C++ does.
- Fixed by a shipped bundle 21
- A mapper defect with a bundle in the published patchset.
- Fixed by a staged bundle 7
- A mapper defect whose bundle is held out of the published patchset.
- Bounded, not a defect 2
- A boundary rather than a defect: Ada cannot represent the construct directly, or the mapper does not emit it.
Class.
| Feature | State | Evidence |
|---|---|---|
constructors-destructors |
Verified working | panels/cxx-ada-spec/cases/core-language |
data-members-layout |
Verified working with a guard | panels/cxx-ada-spec/cases/core-languageGenerated bindings expose layout. Compare Object_Size with compiler-produced sizeof values because Itanium mangling does not encode member layout. |
Data layout.
| Feature | State | Evidence |
|---|---|---|
inherited-tail-padding-layout |
Staged | cxx-ada-inherited-tail-paddingThe staged bundle preserves the base subobject data size separately from its complete-object size and emits exact component positions for C++ tail-padding reuse. The nested primary-base component it selects is emitted by the staged virtual-base layout path, so patchset 1.2.0 does not ship it. |
empty-class-object-size |
Staged | cxx-ada-empty-class-storageThe staged bundle separates a zero-size empty value from its nonzero complete-object allocation. It omits artificial empty bases and only a no_unique_address selector that actually overlaps another field; naming that omitted C++ subobject requires an accessor wrapper. It reuses the staged tail-padding machinery, so patchset 1.2.0 does not ship it. |
enums-bitfields-unions |
Verified runtime | panels/cxx-ada-spec/cases/abi-layout panels/cxx-ada-spec/cases/call-abi panels/cxx-ada-spec/generated/catalog.pyNamed enums, bit-fields, and unions compile; their size, alignment, and by-value runtime behavior are checked. |
explicit-alignment |
Fixed by a bundle | cxx-ada-explicit-alignmentPatchset 1.2.0 emits the user-specified alignment independently of packed layout. |
Dispatch.
| Feature | State | Evidence |
|---|---|---|
virtual-methods |
Verified working | panels/cxx-ada-spec/cases/core-language |
derived-class-new-virtual-slots |
Staged | cxx-ada-derived-virtual-slotsThe staged bundle gives complete and deleting destructors hierarchy-stable Ada names so they override their inherited slots. Virtuals introduced later in a derived class then retain the C++ vtable indices, including through recursively nested concrete secondary bases. Patchset 1.2.0 does not ship this. |
Function.
| Feature | State | Evidence |
|---|---|---|
overloaded-methods |
Verified working | panels/cxx-ada-spec/cases/core-language |
static-methods |
Verified working | panels/cxx-ada-spec/cases/core-language |
operators-conversions |
Verified ada compile | panels/cxx-ada-spec/generated/catalog.pyoperatorsconversion_operators |
method-cv-overloads |
Fixed by a bundle | cxx-ada-qualified-method-names |
method-ref-qualifier-overloads |
Fixed by a bundle | cxx-ada-qualified-method-names |
copy-move-special-members |
Fixed by a bundle | cxx-ada-qualified-method-namesPatchset 1.2.0 gives move assignment a distinct Ada name. |
Inheritance.
| Feature | State | Evidence |
|---|---|---|
single-inheritance |
Verified working | panels/cxx-ada-spec/cases/core-languageThe positive case avoids inherited tail-padding reuse and checks both Ada and C++ object sizes. |
multiple-inheritance-interface-secondary |
Verified working | panels/cxx-ada-spec/cases/interface-secondary-baseThe dumper maps a pure abstract, data-free secondary base to a limited interface; the runtime test verifies Ada dispatch and secondary-base pointer adjustment. |
multiple-inheritance-concrete-secondary |
Staged with access view | panels/cxx-ada-spec/generated/catalog.pyconcrete_multiple_inheritance cxx-ada-concrete-multiple-inheritance cxx-ada-virtual-diamond-layout panels/cxx-ada-spec/cases/recursive-secondary-baseThe staged bundle maps the C++ primary base to Ada inheritance and each additional concrete base to exact nested as-base storage. Access-view conversions at nested component addresses support secondary virtual dispatch, including a secondary base that itself has concrete primary and secondary bases; dynamic virtual-base conversions remain an ABI boundary. Patchset 1.2.0 does not ship this; an unstaged compiler still omits every secondary base subobject. |
virtual-inheritance-layout |
Staged | cxx-ada-virtual-inheritance-layoutThe staged bundle preserves complete size, alignment, direct-member position, and virtual-base position while leaving the hidden ABI pointer as an opaque gap. Patchset 1.2.0 does not ship this. |
virtual-diamond-as-base-layout |
Staged | cxx-ada-virtual-diamond-layoutThe staged bundle emits shortened storage types for non-polymorphic direct bases that omit their shared virtual base, preserving all visible diamond fields without duplicating the root. Patchset 1.2.0 does not ship this. |
Library.
| Feature | State | Evidence |
|---|---|---|
standard-library-nontrivial-values |
Facade required | panels/cxx-ada-spec/cases/stdlib-value-facadeA slim std::string-by-value dump references missing transitive Ada units. The executable case keeps std::string ownership in C++ and crosses a C-compatible data-and-length facade instead. |
Name lookup.
| Feature | State | Evidence |
|---|---|---|
namespace-collisions |
Fixed by a bundle | cxx-ada-namespace-identityPatchset 1.2.0 preserves complete named namespace paths in generated Ada identifiers. |
enclosing-type-method-name-collisions |
Fixed by a bundle | cxx-ada-enclosing-type-method-namesPatchset 1.2.0 gives only a method that collides case-insensitively with its enclosing type a stable Method suffix while retaining the C++ external symbol. |
profile-formal-type-name-collisions |
Fixed by a bundle | cxx-ada-profile-formal-type-namesPatchset 1.2.0 prefixes a formal when its Ada identifier would hide its own type, a later formal's type, or the result type. |
visible-type-method-name-collisions |
Fixed by a bundle | cxx-ada-visible-type-method-namesPatchset 1.2.0 gives a method a stable Method suffix when its identifier collides with a type made visible from another generated class package. |
nested-classes-anonymous-scopes |
Verified ada compile | panels/cxx-ada-spec/generated/catalog.pynested_classanonymous_namespacenested_namespace |
ada-casefold-collisions |
Fixed by a bundle | cxx-ada-casefold-identityPatchset 1.2.0 assigns stable scope-local suffixes to later case variants and all of their references. |
generated-name-collisions |
Staged | cxx-ada-generated-name-identityThe staged bundle reserves source spellings and gives only colliding synthesized declarations readable scope-local suffixes. It renames entities the staged ABI-layout bundles introduce and does not apply without them, so patchset 1.2.0 does not ship it. |
Runtime.
| Feature | State | Evidence |
|---|---|---|
exceptions |
Verified runtime interoperability | panels/cxx-ada-spec/generated/catalog.pyexception_throw panels/cxx-ada-spec/cases/exception-interoperabilityA C++ throw propagates into an Ada others handler at both optimization levels. A status-returning C facade is also verified for APIs that choose not to expose exceptions. GNAT's internal foreign-language identity API is version-dependent and is not part of this portable claim. |
scalar-call-abi |
Verified with target boundary | panels/cxx-ada-spec/cases/call-abiBoolean, signed-char, unsigned-long-long, float, and double mappings execute at both optimization levels. Long double also executes and must match except on Linux AArch64 toolchains where GNAT and C++ use incompatible target calling conventions; that explicit boundary does not suppress the remaining ABI oracles. |
Template.
| Feature | State | Evidence |
|---|---|---|
explicit-template-instantiations |
Verified working | cxx-ada-template-qualification |
external-template-instance-references |
Fixed by a bundle | cxx-ada-template-qualificationAliases, fields, parameters, and results need the generated instance-package qualifier. |
trivial-template-record-syntax |
Fixed by a bundle | cxx-ada-template-record-terminationPatchset 1.2.0 terminates the Convention aspect for trivial records emitted in concrete template packages. |
uninstantiated-templates |
Not emitted | panels/cxx-ada-spec/cases/uninstantiated-templatesThe dumper emits no declaration until the C++ template is explicitly instantiated; the executable case proves that the explicit instance is then emitted and usable. |
class-template-specializations |
Fixed by a bundle | panels/cxx-ada-spec/generated/catalog.pypartial_specializationfull_specializationPatchset 1.2.0 terminates the generated trivial records. |
advanced-template-parameters |
Fixed by a bundle | cxx-ada-template-nested-typesPatchset 1.2.0 declares anonymous array field types inside concrete packages with non-type or defaulted template arguments. |
template-template-parameters |
Fixed by a bundle | panels/cxx-ada-spec/generated/catalog.pytemplate_template_parameterPatchset 1.2.0 terminates the generated trivial record. |
nested-alias-constrained-templates |
Fixed by a bundle | panels/cxx-ada-spec/generated/catalog.pynested_templatealias_templateconstrained_templatePatchset 1.2.0 terminates trivial records and maps alias-template instances to the concrete type in their generated packages. |
Type system.
| Feature | State | Evidence |
|---|---|---|
references-rvalue-references |
Verified ada compile | panels/cxx-ada-spec/generated/catalog.pyfree_rvalue_references cxx-ada-qualified-method-namesPatchset 1.2.0 preserves lvalue- and rvalue-qualified method identity in stable Ada suffixes. |
cv-qualifiers-noexcept |
Verified ada compile | cxx-ada-qualified-method-names panels/cxx-ada-spec/generated/catalog.pynoexcept_default_argumentsPatchset 1.2.0 preserves cv-qualified method identity in stable Ada suffixes; noexcept/default arguments compile. |
data-member-pointers |
Fixed by a bundle | cxx-ada-member-pointersPatchset 1.2.0 preserves the Itanium ABI ptrdiff_t offset, including its -1 null representation; dereferencing remains a C++ operation. |
member-function-pointers |
Fixed by a bundle | cxx-ada-member-pointersPatchset 1.2.0 preserves the opaque two-word Itanium ABI representation, including nonvirtual, virtual, and null values; invocation remains a C++ operation. |
extended-character-types |
Fixed by a bundle | cxx-ada-char8-typePatchset 1.2.0 maps C++20 char8_t to ABI-equivalent Interfaces.C.unsigned_char; wchar_t, char16_t, and char32_t retain their existing mappings. |
complex-vector-types |
Patched with method wrapper boundary | cxx-ada-vector-types panels/cxx-ada-spec/generated/catalog.pycomplex_and_vectorComplex float types already mapped to Ada.Numerics complex units. Patchset 1.2.0 replaces vector placeholders with aligned GNAT machine-vector arrays. Free and C-wrapper profiles use the direct vector calling convention; direct Ada dispatch to a vector-bearing C++ method is not portable across the tested compiler/target matrix. |
anonymous-enum-constants |
Fixed by a bundle | cxx-ada-anonymous-enumsPatchset 1.2.0 emits sequential enumerations or integer-subtype constants and maps signature references consistently to the synthetic type. |
integer-128 |
Fixed by a bundle | cxx-ada-int128-typesPatchset 1.2.0 backports GCC 15's prefix recognition to GCC 13 and 14; GCC 15 and 16 are known-good controls. |
Runtime suites.
Each suite links C++ and Ada and runs at -O0 and -O2.
panels/cxx-ada-spec/cases/core-languagepanels/cxx-ada-spec/cases/abi-layoutpanels/cxx-ada-spec/cases/call-abipanels/cxx-ada-spec/cases/interface-secondary-basepanels/cxx-ada-spec/cases/exception-interoperabilitypanels/cxx-ada-spec/cases/uninstantiated-templatespanels/cxx-ada-spec/cases/stdlib-value-facadebundles/cxx-ada-template-qualificationbundles/cxx-ada-template-record-terminationbundles/cxx-ada-explicit-alignmentbundles/cxx-ada-namespace-identitybundles/cxx-ada-qualified-method-namesbundles/cxx-ada-casefold-identitybundles/cxx-ada-template-nested-typesbundles/cxx-ada-anonymous-enumsbundles/cxx-ada-char8-typebundles/cxx-ada-int128-typesbundles/cxx-ada-vector-typesbundles/cxx-ada-member-pointersbundles/cxx-ada-enclosing-type-method-namesbundles/cxx-ada-profile-formal-type-namesbundles/cxx-ada-visible-type-method-names
Method.
How the panel is built, and what it deliberately bounds The panel's own notes: probe layers, run states, target boundaries, and the limits it records rather than hides.
This panel turns exploratory g++ -fdump-ada-spec observations into repeatable
evidence. It separates three outcomes that need different treatment:
- a supported mapping, which gets a positive end-to-end C++/Ada case;
- a mapper defect, which gets an independent patch bundle with an executable before/after regression;
- a C++ construct Ada cannot represent directly, which is documented as a facade boundary rather than disguised as a mapper bug.
matrix.toml records feature-level conclusions. coverage.toml assigns every
atomic probe to a feature group, lists the runtime oracles, and states the
remaining limits. generated/coverage.py fails if a catalog probe is omitted
or assigned twice.
The panel runs in three states. unpatched characterizes the pinned upstream
compiler. patched is a compiler carrying exactly patchset 1.2.0, which is
what a release ships. staged additionally carries the staged bundles listed
under staged subjects. A patched run makes no claim about
a staged subject: it reports those suites as skipped rather than asserting
either the defect or the fix.
The executable panel currently has four layers:
- 63 isolated atomic probes cover types and layout, pointers and functions, templates, inheritance, names and linkage, and runtime/storage declarations. Each probe runs in its own directory, so one malformed dump cannot mask a later feature. Required declarations are checked before the generated Ada is compiled. Versioned expectation files distinguish successful mappings from repeatable invalid Ada and omissions.
- 16 generated cases cover all 88 value pairs across payload kind, reference carrier, C++ scope, qualifier, and full/slim dump mode. This is pairwise interaction coverage, not a hand-selected sample.
- 32 fixed-seed grammar cases combine three to seven declarations per translation unit, with periodic inheritance and overload clusters. They exercise higher-order interactions in the currently representable subset and alternate full and slim dump modes.
- Twenty-two shipped runtime suites, plus eight staged ones, link C++ and Ada at
-O0and-O2. They check scalar, enum, record, union, pointer, reference, and callback calling conventions; object size, alignment, and field offsets; ordinary, interface, and concrete secondary-base virtual dispatch, including recursively nested concrete bases; template qualification, record termination, nested types, explicit alignment, namespace and method identity—including enclosing-type, use-visible type/method, and subprogram-profile collisions—anonymous enumeration values, andchar8_t, 128-bit integers, machine vectors through a C++ method wrapper, and opaque pointer-to-member values; uninstantiated-template emission, a nontrivial standard-library value facade, C++ exception propagation into an Ada handler; and the exact behavior of known defects.
The call-ABI suite reports the long double result separately. On Linux
AArch64 with the pinned GCC 13--15 toolchains, GNAT and C++ disagree on that
target calling convention even though the mapper emits the standard
Interfaces.C.long_double declaration. That target/runtime boundary is
reported explicitly instead of stopping the suite, so enum, record, union,
pointer, reference, and callback oracles still execute. A mismatch on any
other target remains a failure.
The defect regressions reproduce malformed template records before patching, anonymous nested template types before patching, anonymous enum omissions before patching, pointer-to-member syntax failures, standalone empty-class storage drift, inherited tail-padding drift, explicit alignment before patching, virtual-inheritance, virtual-diamond, and concrete multiple-inheritance layout drift, unsigned 128-bit integer failures on GCC 13 and 14 before patching, and several version- or type-specific omissions. Independent problems must become independent patch bundles.
The coverage summary reports all three baselines. Patchset 1.2.0 leaves one
atomic case classified non-passing on every supported major:
concrete_multiple_inheritance, whose subject is staged. A staged compiler
passes all 63.
That atomic case does not merely require legal Ada. Dropping both base
subobjects also compiles, so the case requires the primary base as Ada
inheritance and the secondary base as its own storage view; a compiler without
the staged bundle reports spec-mismatch, not a false pass.
Its C++ classes declare virtual destructors deliberately. Without one the
mapper emits no base list at all, so both base subobjects vanish from the Ada
record even with the staged layout bundles applied. That is a distinct gap from
the one this probe characterizes and is recorded under coverage.toml limits;
it has no bundle yet.
The confirmed-history ledger is larger than that residual atomic count:
twenty-two independent C++ mapper defects have bundles introduced for 1.2.0 —
fifteen accepted into the patchset and seven staged — and no confirmed
fixed-layout runtime defect remains. Every linked bundle, accepted or staged,
contains the offending C++, the unpatched Ada output, the corrected Ada output,
and an executable -O0/-O2 before/after regression:
cxx-ada-template-qualification: references outside a concrete template package lose their instance qualifier;cxx-ada-template-record-termination: trivial concrete template records leave their Convention aspect unterminated;cxx-ada-explicit-alignment: explicitly over-aligned records retain only their natural Ada alignment;cxx-ada-namespace-identity: distinct named C++ namespaces collapse into duplicate Ada identifiers;cxx-ada-qualified-method-names: cv/ref-qualified overloads and move assignment collapse onto Ada homographs;cxx-ada-casefold-identity: C++ identifiers differing only by case collide in Ada;cxx-ada-template-nested-types: anonymous field types are emitted outside the concrete template package that needs them;cxx-ada-anonymous-enums: top-level anonymous enumerators and their synthetic type are omitted;cxx-ada-char8-type:char8_tmaps to a nonexistent Ada identifier;cxx-ada-int128-types: GCC 13 and 14 fail to recognize the unsigned internal 128-bit type name;cxx-ada-vector-types: machine vectors map to placeholders that cannot appear in profiles;cxx-ada-member-pointers: data- and function-member pointer representations are emitted without Ada types;cxx-ada-enclosing-type-method-names: a method collides case-insensitively with its enclosing Ada type;cxx-ada-profile-formal-type-names: a formal hides its own, a later formal's, or the result type;cxx-ada-visible-type-method-names: a method hides a type made visible from another generated class package.
Staged subjects
Patchset 1.2.0 does not ship these. They carry the same evidence as an
accepted bundle and run in the panel's staged state; a patched run skips
them and their eight runtime suites.
cxx-ada-inherited-tail-padding: Ada inheritance prevents C++ reuse of base tail padding and moves derived fields;cxx-ada-empty-class-storage: empty complete objects receive zero storage while overlapping empty subobjects are represented as ordinary fields;cxx-ada-virtual-inheritance-layout: virtual bases lose complete size, alignment, and field positions;cxx-ada-virtual-diamond-layout: direct diamond bases incorrectly include their shared virtual base as complete storage;cxx-ada-concrete-multiple-inheritance: additional concrete bases are emitted as illegal Ada progenitors instead of nested ABI storage;cxx-ada-derived-virtual-slots: class-specific destructor names shift later derived virtuals away from their C++ vtable slots;cxx-ada-generated-name-identity: readable synthesized names collide with user-written methods, aliases, formals, layout helpers, class packages, and special members.
The following list is only the work still open or intentionally bounded, not the complete defect history.
The remaining confirmed inventory is deliberately explicit:
- tested semantic boundaries rather than hidden mapper successes:
uninstantiated templates are not emitted, nontrivial standard-library values
require a facade, and dynamic virtual-base conversions remain ABI operations.
C++ exception propagation is tested and supported through Ada's portable
othershandler. GNAT's internal API for recovering the foreign language identity varies by runtime version and is not claimed as portable behavior; Linux AArch64long doubleinteroperability on affected GNAT releases is a compiler call-ABI boundary, not a mapper-spelling success. Direct Ada dispatch to vector-bearing C++ methods likewise requires a C++ wrapper, because tested GNAT versions do not classify that method ABI consistently.
Run the complete current panel against a compiler root:
./panels/cxx-ada-spec/run-panel.sh TOOLCHAIN_ROOT GCC_VERSION unpatchedUse patched after applying patchset 1.2.0, and staged after additionally
applying the staged bundles with scripts/apply-staged.sh. An expected
pre-patch compiler rejection counts as a passing defect characterization; a
patched or staged run must generate compilable Ada and execute its consumer for
every subject that state covers.
The matrix is deliberately broader than the current patchset. New confirmed
defects must become independent bundles/<id>/ entries instead of being folded
into the template-qualification patch. The panel is operationally broad but not
mathematically exhaustive; coverage.toml explicitly lists constructs still
requiring probes or runtime ABI oracles.