cxx-ada-generated-name-identity

C++ Ada generated-name identity

Readable Ada names synthesized for C++ entities can collide with user-written identifiers and with each other.

StagedApplies in patchset orderStaged in 1.2.0

Why this is staged.

The name allocator renames the as-base types, synthetic base components, and destructor entities introduced by the staged ABI-layout bundles, and its patch does not apply without them. Held out of the published patchset for separate upstream review.

Depends on

Where it applies.

How each patchset treats this bundle on each GCC major
PatchsetGCC 13GCC 14GCC 15GCC 16
1.2.0 (latest)Staged13.2.0Staged14.2.0Staged15.3.0Staged16.2.0
1.1.0Not applicable13.2.0Not applicable14.2.0Not applicable15.3.0Not applicable16.2.0
1.0.1Not applicable13.2.0Not applicable14.2.0Not applicable15.3.0Not applicable16.1.0
1.0.0Not applicable13.2.0Not applicable14.2.0Not applicable15.3.0Not applicable16.1.0

Explanation.

The mapper synthesizes readable Ada names for language distinctions and ABI objects that have no direct Ada spelling. Those names previously shared no collision policy with source identifiers. A valid C++ declaration could therefore make the generated specification illegal.

For example, a const qualifier is appended to a method name:

class Methods {
public:
  int inspect() const;
  int inspect_Const();
};

The unpatched output contains two declarations named inspect_Const:

function inspect_Const (this : access constant Methods) return int;
function inspect_Const (this : access Methods) return int;

The corrected mapper reserves source spellings first and changes only the generated collision:

function inspect_Const_2 (this : access constant Methods) return int;
function inspect_Const (this : access Methods) return int;

The same problem occurs between a template-instantiation package and its source alias:

template<typename T> struct Box { T value; };
typedef Box<int> Box_int;

Previously both were Box_int; now the generated package is renamed while the alias stays readable and its reference follows the allocation:

package Box_int_2 is
   type Box is limited record ... end record;
end Box_int_2;
subtype Box_int is Box_int_2.Box;

It also covers generated formal prefixes, base-storage types, unnamed base components, class packages, constructors, destructors, and assignment operators. Representative corrected declarations are:

function make_widget
  (the_Widget_2 : int; the_Widget : int) return access Widget;
type Tail_Derived_As_Base_2 is limited record ... end record;
parent_Base_2  : aliased Left;
field_2_Base_2 : aliased Right;
package Class_Gadget_2 is ... end Class_Gadget_2;
function New_Creator_2 return Creator;
procedure Delete_2 (this : access Destroyer);
function Assign_Assigner_2 (...) return access Assigner;

Names are allocated per Ada scope, compared case-insensitively, and keyed by the C++ declaration and generated role. Unrelated scopes keep their original names. The executable regression makes GNAT compile the complete generated specification and calls a C++ oracle at -O0 and -O2.

Patch.

Variant gcc-13-14

Applies to 13.2.0, 14.2.0. Source flavors: linux, darwin_arm64.

+416 −95 2 files

Download the patch

gcc/c-family/c-ada-spec.cc +309−95modified
Unified diff for gcc/c-family/c-ada-spec.cc: original line, patched line, change, source
@@ -712 +712 @@enum ada_name_role
712712 ADA_NAME_TEMPLATE_INSTANCE,
713713 ADA_NAME_AS_BASE,
714714 ADA_NAME_SYNTHETIC_FIELD,
715Removed line. ADA_NAME_FORMAL
715Added line. ADA_NAME_FORMAL,
716Added line. ADA_NAME_CLASS_PACKAGE,
717Added line. ADA_NAME_CONSTRUCTOR,
718Added line. ADA_NAME_DESTRUCTOR,
719Added line. ADA_NAME_ASSIGNMENT
716720};
717721
718722static const char *allocate_ada_name (const char *, tree, ada_name_role,
719723 tree, const char *, const char *);
720724
721725static void pp_ada_namespace_name (pretty_printer *, tree);
726Added line. static void reserve_ada_source_names (const char *);
727Added line. static bool method_name_matches_visible_type (tree, tree);
728Added line. static bool method_name_matches_destructor (tree);
722729
723730/* Return the innermost named C++ namespace containing NODE. Anonymous
724731 namespaces do not add an Ada package level. */
@@ -925 +932 @@dump_ada_nodes (pretty_printer *pp, const char *source_file)
925932 /* Sort the table of declarations to dump by sloc. */
926933 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
927934
935Added line. if (cpp_check)
936Added line. reserve_ada_source_names (source_file);
937Added line.
928938 /* Fetch the table of comments. */
929939 comments = cpp_get_comments (parse_in);
930940
@@ -1691 +1701 @@allocate_ada_name (const char *preferred, tree identity, ada_name_role role,
16911701 return allocated->name;
16921702}
16931703
1704Added line. /* Reserve DECL's spelling before any synthetic names are allocated. This
1705Added line. gives user-written C++ identifiers priority independent of dump order. */
1706Added line.
1707Added line. static void
1708Added line. reserve_ada_source_decl (tree decl, const char *file)
1709Added line. {
1710Added line. if (!decl || !DECL_P (decl))
1711Added line. return;
1712Added line.
1713Added line. for (tree context = DECL_CONTEXT (decl); context; )
1714Added line. {
1715Added line. if (TREE_CODE (context) == NAMESPACE_DECL
1716Added line. && DECL_NAME (context)
1717Added line. && strcmp (IDENTIFIER_POINTER (DECL_NAME (context)), "::"))
1718Added line. {
1719Added line. bool space_found = false;
1720Added line. char *name = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (context)),
1721Added line. &space_found);
1722Added line. allocate_ada_name (name, DECL_NAME (context), ADA_NAME_SOURCE,
1723Added line. DECL_CONTEXT (context), file, "_Case_");
1724Added line. free (name);
1725Added line. }
1726Added line.
1727Added line. context = DECL_P (context) ? DECL_CONTEXT (context)
1728Added line. : TYPE_P (context) ? TYPE_CONTEXT (context) : NULL_TREE;
1729Added line. }
1730Added line.
1731Added line. if (DECL_NAME (decl))
1732Added line. {
1733Added line. bool space_found = false;
1734Added line. char *name = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (decl)),
1735Added line. &space_found);
1736Added line. allocate_ada_name (name, DECL_NAME (decl), ADA_NAME_SOURCE,
1737Added line. DECL_CONTEXT (decl), file, "_Case_");
1738Added line. free (name);
1739Added line. }
1740Added line.
1741Added line. if (TREE_CODE (decl) == FUNCTION_DECL)
1742Added line. for (tree arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
1743Added line. reserve_ada_source_decl (arg, file);
1744Added line. }
1745Added line.
1746Added line. /* Reserve all source spellings in this generated Ada unit. */
1747Added line.
1748Added line. static void
1749Added line. reserve_ada_source_names (const char *file)
1750Added line. {
1751Added line. for (int i = 0; i < to_dump_count; ++i)
1752Added line. {
1753Added line. tree decl = to_dump[i];
1754Added line. reserve_ada_source_decl (decl, file);
1755Added line. if (TREE_CODE (decl) == TYPE_DECL
1756Added line. && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1757Added line. for (tree field = TYPE_FIELDS (TREE_TYPE (decl)); field;
1758Added line. field = TREE_CHAIN (field))
1759Added line. reserve_ada_source_decl (field, file);
1760Added line. }
1761Added line. }
1762Added line.
1763Added line. /* Return the allocated name of the package that encloses a non-trivial C++
1764Added line. class declaration. */
1765Added line.
1766Added line. static const char *
1767Added line. allocated_class_package_name (tree decl)
1768Added line. {
1769Added line. bool space_found = false;
1770Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (decl)),
1771Added line. &space_found);
1772Added line. const char *base
1773Added line. = allocate_ada_name (source, DECL_NAME (decl), ADA_NAME_SOURCE,
1774Added line. DECL_CONTEXT (decl),
1775Added line. LOCATION_FILE (decl_sloc (decl, false)), "_Case_");
1776Added line. char *candidate = concat ("Class_", base, NULL);
1777Added line. const char *allocated
1778Added line. = allocate_ada_name (candidate, TREE_TYPE (decl), ADA_NAME_CLASS_PACKAGE,
1779Added line. DECL_CONTEXT (decl),
1780Added line. LOCATION_FILE (decl_sloc (decl, false)), "_");
1781Added line. free (candidate);
1782Added line. free (source);
1783Added line. return allocated;
1784Added line. }
1785Added line.
16941786/* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
16951787 syntax. LIMITED_ACCESS indicates whether NODE can be accessed through a
16961788 limited 'with' clause rather than a regular 'with' clause. */
@@ -1755 +1847 @@pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
17551847 && (external_decl
17561848 || named_namespace_context (decl) != current_namespace))
17571849 {
1758Removed line. pp_string (buffer, "Class_");
1759Removed line. pp_string (buffer, allocated);
1850Added line. pp_string (buffer, allocated_class_package_name (decl));
17601851 pp_dot (buffer);
17611852 }
17621853 }
@@ -2006 +2097 @@parameter_name_conflicts_with_profile (tree parameter, tree func,
20062097 return identifier_matches_type (name, return_type);
20072098}
20082099
2100Added line. /* Return PARAMETER's complete Ada formal name. A conflict with a profile
2101Added line. type is resolved before allocation, so a user-written the_Name remains a
2102Added line. distinct declaration rather than colliding with the generated spelling. */
2103Added line.
2104Added line. static const char *
2105Added line. allocated_formal_name (tree parameter, tree func, bool is_constructor)
2106Added line. {
2107Added line. bool space_found = false;
2108Added line. char *base = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (parameter)),
2109Added line. &space_found);
2110Added line. const bool renamed
2111Added line. = parameter_name_conflicts_with_profile (parameter, func, is_constructor);
2112Added line. char *candidate = renamed ? concat ("the_", base, NULL) : xstrdup (base);
2113Added line. const char *allocated
2114Added line. = allocate_ada_name (candidate, renamed ? parameter : DECL_NAME (parameter),
2115Added line. renamed ? ADA_NAME_FORMAL : ADA_NAME_SOURCE,
2116Added line. DECL_CONTEXT (parameter),
2117Added line. LOCATION_FILE (decl_sloc (func, false)), "_");
2118Added line. free (candidate);
2119Added line. free (base);
2120Added line. return allocated;
2121Added line. }
2122Added line.
20092123/* Dump in BUFFER a function declaration FUNC in Ada syntax.
20102124 IS_METHOD indicates whether FUNC is a C++ method.
20112125 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
@@ -2083 +2197 @@dump_ada_function_declaration (pretty_printer *buffer, tree func,
20832197 {
20842198 if (DECL_NAME (arg))
20852199 {
2086Removed line. if (parameter_name_conflicts_with_profile (arg, func,
2087Removed line. is_constructor))
2088Removed line. pp_string (buffer, "the_");
2089Removed line. pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE,
2090Removed line. false);
2200Added line. pp_string (buffer, allocated_formal_name (arg, func,
2201Added line. is_constructor));
20912202 pp_string (buffer, " : ");
20922203 }
20932204 else
@@ -2290 +2401 @@dump_template_types (pretty_printer *buffer, tree types, int spc)
22902401 }
22912402}
22922403
2404Added line. /* Dump the allocated package name for a concrete template INSTANCE. */
2405Added line.
2406Added line. static void
2407Added line. dump_template_instance_name (pretty_printer *pp, tree tmpl, tree instance,
2408Added line. tree types, int spc)
2409Added line. {
2410Added line. pretty_printer name_pp;
2411Added line. const bool saved_package_prefix = package_prefix;
2412Added line. package_prefix = false;
2413Added line. dump_ada_node (&name_pp, instance, tmpl, spc, false, true);
2414Added line. dump_template_types (&name_pp, types, spc);
2415Added line. package_prefix = saved_package_prefix;
2416Added line. const char *candidate = pp_formatted_text (&name_pp);
2417Added line. const char *allocated
2418Added line. = allocate_ada_name (candidate, instance, ADA_NAME_TEMPLATE_INSTANCE,
2419Added line. DECL_CONTEXT (tmpl),
2420Added line. LOCATION_FILE (decl_sloc (tmpl, false)), "_");
2421Added line. pp_string (pp, allocated);
2422Added line. }
2423Added line.
22932424/* If NODE is a concrete template instance emitted in a nested package,
22942425 dump the type name owned by that package. */
22952426
@@ -2330 +2461 @@dump_template_type_name (pretty_printer *buffer, tree node, int spc)
23302461 continue;
23312462
23322463 package_prefix = false;
2333Removed line. dump_ada_node (buffer, TYPE_NAME (instance), tmpl, spc, false, true);
2334Removed line. dump_template_types (buffer, types, spc);
2464Added line. dump_template_instance_name (buffer, tmpl, instance, types, spc);
23352465 pp_dot (buffer);
23362466 dump_ada_node (buffer, TYPE_NAME (instance), tmpl, spc, false, true);
23372467 package_prefix = true;
@@ -2387 +2517 @@dump_ada_template (pretty_printer *buffer, tree t, int spc)
23872517 INDENT (spc);
23882518 pp_string (buffer, "package ");
23892519 package_prefix = false;
2390Removed line. dump_ada_node (buffer, instance, t, spc, false, true);
2391Removed line. dump_template_types (buffer, types, spc);
2520Added line. dump_template_instance_name (buffer, t, instance, types, spc);
23922521 pp_string (buffer, " is");
23932522 spc += INDENT_INCR;
23942523 newline_and_indent (buffer, spc);
@@ -2420 +2549 @@dump_ada_template (pretty_printer *buffer, tree t, int spc)
24202549 newline_and_indent (buffer, spc);
24212550 pp_string (buffer, "use ");
24222551 package_prefix = false;
2423Removed line. dump_ada_node (buffer, instance, t, spc, false, true);
2424Removed line. dump_template_types (buffer, types, spc);
2552Added line. dump_template_instance_name (buffer, t, instance, types, spc);
24252553 package_prefix = true;
24262554 current_template = previous_template;
24272555 current_template_instance = previous_template_instance;
@@ -3284 +3412 @@is_shortened_base_field (tree field)
32843412 < (unsigned HOST_WIDE_INT) object_size * BITS_PER_UNIT;
32853413}
32863414
3415Added line. /* Return the allocated name of NODE's shortened base-subobject type. */
3416Added line.
3417Added line. static const char *
3418Added line. allocated_as_base_name (tree node)
3419Added line. {
3420Added line. tree decl = get_underlying_decl (node);
3421Added line. gcc_assert (decl && DECL_NAME (decl));
3422Added line. bool space_found = false;
3423Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (decl)),
3424Added line. &space_found);
3425Added line. const char *base
3426Added line. = allocate_ada_name (source, DECL_NAME (decl), ADA_NAME_SOURCE,
3427Added line. DECL_CONTEXT (decl),
3428Added line. LOCATION_FILE (decl_sloc (decl, false)), "_Case_");
3429Added line. char *candidate = concat (base, "_As_Base", NULL);
3430Added line. const char *allocated
3431Added line. = allocate_ada_name (candidate, node, ADA_NAME_AS_BASE,
3432Added line. DECL_CONTEXT (decl),
3433Added line. LOCATION_FILE (decl_sloc (decl, false)), "_");
3434Added line. free (candidate);
3435Added line. free (source);
3436Added line. return allocated;
3437Added line. }
3438Added line.
3439Added line. /* Dump NODE's shortened base-subobject type name. */
3440Added line.
3441Added line. static void
3442Added line. dump_ada_as_base_name (pretty_printer *buffer, tree node)
3443Added line. {
3444Added line. pp_ada_namespace_prefix (buffer, get_underlying_decl (node));
3445Added line. pp_string (buffer, allocated_as_base_name (node));
3446Added line. }
3447Added line.
3448Added line. /* Return the allocated name of an unnamed C++ base component. NUMBER is its
3449Added line. one-based position among represented fields. */
3450Added line.
3451Added line. static const char *
3452Added line. allocated_synthetic_field_name (tree owner, tree field, int number)
3453Added line. {
3454Added line. char candidate[32];
3455Added line. if (number == 1)
3456Added line. strcpy (candidate, "parent");
3457Added line. else
3458Added line. snprintf (candidate, sizeof (candidate), "field_%d", number);
3459Added line. tree decl = get_underlying_decl (owner);
3460Added line. gcc_assert (decl);
3461Added line. const char *allocated
3462Added line. = allocate_ada_name (candidate, field, ADA_NAME_SYNTHETIC_FIELD,
3463Added line. owner, LOCATION_FILE (decl_sloc (decl, false)),
3464Added line. "_Base_");
3465Added line. return allocated;
3466Added line. }
3467Added line.
32873468/* Dump FIELD's named type, selecting the shortened storage type when FIELD
32883469 is a base subobject that excludes its type's virtual bases. */
32893470
32903471static void
32913472dump_ada_record_field_type (pretty_printer *buffer, tree field)
32923473{
3293Removed line. dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (field)), false);
32943474 if (is_shortened_base_field (field))
3295Removed line. pp_string (buffer, "_As_Base");
3475Added line. dump_ada_as_base_name (buffer, TREE_TYPE (field));
3476Added line. else
3477Added line. dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (field)), false);
32963478}
32973479
32983480/* Return true if FIELD lies wholly inside NODE's C++ as-base size. */
@@ -3343 +3525 @@dump_ada_as_base_storage_type (pretty_printer *buffer, tree node, tree type,
33433525 pp_newline (buffer);
33443526 newline_and_indent (buffer, spc);
33453527 pp_string (buffer, "type ");
3346Removed line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true);
3347Removed line. pp_string (buffer, "_As_Base is record");
3528Added line. pp_string (buffer, allocated_as_base_name (node));
3529Added line. pp_string (buffer, " is record");
33483530 pp_newline (buffer);
33493531
33503532 for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field))
@@ -3356 +3538 @@dump_ada_as_base_storage_type (pretty_printer *buffer, tree node, tree type,
33563538 continue;
33573539
33583540 INDENT (spc + INDENT_INCR);
3359Removed line. if (field_num == 0)
3360Removed line. pp_string (buffer, "parent : ");
3361Removed line. else
3362Removed line. {
3363Removed line. char buf[32];
3364Removed line. sprintf (buf, "field_%d : ", field_num + 1);
3365Removed line. pp_string (buffer, buf);
3366Removed line. }
3541Added line. pp_string (buffer, allocated_synthetic_field_name (node, field,
3542Added line. field_num + 1));
3543Added line. pp_string (buffer, " : ");
33673544 dump_ada_record_field_type (buffer, field);
33683545 pp_semicolon (buffer);
33693546 pp_newline (buffer);
@@ -3399 +3576 @@dump_ada_as_base_storage_type (pretty_printer *buffer, tree node, tree type,
33993576 {
34003577 newline_and_indent (buffer, spc);
34013578 pp_string (buffer, "pragma Component_Alignment (Storage_Unit, ");
3402Removed line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true);
3403Removed line. pp_string (buffer, "_As_Base);");
3579Added line. pp_string (buffer, allocated_as_base_name (node));
3580Added line. pp_string (buffer, ");");
34043581 }
34053582
34063583 newline_and_indent (buffer, spc);
34073584 pp_string (buffer, "for ");
3408Removed line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true);
3409Removed line. pp_string (buffer, "_As_Base'Size use ");
3585Added line. pp_string (buffer, allocated_as_base_name (node));
3586Added line. pp_string (buffer, "'Size use ");
34103587 pp_wide_integer (buffer, (HOST_WIDE_INT) data_size * BITS_PER_UNIT);
34113588 pp_semicolon (buffer);
34123589
34133590 newline_and_indent (buffer, spc);
34143591 pp_string (buffer, "for ");
3415Removed line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true);
3416Removed line. pp_string (buffer, "_As_Base'Object_Size use ");
3592Added line. pp_string (buffer, allocated_as_base_name (node));
3593Added line. pp_string (buffer, "'Object_Size use ");
34173594 pp_wide_integer (buffer, (HOST_WIDE_INT) data_size * BITS_PER_UNIT);
34183595 pp_semicolon (buffer);
34193596
34203597 newline_and_indent (buffer, spc);
34213598 pp_string (buffer, "for ");
3422Removed line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true);
3423Removed line. pp_string (buffer, "_As_Base'Alignment use ");
3599Added line. pp_string (buffer, allocated_as_base_name (node));
3600Added line. pp_string (buffer, "'Alignment use ");
34243601 pp_decimal_int (buffer, as_base_alignment (node, data_size));
34253602 pp_semicolon (buffer);
34263603
34273604 newline_and_indent (buffer, spc);
34283605 pp_string (buffer, "for ");
3429Removed line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true);
3430Removed line. pp_string (buffer, "_As_Base use record");
3606Added line. pp_string (buffer, allocated_as_base_name (node));
3607Added line. pp_string (buffer, " use record");
34313608
34323609 int repr_field_num = 0;
34333610 for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field))
@@ -3448 +3625 @@dump_ada_as_base_storage_type (pretty_printer *buffer, tree node, tree type,
34483625 newline_and_indent (buffer, spc + INDENT_INCR);
34493626 if (DECL_NAME (field))
34503627 dump_ada_decl_name (buffer, field, false);
3451Removed line. else if (repr_field_num == 1)
3452Removed line. pp_string (buffer, "parent");
34533628 else
3454Removed line. {
3455Removed line. char buf[32];
3456Removed line. sprintf (buf, "field_%d", repr_field_num);
3457Removed line. pp_string (buffer, buf);
3458Removed line. }
3629Added line. pp_string (buffer, allocated_synthetic_field_name (node, field,
3630Added line. repr_field_num));
34593631 pp_string (buffer, " at ");
34603632 pp_unsigned_wide_integer (buffer, position);
34613633 pp_string (buffer, " range ");
@@ -3575 +3747 @@dump_ada_cpp_layout (pretty_printer *buffer, tree node, tree type, int spc,
35753747 newline_and_indent (buffer, spc + INDENT_INCR);
35763748 if (DECL_NAME (field))
35773749 dump_ada_decl_name (buffer, field, false);
3578Removed line. else if (field_num == 1)
3579Removed line. pp_string (buffer, "parent");
35803750 else
3581Removed line. {
3582Removed line. char buf[32];
3583Removed line. sprintf (buf, "field_%d", field_num);
3584Removed line. pp_string (buffer, buf);
3585Removed line. }
3751Added line. pp_string (buffer, allocated_synthetic_field_name (node, field,
3752Added line. field_num));
35863753 pp_string (buffer, " at ");
35873754 pp_unsigned_wide_integer (buffer, position);
35883755 pp_string (buffer, " range ");
@@ -3856 +4023 @@overloading_index (tree name)
38564023static void
38574024print_constructor (pretty_printer *buffer, tree t, tree type)
38584025{
3859Removed line. tree decl_name = DECL_NAME (TYPE_NAME (type));
3860Removed line.
3861Removed line. pp_string (buffer, "New_");
3862Removed line. pp_ada_tree_identifier (buffer, decl_name, t, false);
4026Added line. tree type_decl = TYPE_NAME (type);
4027Added line. bool space_found = false;
4028Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (type_decl)),
4029Added line. &space_found);
4030Added line. const char *base
4031Added line. = allocate_ada_name (source, DECL_NAME (type_decl), ADA_NAME_SOURCE,
4032Added line. DECL_CONTEXT (type_decl),
4033Added line. LOCATION_FILE (decl_sloc (type_decl, false)), "_Case_");
4034Added line. char *candidate = concat ("New_", base, NULL);
4035Added line. pp_string (buffer, allocate_ada_name (candidate, t, ADA_NAME_CONSTRUCTOR,
4036Added line. DECL_CONTEXT (t),
4037Added line. LOCATION_FILE (decl_sloc (t, false)), "_"));
4038Added line. free (candidate);
4039Added line. free (source);
38634040}
38644041
38654042/* Dump in BUFFER destructor spec corresponding to T. */
@@ -3867 +4044 @@print_constructor (pretty_printer *buffer, tree t, tree type)
38674044static void
38684045print_destructor (pretty_printer *buffer, tree t)
38694046{
3870Removed line. if (startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del"))
3871Removed line. pp_string (buffer, "Delete_And_Free");
3872Removed line. else
3873Removed line. pp_string (buffer, "Delete");
4047Added line. const char *candidate
4048Added line. = startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del")
4049Added line. ? "Delete_And_Free" : "Delete";
4050Added line. pp_string (buffer, allocate_ada_name (candidate, t, ADA_NAME_DESTRUCTOR,
4051Added line. DECL_CONTEXT (t),
4052Added line. LOCATION_FILE (decl_sloc (t, false)), "_"));
38744053}
38754054
38764055/* Dump in BUFFER assignment operator spec corresponding to T. */
@@ -3878 +4057 @@print_destructor (pretty_printer *buffer, tree t)
38784057static void
38794058print_assignment_operator (pretty_printer *buffer, tree t, tree type)
38804059{
3881Removed line. tree decl_name = DECL_NAME (TYPE_NAME (type));
3882Removed line.
3883Removed line. pp_string (buffer, "Assign_");
3884Removed line. pp_ada_tree_identifier (buffer, decl_name, t, false);
3885Removed line.
3886Removed line. if (cpp_check (t, GET_FUNCTION_QUALIFIERS)
3887Removed line. & CPP_FUNCTION_MOVE_ASSIGNMENT)
3888Removed line. pp_string (buffer, "_Move");
4060Added line. tree type_decl = TYPE_NAME (type);
4061Added line. bool space_found = false;
4062Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (type_decl)),
4063Added line. &space_found);
4064Added line. const char *base
4065Added line. = allocate_ada_name (source, DECL_NAME (type_decl), ADA_NAME_SOURCE,
4066Added line. DECL_CONTEXT (type_decl),
4067Added line. LOCATION_FILE (decl_sloc (type_decl, false)), "_Case_");
4068Added line. char *candidate
4069Added line. = concat ("Assign_", base,
4070Added line. (cpp_check (t, GET_FUNCTION_QUALIFIERS)
4071Added line. & CPP_FUNCTION_MOVE_ASSIGNMENT) ? "_Move" : "", NULL);
4072Added line. pp_string (buffer, allocate_ada_name (candidate, t, ADA_NAME_ASSIGNMENT,
4073Added line. DECL_CONTEXT (t),
4074Added line. LOCATION_FILE (decl_sloc (t, false)), "_"));
4075Added line. free (candidate);
4076Added line. free (source);
38894077}
38904078
3891Removed line. /* Append the C++ method qualifiers that Ada profiles cannot represent. */
4079Added line. /* Return the complete Ada name of T, including distinctions Ada profiles
4080Added line. cannot express. Allocate the complete name as one unit so it cannot
4081Added line. collide with a user-written identifier such as inspect_Const. */
38924082
3893Removed line. static void
3894Removed line. print_method_qualifiers (pretty_printer *buffer, tree t)
4083Added line. static const char *
4084Added line. allocated_method_name (tree t, tree type, unsigned int overload_suffix)
38954085{
4086Added line. tree decl_name = DECL_NAME (t);
4087Added line. bool space_found = false;
4088Added line. char *base = to_ada_name (IDENTIFIER_POINTER (decl_name), &space_found);
38964089 const int qualifiers = cpp_check (t, GET_FUNCTION_QUALIFIERS);
4090Added line. const bool renamed
4091Added line. = (method_name_matches_visible_type (decl_name, type)
4092Added line. || method_name_matches_destructor (decl_name));
4093Added line. const size_t length = strlen (base) + 96;
4094Added line. char *candidate = XNEWVEC (char, length);
4095Added line. strcpy (candidate, base);
38974096
38984097 if (qualifiers & CPP_FUNCTION_CONST)
3899Removed line. pp_string (buffer, "_Const");
4098Added line. strcat (candidate, "_Const");
39004099 if (qualifiers & CPP_FUNCTION_VOLATILE)
3901Removed line. pp_string (buffer, "_Volatile");
4100Added line. strcat (candidate, "_Volatile");
39024101 if (qualifiers & CPP_FUNCTION_LVALUE)
3903Removed line. pp_string (buffer, "_Lvalue");
4102Added line. strcat (candidate, "_Lvalue");
39044103 else if (qualifiers & CPP_FUNCTION_RVALUE)
3905Removed line. pp_string (buffer, "_Rvalue");
4104Added line. strcat (candidate, "_Rvalue");
4105Added line. if (renamed)
4106Added line. strcat (candidate, "_Method");
4107Added line. if (overload_suffix > 1)
4108Added line. snprintf (candidate + strlen (candidate),
4109Added line. length - strlen (candidate), "%u", overload_suffix);
4110Added line.
4111Added line. const bool generated = qualifiers || renamed || overload_suffix > 1;
4112Added line. const char *allocated
4113Added line. = allocate_ada_name (candidate, generated ? t : decl_name,
4114Added line. generated ? (renamed ? ADA_NAME_RENAMED_METHOD
4115Added line. : ADA_NAME_QUALIFIED_METHOD)
4116Added line. : ADA_NAME_SOURCE,
4117Added line. DECL_CONTEXT (t),
4118Added line. LOCATION_FILE (decl_sloc (t, false)), "_");
4119Added line. free (candidate);
4120Added line. free (base);
4121Added line. return allocated;
39064122}
39074123
39084124/* Return true if METHOD_NAME collides with the enclosing class or another
@@ -4101 +4317 @@dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
41014317 if (separate_class_package (t))
41024318 {
41034319 is_class = true;
4104Removed line. pp_string (buffer, "package Class_");
4105Removed line. dump_ada_node (buffer, t, type, spc, false, true);
4320Added line. pp_string (buffer, "package ");
4321Added line. pp_string (buffer, allocated_class_package_name (t));
41064322 pp_string (buffer, " is");
41074323 spc += INDENT_INCR;
41084324 newline_and_indent (buffer, spc);
@@ -4277 +4493 @@dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
42774493 else
42784494 {
42794495 const unsigned int suffix = overloading_index (decl_name);
4280Removed line. pp_ada_tree_identifier (buffer, decl_name, t, false);
4281Removed line. if (is_method)
4282Removed line. {
4283Removed line. print_method_qualifiers (buffer, t);
4284Removed line. if (method_name_matches_visible_type (decl_name, type)
4285Removed line. || method_name_matches_destructor (decl_name))
4286Removed line. pp_string (buffer, "_Method");
4287Removed line. }
4288Removed line. if (suffix > 1)
4289Removed line. pp_decimal_int (buffer, suffix);
4496Added line. if (is_method || suffix > 1)
4497Added line. pp_string (buffer, allocated_method_name (t, type, suffix));
4498Added line. else
4499Added line. pp_ada_tree_identifier (buffer, decl_name, t, false);
42904500 }
42914501
42924502 dump_ada_function_declaration
@@ -4452 +4662 @@dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
44524662 newline_and_indent (buffer, spc);
44534663 pp_string (buffer, "end;");
44544664 newline_and_indent (buffer, spc);
4455Removed line. pp_string (buffer, "use Class_");
4456Removed line. dump_ada_node (buffer, t, type, spc, false, true);
4665Added line. pp_string (buffer, "use ");
4666Added line. pp_string (buffer, allocated_class_package_name (t));
44574667 pp_semicolon (buffer);
44584668 pp_newline (buffer);
44594669
@@ -4470 +4680 @@dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
44704680
44714681 else
44724682 {
4473Removed line. pp_string (buffer, "; -- ");
4683Added line. const bool layout_terminated
4684Added line. = (TREE_CODE (t) == TYPE_DECL
4685Added line. && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
4686Added line. && (needs_empty_class_layout (TREE_TYPE (t))
4687Added line. || (((needs_tail_padding_layout (TREE_TYPE (t))
4688Added line. || (cpp_check && cpp_check (TREE_TYPE (t), HAS_VIRTUAL_BASE))
4689Added line. || has_concrete_nested_base (TREE_TYPE (t)))
4690Added line. && has_constant_field_layout (TREE_TYPE (t))))));
4691Added line. pp_string (buffer, layout_terminated ? " -- " : "; -- ");
44744692 dump_sloc (buffer, t);
44754693
44764694 if (TREE_CODE (t) == TYPE_DECL
@@ -4543 +4761 @@dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested,
45434761 {
45444762 INDENT (field_spc);
45454763
4546Removed line. if (field_num == 0)
4547Removed line. pp_string (buffer, "parent : aliased ");
4548Removed line. else
4549Removed line. {
4550Removed line. sprintf (buf, "field_%d : aliased ", field_num + 1);
4551Removed line. pp_string (buffer, buf);
4552Removed line. }
4764Added line. pp_string (buffer, allocated_synthetic_field_name (node, tmp,
4765Added line. field_num + 1));
4766Added line. pp_string (buffer, " : aliased ");
45534767 dump_ada_record_field_type (buffer, tmp);
45544768 pp_semicolon (buffer);
45554769 }
gcc/testsuite/g++.dg/ada-spec/generated-name-identity.C +107−0new file
Unified diff for gcc/testsuite/g++.dg/ada-spec/generated-name-identity.C: original line, patched line, change, source
@@ -0 +1 @@
1Added line. /* { dg-do compile } */
2Added line. /* { dg-options "-fdump-ada-spec-slim" } */
3Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function inspect_Const_2" } } */
4Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function inspect_Const " } } */
5Added line. /* { dg-final { scan-file generated_name_identity_c.ads "package Box_int_2 is" } } */
6Added line. /* { dg-final { scan-file generated_name_identity_c.ads "subtype Box_int is Box_int_2.Box" } } */
7Added line. /* { dg-final { scan-file generated_name_identity_c.ads "the_Widget_2 : int; the_Widget : int" } } */
8Added line. /* { dg-final { scan-file generated_name_identity_c.ads "type Tail_Derived_As_Base_2" } } */
9Added line. /* { dg-final { scan-file generated_name_identity_c.ads "parent_Base_2 : aliased Left" } } */
10Added line. /* { dg-final { scan-file generated_name_identity_c.ads "field_2_Base_2 : aliased Right" } } */
11Added line. /* { dg-final { scan-file generated_name_identity_c.ads "package Class_Gadget_2 is" } } */
12Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function New_Creator_2" } } */
13Added line. /* { dg-final { scan-file generated_name_identity_c.ads "procedure Delete_2" } } */
14Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function Assign_Assigner_2" } } */
15Added line.
16Added line. class Methods
17Added line. {
18Added line. public:
19Added line. int inspect () const;
20Added line. int inspect_Const ();
21Added line. };
22Added line.
23Added line. template<typename T>
24Added line. struct Box
25Added line. {
26Added line. T value;
27Added line. };
28Added line.
29Added line. typedef Box<int> Box_int;
30Added line.
31Added line. struct Widget
32Added line. {
33Added line. int value;
34Added line. };
35Added line.
36Added line. Widget *make_widget (int Widget, int the_Widget);
37Added line.
38Added line. struct Tail_Base
39Added line. {
40Added line. char bytes[2];
41Added line. };
42Added line.
43Added line. struct Tail_Derived_As_Base
44Added line. {
45Added line. int value;
46Added line. };
47Added line.
48Added line. struct alignas(2) Tail_Derived : Tail_Base
49Added line. {
50Added line. char extra;
51Added line. };
52Added line.
53Added line. struct Left
54Added line. {
55Added line. int left;
56Added line. };
57Added line.
58Added line. struct Right
59Added line. {
60Added line. int right;
61Added line. };
62Added line.
63Added line. struct Both : Left, Right
64Added line. {
65Added line. int parent;
66Added line. int field_2;
67Added line. };
68Added line.
69Added line. struct Class_Gadget
70Added line. {
71Added line. int value;
72Added line. };
73Added line.
74Added line. class Gadget
75Added line. {
76Added line. public:
77Added line. int ping ();
78Added line. };
79Added line.
80Added line. class Creator
81Added line. {
82Added line. public:
83Added line. Creator ();
84Added line. int New_Creator ();
85Added line. };
86Added line.
87Added line. class Destroyer
88Added line. {
89Added line. public:
90Added line. ~Destroyer ();
91Added line. static int Delete;
92Added line. };
93Added line.
94Added line. class Assigner
95Added line. {
96Added line. public:
97Added line. Assigner &operator= (const Assigner &);
98Added line. int Assign_Assigner ();
99Added line. };
100Added line.
101Added line. extern "C" int
102Added line. generated_name_identity_oracle ()
103Added line. {
104Added line. return 73;
105Added line. }
106Added line.
107Added line. /* { dg-final { cleanup-ada-spec } } */
108

Variant gcc-15-16

Applies to 15.3.0, 16.1.0, 16.2.0. Source flavors: linux, darwin_arm64.

+416 −95 2 files

Download the patch

gcc/c-family/c-ada-spec.cc +309−95modified
Unified diff for gcc/c-family/c-ada-spec.cc: original line, patched line, change, source
@@ -766 +766 @@enum ada_name_role
766766 ADA_NAME_TEMPLATE_INSTANCE,
767767 ADA_NAME_AS_BASE,
768768 ADA_NAME_SYNTHETIC_FIELD,
769Removed line. ADA_NAME_FORMAL
769Added line. ADA_NAME_FORMAL,
770Added line. ADA_NAME_CLASS_PACKAGE,
771Added line. ADA_NAME_CONSTRUCTOR,
772Added line. ADA_NAME_DESTRUCTOR,
773Added line. ADA_NAME_ASSIGNMENT
770774};
771775
772776static const char *allocate_ada_name (const char *, tree, ada_name_role,
773777 tree, const char *, const char *);
774778static void pp_ada_namespace_name (pretty_printer *, tree);
779Added line. static void reserve_ada_source_names (const char *);
780Added line. static bool method_name_matches_visible_type (tree, tree);
781Added line. static bool method_name_matches_destructor (tree);
775782
776783/* Return the innermost named C++ namespace containing NODE. Anonymous
777784 namespaces do not add an Ada package level. */
@@ -978 +985 @@dump_ada_nodes (pretty_printer *pp, const char *source_file)
978985 /* Sort the table of declarations to dump by sloc. */
979986 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
980987
988Added line. if (cpp_check)
989Added line. reserve_ada_source_names (source_file);
990Added line.
981991 /* Fetch the table of comments. */
982992 comments = cpp_get_comments (parse_in);
983993
@@ -1744 +1754 @@allocate_ada_name (const char *preferred, tree identity, ada_name_role role,
17441754 return allocated->name;
17451755}
17461756
1757Added line. /* Reserve DECL's spelling before any synthetic names are allocated. This
1758Added line. gives user-written C++ identifiers priority independent of dump order. */
1759Added line.
1760Added line. static void
1761Added line. reserve_ada_source_decl (tree decl, const char *file)
1762Added line. {
1763Added line. if (!decl || !DECL_P (decl))
1764Added line. return;
1765Added line.
1766Added line. for (tree context = DECL_CONTEXT (decl); context; )
1767Added line. {
1768Added line. if (TREE_CODE (context) == NAMESPACE_DECL
1769Added line. && DECL_NAME (context)
1770Added line. && strcmp (IDENTIFIER_POINTER (DECL_NAME (context)), "::"))
1771Added line. {
1772Added line. bool space_found = false;
1773Added line. char *name = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (context)),
1774Added line. &space_found);
1775Added line. allocate_ada_name (name, DECL_NAME (context), ADA_NAME_SOURCE,
1776Added line. DECL_CONTEXT (context), file, "_Case_");
1777Added line. free (name);
1778Added line. }
1779Added line.
1780Added line. context = DECL_P (context) ? DECL_CONTEXT (context)
1781Added line. : TYPE_P (context) ? TYPE_CONTEXT (context) : NULL_TREE;
1782Added line. }
1783Added line.
1784Added line. if (DECL_NAME (decl))
1785Added line. {
1786Added line. bool space_found = false;
1787Added line. char *name = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (decl)),
1788Added line. &space_found);
1789Added line. allocate_ada_name (name, DECL_NAME (decl), ADA_NAME_SOURCE,
1790Added line. DECL_CONTEXT (decl), file, "_Case_");
1791Added line. free (name);
1792Added line. }
1793Added line.
1794Added line. if (TREE_CODE (decl) == FUNCTION_DECL)
1795Added line. for (tree arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
1796Added line. reserve_ada_source_decl (arg, file);
1797Added line. }
1798Added line.
1799Added line. /* Reserve all source spellings in this generated Ada unit. */
1800Added line.
1801Added line. static void
1802Added line. reserve_ada_source_names (const char *file)
1803Added line. {
1804Added line. for (int i = 0; i < to_dump_count; ++i)
1805Added line. {
1806Added line. tree decl = to_dump[i];
1807Added line. reserve_ada_source_decl (decl, file);
1808Added line. if (TREE_CODE (decl) == TYPE_DECL
1809Added line. && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)))
1810Added line. for (tree field = TYPE_FIELDS (TREE_TYPE (decl)); field;
1811Added line. field = TREE_CHAIN (field))
1812Added line. reserve_ada_source_decl (field, file);
1813Added line. }
1814Added line. }
1815Added line.
1816Added line. /* Return the allocated name of the package that encloses a non-trivial C++
1817Added line. class declaration. */
1818Added line.
1819Added line. static const char *
1820Added line. allocated_class_package_name (tree decl)
1821Added line. {
1822Added line. bool space_found = false;
1823Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (decl)),
1824Added line. &space_found);
1825Added line. const char *base
1826Added line. = allocate_ada_name (source, DECL_NAME (decl), ADA_NAME_SOURCE,
1827Added line. DECL_CONTEXT (decl),
1828Added line. LOCATION_FILE (decl_sloc (decl, false)), "_Case_");
1829Added line. char *candidate = concat ("Class_", base, NULL);
1830Added line. const char *allocated
1831Added line. = allocate_ada_name (candidate, TREE_TYPE (decl), ADA_NAME_CLASS_PACKAGE,
1832Added line. DECL_CONTEXT (decl),
1833Added line. LOCATION_FILE (decl_sloc (decl, false)), "_");
1834Added line. free (candidate);
1835Added line. free (source);
1836Added line. return allocated;
1837Added line. }
1838Added line.
17471839/* Dump in PP the name of an identifier NODE of type TYPE, following Ada
17481840 syntax. LIMITED_ACCESS indicates whether NODE can be accessed through a
17491841 limited 'with' clause rather than a regular 'with' clause. */
@@ -1808 +1900 @@pp_ada_tree_identifier (pretty_printer *pp, tree node, tree type,
18081900 && (external_decl
18091901 || named_namespace_context (decl) != current_namespace))
18101902 {
1811Removed line. pp_string (pp, "Class_");
1812Removed line. pp_string (pp, allocated);
1903Added line. pp_string (pp, allocated_class_package_name (decl));
18131904 pp_dot (pp);
18141905 }
18151906 }
@@ -2059 +2150 @@parameter_name_conflicts_with_profile (tree parameter, tree func,
20592150 return identifier_matches_type (name, return_type);
20602151}
20612152
2153Added line. /* Return PARAMETER's complete Ada formal name. A conflict with a profile
2154Added line. type is resolved before allocation, so a user-written the_Name remains a
2155Added line. distinct declaration rather than colliding with the generated spelling. */
2156Added line.
2157Added line. static const char *
2158Added line. allocated_formal_name (tree parameter, tree func, bool is_constructor)
2159Added line. {
2160Added line. bool space_found = false;
2161Added line. char *base = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (parameter)),
2162Added line. &space_found);
2163Added line. const bool renamed
2164Added line. = parameter_name_conflicts_with_profile (parameter, func, is_constructor);
2165Added line. char *candidate = renamed ? concat ("the_", base, NULL) : xstrdup (base);
2166Added line. const char *allocated
2167Added line. = allocate_ada_name (candidate, renamed ? parameter : DECL_NAME (parameter),
2168Added line. renamed ? ADA_NAME_FORMAL : ADA_NAME_SOURCE,
2169Added line. DECL_CONTEXT (parameter),
2170Added line. LOCATION_FILE (decl_sloc (func, false)), "_");
2171Added line. free (candidate);
2172Added line. free (base);
2173Added line. return allocated;
2174Added line. }
2175Added line.
20622176/* Dump in PP a function declaration FUNC in Ada syntax.
20632177 IS_METHOD indicates whether FUNC is a C++ method.
20642178 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
@@ -2136 +2250 @@dump_ada_function_declaration (pretty_printer *pp, tree func,
21362250 {
21372251 if (DECL_NAME (arg))
21382252 {
2139Removed line. if (parameter_name_conflicts_with_profile (arg, func,
2140Removed line. is_constructor))
2141Removed line. pp_string (pp, "the_");
2142Removed line. pp_ada_tree_identifier (pp, DECL_NAME (arg), NULL_TREE,
2143Removed line. false);
2253Added line. pp_string (pp, allocated_formal_name (arg, func,
2254Added line. is_constructor));
21442255 pp_string (pp, " : ");
21452256 }
21462257 else
@@ -2333 +2444 @@dump_template_types (pretty_printer *pp, tree types, int spc)
23332444 }
23342445}
23352446
2447Added line. /* Dump the allocated package name for a concrete template INSTANCE. */
2448Added line.
2449Added line. static void
2450Added line. dump_template_instance_name (pretty_printer *pp, tree tmpl, tree instance,
2451Added line. tree types, int spc)
2452Added line. {
2453Added line. pretty_printer name_pp;
2454Added line. const bool saved_package_prefix = package_prefix;
2455Added line. package_prefix = false;
2456Added line. dump_ada_node (&name_pp, instance, tmpl, spc, false, true);
2457Added line. dump_template_types (&name_pp, types, spc);
2458Added line. package_prefix = saved_package_prefix;
2459Added line. const char *candidate = pp_formatted_text (&name_pp);
2460Added line. const char *allocated
2461Added line. = allocate_ada_name (candidate, instance, ADA_NAME_TEMPLATE_INSTANCE,
2462Added line. DECL_CONTEXT (tmpl),
2463Added line. LOCATION_FILE (decl_sloc (tmpl, false)), "_");
2464Added line. pp_string (pp, allocated);
2465Added line. }
2466Added line.
23362467/* If NODE is a concrete template instance emitted in a nested package,
23372468 dump the type name owned by that package. */
23382469
@@ -2373 +2504 @@dump_template_type_name (pretty_printer *pp, tree node, int spc)
23732504 continue;
23742505
23752506 package_prefix = false;
2376Removed line. dump_ada_node (pp, TYPE_NAME (instance), tmpl, spc, false, true);
2377Removed line. dump_template_types (pp, types, spc);
2507Added line. dump_template_instance_name (pp, tmpl, instance, types, spc);
23782508 pp_dot (pp);
23792509 dump_ada_node (pp, TYPE_NAME (instance), tmpl, spc, false, true);
23802510 package_prefix = true;
@@ -2430 +2560 @@dump_ada_template (pretty_printer *pp, tree t, int spc)
24302560 INDENT (spc);
24312561 pp_string (pp, "package ");
24322562 package_prefix = false;
2433Removed line. dump_ada_node (pp, instance, t, spc, false, true);
2434Removed line. dump_template_types (pp, types, spc);
2563Added line. dump_template_instance_name (pp, t, instance, types, spc);
24352564 pp_string (pp, " is");
24362565 spc += INDENT_INCR;
24372566 newline_and_indent (pp, spc);
@@ -2463 +2592 @@dump_ada_template (pretty_printer *pp, tree t, int spc)
24632592 newline_and_indent (pp, spc);
24642593 pp_string (pp, "use ");
24652594 package_prefix = false;
2466Removed line. dump_ada_node (pp, instance, t, spc, false, true);
2467Removed line. dump_template_types (pp, types, spc);
2595Added line. dump_template_instance_name (pp, t, instance, types, spc);
24682596 package_prefix = true;
24692597 current_template = previous_template;
24702598 current_template_instance = previous_template_instance;
@@ -3355 +3483 @@is_shortened_base_field (tree field)
33553483 < (unsigned HOST_WIDE_INT) object_size * BITS_PER_UNIT;
33563484}
33573485
3486Added line. /* Return the allocated name of NODE's shortened base-subobject type. */
3487Added line.
3488Added line. static const char *
3489Added line. allocated_as_base_name (tree node)
3490Added line. {
3491Added line. tree decl = get_underlying_decl (node);
3492Added line. gcc_assert (decl && DECL_NAME (decl));
3493Added line. bool space_found = false;
3494Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (decl)),
3495Added line. &space_found);
3496Added line. const char *base
3497Added line. = allocate_ada_name (source, DECL_NAME (decl), ADA_NAME_SOURCE,
3498Added line. DECL_CONTEXT (decl),
3499Added line. LOCATION_FILE (decl_sloc (decl, false)), "_Case_");
3500Added line. char *candidate = concat (base, "_As_Base", NULL);
3501Added line. const char *allocated
3502Added line. = allocate_ada_name (candidate, node, ADA_NAME_AS_BASE,
3503Added line. DECL_CONTEXT (decl),
3504Added line. LOCATION_FILE (decl_sloc (decl, false)), "_");
3505Added line. free (candidate);
3506Added line. free (source);
3507Added line. return allocated;
3508Added line. }
3509Added line.
3510Added line. /* Dump NODE's shortened base-subobject type name. */
3511Added line.
3512Added line. static void
3513Added line. dump_ada_as_base_name (pretty_printer *pp, tree node)
3514Added line. {
3515Added line. pp_ada_namespace_prefix (pp, get_underlying_decl (node));
3516Added line. pp_string (pp, allocated_as_base_name (node));
3517Added line. }
3518Added line.
3519Added line. /* Return the allocated name of an unnamed C++ base component. NUMBER is its
3520Added line. one-based position among represented fields. */
3521Added line.
3522Added line. static const char *
3523Added line. allocated_synthetic_field_name (tree owner, tree field, int number)
3524Added line. {
3525Added line. char candidate[32];
3526Added line. if (number == 1)
3527Added line. strcpy (candidate, "parent");
3528Added line. else
3529Added line. snprintf (candidate, sizeof (candidate), "field_%d", number);
3530Added line. tree decl = get_underlying_decl (owner);
3531Added line. gcc_assert (decl);
3532Added line. const char *allocated
3533Added line. = allocate_ada_name (candidate, field, ADA_NAME_SYNTHETIC_FIELD,
3534Added line. owner, LOCATION_FILE (decl_sloc (decl, false)),
3535Added line. "_Base_");
3536Added line. return allocated;
3537Added line. }
3538Added line.
33583539/* Dump FIELD's named type, selecting the shortened storage type when FIELD
33593540 is a base subobject that excludes its type's virtual bases. */
33603541
33613542static void
33623543dump_ada_record_field_type (pretty_printer *pp, tree field)
33633544{
3364Removed line. dump_ada_decl_name (pp, TYPE_NAME (TREE_TYPE (field)), false);
33653545 if (is_shortened_base_field (field))
3366Removed line. pp_string (pp, "_As_Base");
3546Added line. dump_ada_as_base_name (pp, TREE_TYPE (field));
3547Added line. else
3548Added line. dump_ada_decl_name (pp, TYPE_NAME (TREE_TYPE (field)), false);
33673549}
33683550
33693551/* Return true if FIELD lies wholly inside NODE's C++ as-base size. */
@@ -3414 +3596 @@dump_ada_as_base_storage_type (pretty_printer *pp, tree node, tree type,
34143596 pp_newline (pp);
34153597 newline_and_indent (pp, spc);
34163598 pp_string (pp, "type ");
3417Removed line. dump_ada_node (pp, TYPE_NAME (node), type, spc, false, true);
3418Removed line. pp_string (pp, "_As_Base is record");
3599Added line. pp_string (pp, allocated_as_base_name (node));
3600Added line. pp_string (pp, " is record");
34193601 pp_newline (pp);
34203602
34213603 for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field))
@@ -3427 +3609 @@dump_ada_as_base_storage_type (pretty_printer *pp, tree node, tree type,
34273609 continue;
34283610
34293611 INDENT (spc + INDENT_INCR);
3430Removed line. if (field_num == 0)
3431Removed line. pp_string (pp, "parent : ");
3432Removed line. else
3433Removed line. {
3434Removed line. char buf[32];
3435Removed line. sprintf (buf, "field_%d : ", field_num + 1);
3436Removed line. pp_string (pp, buf);
3437Removed line. }
3612Added line. pp_string (pp, allocated_synthetic_field_name (node, field,
3613Added line. field_num + 1));
3614Added line. pp_string (pp, " : ");
34383615 dump_ada_record_field_type (pp, field);
34393616 pp_semicolon (pp);
34403617 pp_newline (pp);
@@ -3470 +3647 @@dump_ada_as_base_storage_type (pretty_printer *pp, tree node, tree type,
34703647 {
34713648 newline_and_indent (pp, spc);
34723649 pp_string (pp, "pragma Component_Alignment (Storage_Unit, ");
3473Removed line. dump_ada_node (pp, TYPE_NAME (node), type, spc, false, true);
3474Removed line. pp_string (pp, "_As_Base);");
3650Added line. pp_string (pp, allocated_as_base_name (node));
3651Added line. pp_string (pp, ");");
34753652 }
34763653
34773654 newline_and_indent (pp, spc);
34783655 pp_string (pp, "for ");
3479Removed line. dump_ada_node (pp, TYPE_NAME (node), type, spc, false, true);
3480Removed line. pp_string (pp, "_As_Base'Size use ");
3656Added line. pp_string (pp, allocated_as_base_name (node));
3657Added line. pp_string (pp, "'Size use ");
34813658 pp_wide_integer (pp, (HOST_WIDE_INT) data_size * BITS_PER_UNIT);
34823659 pp_semicolon (pp);
34833660
34843661 newline_and_indent (pp, spc);
34853662 pp_string (pp, "for ");
3486Removed line. dump_ada_node (pp, TYPE_NAME (node), type, spc, false, true);
3487Removed line. pp_string (pp, "_As_Base'Object_Size use ");
3663Added line. pp_string (pp, allocated_as_base_name (node));
3664Added line. pp_string (pp, "'Object_Size use ");
34883665 pp_wide_integer (pp, (HOST_WIDE_INT) data_size * BITS_PER_UNIT);
34893666 pp_semicolon (pp);
34903667
34913668 newline_and_indent (pp, spc);
34923669 pp_string (pp, "for ");
3493Removed line. dump_ada_node (pp, TYPE_NAME (node), type, spc, false, true);
3494Removed line. pp_string (pp, "_As_Base'Alignment use ");
3670Added line. pp_string (pp, allocated_as_base_name (node));
3671Added line. pp_string (pp, "'Alignment use ");
34953672 pp_decimal_int (pp, as_base_alignment (node, data_size));
34963673 pp_semicolon (pp);
34973674
34983675 newline_and_indent (pp, spc);
34993676 pp_string (pp, "for ");
3500Removed line. dump_ada_node (pp, TYPE_NAME (node), type, spc, false, true);
3501Removed line. pp_string (pp, "_As_Base use record");
3677Added line. pp_string (pp, allocated_as_base_name (node));
3678Added line. pp_string (pp, " use record");
35023679
35033680 int repr_field_num = 0;
35043681 for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field))
@@ -3519 +3696 @@dump_ada_as_base_storage_type (pretty_printer *pp, tree node, tree type,
35193696 newline_and_indent (pp, spc + INDENT_INCR);
35203697 if (DECL_NAME (field))
35213698 dump_ada_decl_name (pp, field, false);
3522Removed line. else if (repr_field_num == 1)
3523Removed line. pp_string (pp, "parent");
35243699 else
3525Removed line. {
3526Removed line. char buf[32];
3527Removed line. sprintf (buf, "field_%d", repr_field_num);
3528Removed line. pp_string (pp, buf);
3529Removed line. }
3700Added line. pp_string (pp, allocated_synthetic_field_name (node, field,
3701Added line. repr_field_num));
35303702 pp_string (pp, " at ");
35313703 pp_unsigned_wide_integer (pp, position);
35323704 pp_string (pp, " range ");
@@ -3645 +3817 @@dump_ada_cpp_layout (pretty_printer *pp, tree node, tree type, int spc,
36453817 newline_and_indent (pp, spc + INDENT_INCR);
36463818 if (DECL_NAME (field))
36473819 dump_ada_decl_name (pp, field, false);
3648Removed line. else if (field_num == 1)
3649Removed line. pp_string (pp, "parent");
36503820 else
3651Removed line. {
3652Removed line. char buf[32];
3653Removed line. sprintf (buf, "field_%d", field_num);
3654Removed line. pp_string (pp, buf);
3655Removed line. }
3821Added line. pp_string (pp, allocated_synthetic_field_name (node, field,
3822Added line. field_num));
36563823 pp_string (pp, " at ");
36573824 pp_unsigned_wide_integer (pp, position);
36583825 pp_string (pp, " range ");
@@ -3937 +4104 @@overloading_index (tree name)
39374104static void
39384105print_constructor (pretty_printer *pp, tree t, tree type)
39394106{
3940Removed line. tree decl_name = DECL_NAME (TYPE_NAME (type));
3941Removed line.
3942Removed line. pp_string (pp, "New_");
3943Removed line. pp_ada_tree_identifier (pp, decl_name, t, false);
4107Added line. tree type_decl = TYPE_NAME (type);
4108Added line. bool space_found = false;
4109Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (type_decl)),
4110Added line. &space_found);
4111Added line. const char *base
4112Added line. = allocate_ada_name (source, DECL_NAME (type_decl), ADA_NAME_SOURCE,
4113Added line. DECL_CONTEXT (type_decl),
4114Added line. LOCATION_FILE (decl_sloc (type_decl, false)), "_Case_");
4115Added line. char *candidate = concat ("New_", base, NULL);
4116Added line. pp_string (pp, allocate_ada_name (candidate, t, ADA_NAME_CONSTRUCTOR,
4117Added line. DECL_CONTEXT (t),
4118Added line. LOCATION_FILE (decl_sloc (t, false)), "_"));
4119Added line. free (candidate);
4120Added line. free (source);
39444121}
39454122
39464123/* Dump in PP destructor spec corresponding to T. */
@@ -3948 +4125 @@print_constructor (pretty_printer *pp, tree t, tree type)
39484125static void
39494126print_destructor (pretty_printer *pp, tree t)
39504127{
3951Removed line. if (startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del"))
3952Removed line. pp_string (pp, "Delete_And_Free");
3953Removed line. else
3954Removed line. pp_string (pp, "Delete");
4128Added line. const char *candidate
4129Added line. = startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del")
4130Added line. ? "Delete_And_Free" : "Delete";
4131Added line. pp_string (pp, allocate_ada_name (candidate, t, ADA_NAME_DESTRUCTOR,
4132Added line. DECL_CONTEXT (t),
4133Added line. LOCATION_FILE (decl_sloc (t, false)), "_"));
39554134}
39564135
39574136/* Dump in PP assignment operator spec corresponding to T. */
@@ -3959 +4138 @@print_destructor (pretty_printer *pp, tree t)
39594138static void
39604139print_assignment_operator (pretty_printer *pp, tree t, tree type)
39614140{
3962Removed line. tree decl_name = DECL_NAME (TYPE_NAME (type));
3963Removed line.
3964Removed line. pp_string (pp, "Assign_");
3965Removed line. pp_ada_tree_identifier (pp, decl_name, t, false);
3966Removed line.
3967Removed line. if (cpp_check (t, GET_FUNCTION_QUALIFIERS)
3968Removed line. & CPP_FUNCTION_MOVE_ASSIGNMENT)
3969Removed line. pp_string (pp, "_Move");
4141Added line. tree type_decl = TYPE_NAME (type);
4142Added line. bool space_found = false;
4143Added line. char *source = to_ada_name (IDENTIFIER_POINTER (DECL_NAME (type_decl)),
4144Added line. &space_found);
4145Added line. const char *base
4146Added line. = allocate_ada_name (source, DECL_NAME (type_decl), ADA_NAME_SOURCE,
4147Added line. DECL_CONTEXT (type_decl),
4148Added line. LOCATION_FILE (decl_sloc (type_decl, false)), "_Case_");
4149Added line. char *candidate
4150Added line. = concat ("Assign_", base,
4151Added line. (cpp_check (t, GET_FUNCTION_QUALIFIERS)
4152Added line. & CPP_FUNCTION_MOVE_ASSIGNMENT) ? "_Move" : "", NULL);
4153Added line. pp_string (pp, allocate_ada_name (candidate, t, ADA_NAME_ASSIGNMENT,
4154Added line. DECL_CONTEXT (t),
4155Added line. LOCATION_FILE (decl_sloc (t, false)), "_"));
4156Added line. free (candidate);
4157Added line. free (source);
39704158}
39714159
3972Removed line. /* Append the C++ method qualifiers that Ada profiles cannot represent. */
4160Added line. /* Return the complete Ada name of T, including distinctions Ada profiles
4161Added line. cannot express. Allocate the complete name as one unit so it cannot
4162Added line. collide with a user-written identifier such as inspect_Const. */
39734163
3974Removed line. static void
3975Removed line. print_method_qualifiers (pretty_printer *pp, tree t)
4164Added line. static const char *
4165Added line. allocated_method_name (tree t, tree type, unsigned int overload_suffix)
39764166{
4167Added line. tree decl_name = DECL_NAME (t);
4168Added line. bool space_found = false;
4169Added line. char *base = to_ada_name (IDENTIFIER_POINTER (decl_name), &space_found);
39774170 const int qualifiers = cpp_check (t, GET_FUNCTION_QUALIFIERS);
4171Added line. const bool renamed
4172Added line. = (method_name_matches_visible_type (decl_name, type)
4173Added line. || method_name_matches_destructor (decl_name));
4174Added line. const size_t length = strlen (base) + 96;
4175Added line. char *candidate = XNEWVEC (char, length);
4176Added line. strcpy (candidate, base);
39784177
39794178 if (qualifiers & CPP_FUNCTION_CONST)
3980Removed line. pp_string (pp, "_Const");
4179Added line. strcat (candidate, "_Const");
39814180 if (qualifiers & CPP_FUNCTION_VOLATILE)
3982Removed line. pp_string (pp, "_Volatile");
4181Added line. strcat (candidate, "_Volatile");
39834182 if (qualifiers & CPP_FUNCTION_LVALUE)
3984Removed line. pp_string (pp, "_Lvalue");
4183Added line. strcat (candidate, "_Lvalue");
39854184 else if (qualifiers & CPP_FUNCTION_RVALUE)
3986Removed line. pp_string (pp, "_Rvalue");
4185Added line. strcat (candidate, "_Rvalue");
4186Added line. if (renamed)
4187Added line. strcat (candidate, "_Method");
4188Added line. if (overload_suffix > 1)
4189Added line. snprintf (candidate + strlen (candidate),
4190Added line. length - strlen (candidate), "%u", overload_suffix);
4191Added line.
4192Added line. const bool generated = qualifiers || renamed || overload_suffix > 1;
4193Added line. const char *allocated
4194Added line. = allocate_ada_name (candidate, generated ? t : decl_name,
4195Added line. generated ? (renamed ? ADA_NAME_RENAMED_METHOD
4196Added line. : ADA_NAME_QUALIFIED_METHOD)
4197Added line. : ADA_NAME_SOURCE,
4198Added line. DECL_CONTEXT (t),
4199Added line. LOCATION_FILE (decl_sloc (t, false)), "_");
4200Added line. free (candidate);
4201Added line. free (base);
4202Added line. return allocated;
39874203}
39884204
39894205/* Return true if METHOD_NAME collides with the enclosing class or another
@@ -4182 +4398 @@dump_ada_declaration (pretty_printer *pp, tree t, tree type, int spc)
41824398 if (separate_class_package (t))
41834399 {
41844400 is_class = true;
4185Removed line. pp_string (pp, "package Class_");
4186Removed line. dump_ada_node (pp, t, type, spc, false, true);
4401Added line. pp_string (pp, "package ");
4402Added line. pp_string (pp, allocated_class_package_name (t));
41874403 pp_string (pp, " is");
41884404 spc += INDENT_INCR;
41894405 newline_and_indent (pp, spc);
@@ -4358 +4574 @@dump_ada_declaration (pretty_printer *pp, tree t, tree type, int spc)
43584574 else
43594575 {
43604576 const unsigned int suffix = overloading_index (decl_name);
4361Removed line. pp_ada_tree_identifier (pp, decl_name, t, false);
4362Removed line. if (is_method)
4363Removed line. {
4364Removed line. print_method_qualifiers (pp, t);
4365Removed line. if (method_name_matches_visible_type (decl_name, type)
4366Removed line. || method_name_matches_destructor (decl_name))
4367Removed line. pp_string (pp, "_Method");
4368Removed line. }
4369Removed line. if (suffix > 1)
4370Removed line. pp_decimal_int (pp, suffix);
4577Added line. if (is_method || suffix > 1)
4578Added line. pp_string (pp, allocated_method_name (t, type, suffix));
4579Added line. else
4580Added line. pp_ada_tree_identifier (pp, decl_name, t, false);
43714581 }
43724582
43734583 dump_ada_function_declaration
@@ -4533 +4743 @@dump_ada_declaration (pretty_printer *pp, tree t, tree type, int spc)
45334743 newline_and_indent (pp, spc);
45344744 pp_string (pp, "end;");
45354745 newline_and_indent (pp, spc);
4536Removed line. pp_string (pp, "use Class_");
4537Removed line. dump_ada_node (pp, t, type, spc, false, true);
4746Added line. pp_string (pp, "use ");
4747Added line. pp_string (pp, allocated_class_package_name (t));
45384748 pp_semicolon (pp);
45394749 pp_newline (pp);
45404750
@@ -4551 +4761 @@dump_ada_declaration (pretty_printer *pp, tree t, tree type, int spc)
45514761
45524762 else
45534763 {
4554Removed line. pp_string (pp, "; -- ");
4764Added line. const bool layout_terminated
4765Added line. = (TREE_CODE (t) == TYPE_DECL
4766Added line. && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
4767Added line. && (needs_empty_class_layout (TREE_TYPE (t))
4768Added line. || (((needs_tail_padding_layout (TREE_TYPE (t))
4769Added line. || (cpp_check && cpp_check (TREE_TYPE (t), HAS_VIRTUAL_BASE))
4770Added line. || has_concrete_nested_base (TREE_TYPE (t)))
4771Added line. && has_constant_field_layout (TREE_TYPE (t))))));
4772Added line. pp_string (pp, layout_terminated ? " -- " : "; -- ");
45554773 dump_sloc (pp, t);
45564774
45574775 if (TREE_CODE (t) == TYPE_DECL
@@ -4623 +4841 @@dump_ada_structure (pretty_printer *pp, tree node, tree type, bool nested,
46234841 {
46244842 INDENT (field_spc);
46254843
4626Removed line. if (field_num == 0)
4627Removed line. pp_string (pp, "parent : aliased ");
4628Removed line. else
4629Removed line. {
4630Removed line. sprintf (buf, "field_%d : aliased ", field_num + 1);
4631Removed line. pp_string (pp, buf);
4632Removed line. }
4844Added line. pp_string (pp, allocated_synthetic_field_name (node, tmp,
4845Added line. field_num + 1));
4846Added line. pp_string (pp, " : aliased ");
46334847 dump_ada_record_field_type (pp, tmp);
46344848 pp_semicolon (pp);
46354849 }
gcc/testsuite/g++.dg/ada-spec/generated-name-identity.C +107−0new file
Unified diff for gcc/testsuite/g++.dg/ada-spec/generated-name-identity.C: original line, patched line, change, source
@@ -0 +1 @@
1Added line. /* { dg-do compile } */
2Added line. /* { dg-options "-fdump-ada-spec-slim" } */
3Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function inspect_Const_2" } } */
4Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function inspect_Const " } } */
5Added line. /* { dg-final { scan-file generated_name_identity_c.ads "package Box_int_2 is" } } */
6Added line. /* { dg-final { scan-file generated_name_identity_c.ads "subtype Box_int is Box_int_2.Box" } } */
7Added line. /* { dg-final { scan-file generated_name_identity_c.ads "the_Widget_2 : int; the_Widget : int" } } */
8Added line. /* { dg-final { scan-file generated_name_identity_c.ads "type Tail_Derived_As_Base_2" } } */
9Added line. /* { dg-final { scan-file generated_name_identity_c.ads "parent_Base_2 : aliased Left" } } */
10Added line. /* { dg-final { scan-file generated_name_identity_c.ads "field_2_Base_2 : aliased Right" } } */
11Added line. /* { dg-final { scan-file generated_name_identity_c.ads "package Class_Gadget_2 is" } } */
12Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function New_Creator_2" } } */
13Added line. /* { dg-final { scan-file generated_name_identity_c.ads "procedure Delete_2" } } */
14Added line. /* { dg-final { scan-file generated_name_identity_c.ads "function Assign_Assigner_2" } } */
15Added line.
16Added line. class Methods
17Added line. {
18Added line. public:
19Added line. int inspect () const;
20Added line. int inspect_Const ();
21Added line. };
22Added line.
23Added line. template<typename T>
24Added line. struct Box
25Added line. {
26Added line. T value;
27Added line. };
28Added line.
29Added line. typedef Box<int> Box_int;
30Added line.
31Added line. struct Widget
32Added line. {
33Added line. int value;
34Added line. };
35Added line.
36Added line. Widget *make_widget (int Widget, int the_Widget);
37Added line.
38Added line. struct Tail_Base
39Added line. {
40Added line. char bytes[2];
41Added line. };
42Added line.
43Added line. struct Tail_Derived_As_Base
44Added line. {
45Added line. int value;
46Added line. };
47Added line.
48Added line. struct alignas(2) Tail_Derived : Tail_Base
49Added line. {
50Added line. char extra;
51Added line. };
52Added line.
53Added line. struct Left
54Added line. {
55Added line. int left;
56Added line. };
57Added line.
58Added line. struct Right
59Added line. {
60Added line. int right;
61Added line. };
62Added line.
63Added line. struct Both : Left, Right
64Added line. {
65Added line. int parent;
66Added line. int field_2;
67Added line. };
68Added line.
69Added line. struct Class_Gadget
70Added line. {
71Added line. int value;
72Added line. };
73Added line.
74Added line. class Gadget
75Added line. {
76Added line. public:
77Added line. int ping ();
78Added line. };
79Added line.
80Added line. class Creator
81Added line. {
82Added line. public:
83Added line. Creator ();
84Added line. int New_Creator ();
85Added line. };
86Added line.
87Added line. class Destroyer
88Added line. {
89Added line. public:
90Added line. ~Destroyer ();
91Added line. static int Delete;
92Added line. };
93Added line.
94Added line. class Assigner
95Added line. {
96Added line. public:
97Added line. Assigner &operator= (const Assigner &);
98Added line. int Assign_Assigner ();
99Added line. };
100Added line.
101Added line. extern "C" int
102Added line. generated_name_identity_oracle ()
103Added line. {
104Added line. return 73;
105Added line. }
106Added line.
107Added line. /* { dg-final { cleanup-ada-spec } } */
108

Tests.

generated-name-identity.C C++ · 107 lines
/* { dg-do compile } */
/* { dg-options "-fdump-ada-spec-slim" } */
/* { dg-final { scan-file generated_name_identity_c.ads "function inspect_Const_2" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "function inspect_Const " } } */
/* { dg-final { scan-file generated_name_identity_c.ads "package Box_int_2 is" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "subtype Box_int is Box_int_2.Box" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "the_Widget_2 : int; the_Widget : int" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "type Tail_Derived_As_Base_2" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "parent_Base_2 : aliased Left" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "field_2_Base_2 : aliased Right" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "package Class_Gadget_2 is" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "function New_Creator_2" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "procedure Delete_2" } } */
/* { dg-final { scan-file generated_name_identity_c.ads "function Assign_Assigner_2" } } */

class Methods
{
public:
  int inspect () const;
  int inspect_Const ();
};

template<typename T>
struct Box
{
  T value;
};

typedef Box<int> Box_int;

struct Widget
{
  int value;
};

Widget *make_widget (int Widget, int the_Widget);

struct Tail_Base
{
  char bytes[2];
};

struct Tail_Derived_As_Base
{
  int value;
};

struct alignas(2) Tail_Derived : Tail_Base
{
  char extra;
};

struct Left
{
  int left;
};

struct Right
{
  int right;
};

struct Both : Left, Right
{
  int parent;
  int field_2;
};

struct Class_Gadget
{
  int value;
};

class Gadget
{
public:
  int ping ();
};

class Creator
{
public:
  Creator ();
  int New_Creator ();
};

class Destroyer
{
public:
  ~Destroyer ();
  static int Delete;
};

class Assigner
{
public:
  Assigner &operator= (const Assigner &);
  int Assign_Assigner ();
};

extern "C" int
generated_name_identity_oracle ()
{
  return 73;
}

/* { dg-final { cleanup-ada-spec } } */

Download · View in repository

generated_name_identity_consumer.adb Ada · 10 lines
with Interfaces.C; use Interfaces.C;
with Generated_Name_Identity_C;

procedure Generated_Name_Identity_Consumer is
   package Bindings renames Generated_Name_Identity_C;
begin
   if Bindings.generated_name_identity_oracle /= 73 then
      raise Program_Error with "generated-name identity oracle mismatch";
   end if;
end Generated_Name_Identity_Consumer;

Download · View in repository

run-test.sh shell · 83 lines
#!/usr/bin/env bash
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-generated-name-identity/tests/generated-name-identity.C"
ada_fixture="$root/bundles/cxx-ada-generated-name-identity/tests/generated_name_identity_consumer.adb"
work=$(mktemp -d "${TMPDIR:-/tmp}/gnat-cxx-ada-generated-name.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" -c "-O$optimization" \
      -fdump-ada-spec-slim generated-name-identity.C
  )

  set +e
  (
    cd "$case_dir"
    "${REGRESSION_ENV[@]}" "$REGRESSION_GNATMAKE" -q -f \
      "-O$optimization" generated_name_identity_consumer.adb \
      -largs generated-name-identity.o -lstdc++
    "${REGRESSION_ENV[@]}" ./generated_name_identity_consumer
  ) >"$case_dir/run.log" 2>&1
  run_status=$?
  set -e

  if [[ "$state" == unpatched ]]; then
    [[ $run_status -ne 0 ]] || {
      echo "error: unpatched generated-name regression unexpectedly passed" >&2
      exit 1
    }
    grep -Eiq 'conflicts with declaration|duplicate|not declared|invalid use' \
      "$case_dir/run.log" || {
      cat "$case_dir/run.log"
      exit 1
    }
    echo "cxx-ada-generated-name-identity -O$optimization: expected collision (GCC $version)"
    continue
  fi

  [[ $run_status -eq 0 ]] || {
    cat "$case_dir/run.log"
    exit 1
  }
  spec="$case_dir/generated_name_identity_c.ads"
  grep -F "function inspect_Const_2" "$spec"
  grep -F "function inspect_Const " "$spec"
  grep -F "package Box_int_2 is" "$spec"
  grep -F "subtype Box_int is Box_int_2.Box" "$spec"
  grep -F "the_Widget_2 : int; the_Widget : int" "$spec"
  grep -F "type Tail_Derived_As_Base_2" "$spec"
  grep -F "parent_Base_2 : aliased Left" "$spec"
  grep -F "field_2_Base_2 : aliased Right" "$spec"
  grep -F "package Class_Gadget_2 is" "$spec"
  grep -F "function New_Creator_2" "$spec"
  grep -F "procedure Delete_2" "$spec"
  grep -F "function Assign_Assigner_2" "$spec"
  echo "cxx-ada-generated-name-identity -O$optimization: patched (GCC $version)"
done

Download · View in repository

Commands.

Apply the patch
patch --fuzz=0 -p1 -i bundles/cxx-ada-generated-name-identity/patches/VARIANT.patch
Build the compiler
PATH=/path/to/bootstrap/bin:$PATH ./scripts/build-gnat.sh SOURCE BUILD INSTALL
Run the regression
./scripts/run-regressions.sh INSTALL 1.2.0 GCC_MAJOR patched

Metadata.