Skip to content

Commit 5bfce0a

Browse files
authored
Incorrect order of base-class initializers in class template [GH edgcpp#302]
1 parent 3c62b61 commit 5bfce0a

15 files changed

Lines changed: 4266 additions & 4 deletions

‎src/Changes‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
Version 7.1
22

3+
10/16/26 [GH #302]
4+
Incorrect order of base-class initializers in class template
5+
6+
Previously, in the IL for prototype instantiations of class templates,
7+
base-class mem-initializers with non-type template arguments could appear after
8+
the initializers for other base classes. Such initializers are now recorded in
9+
base-class declaration order when the base class can be identified.
10+
Initializers for base classes that cannot yet be identified now retain their
11+
source order relative to the next initializer for an identified nonvirtual
12+
direct base class. For example, with --c++11:
13+
14+
template<int> struct A { };
15+
struct B { };
16+
template<int N> struct C : A<N>, B {
17+
C() : A<N>(), B() { } // Previously recorded as "B(), A<N>()".
18+
C(int) : A<+N>(), B() { } // Previously recorded as "B(), A<+N>()".
19+
};
20+
21+
Both initializer lists are now recorded in the order shown.
22+
23+
324
10/16/26 [GH #229]
425
Improper handling of "if constexpr" substatements
526

‎src/decl_inits.c‎

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7508,6 +7508,14 @@ typedef struct a_ctor_init_block {
75087508
a_boolean out_of_order_diag_issued;
75097509
/* TRUE if a diagnostic has been issued about
75107510
mem-initializers not matching declaration order. */
7511+
a_constructor_init_ptr
7512+
first_pending_unresolved_base_init;
7513+
/* First pending constructor init for a base class
7514+
not matched with the base class list. These entries
7515+
occupy the tail of direct_list until the next
7516+
mem-initializer for a matched nonvirtual direct
7517+
base class is scanned. NULL if no entries are
7518+
pending. */
75117519
a_boolean pack_expansion_context_started;
75127520
/* TRUE if begin_potential_pack_expansion_context has
75137521
been called for a mem-initializer, and elements
@@ -7597,10 +7605,61 @@ template containing the ctor-initializer is instantiated.
75977605
cibp->end_of_direct_list->next = new_cip;
75987606
} /* if */
75997607
cibp->end_of_direct_list = new_cip;
7608+
if (cibp->first_pending_unresolved_base_init == NULL) {
7609+
cibp->first_pending_unresolved_base_init = new_cip;
7610+
} /* if */
76007611
return new_cip;
76017612
} /* add_new_unresolved_base_ctor_init */
76027613

76037614

7615+
static void move_pending_unresolved_base_inits(
7616+
a_ctor_init_block *cibp,
7617+
a_constructor_init_ptr explicit_cip)
7618+
/*
7619+
cibp tracks the constructor init entries for the constructor being defined.
7620+
If it has pending entries for unresolved base classes, move them from the tail
7621+
of direct_list to immediately before explicit_cip and clear the pending state.
7622+
explicit_cip is the existing init entry for the matched nonvirtual direct base
7623+
class whose mem-initializer is being scanned. This preserves the source order
7624+
of the unresolved mem-initializers relative to that mem-initializer.
7625+
*/
7626+
{
7627+
a_constructor_init_ptr first_pending =
7628+
cibp->first_pending_unresolved_base_init;
7629+
a_constructor_init_ptr last_pending = cibp->end_of_direct_list;
7630+
7631+
if (first_pending != NULL) {
7632+
/* Find the predecessors of the pending tail and explicit_cip. */
7633+
a_constructor_init_ptr prev_of_pending = NULL, prev_of_explicit = NULL;
7634+
7635+
check_assertion(last_pending != NULL && last_pending->next == NULL);
7636+
for (a_constructor_init_ptr cip = cibp->direct_list, prev_cip = NULL;
7637+
cip != NULL;
7638+
prev_cip = cip, cip = cip->next) {
7639+
if (cip == first_pending) {
7640+
prev_of_pending = prev_cip;
7641+
break;
7642+
} /* if */
7643+
if (cip == explicit_cip) prev_of_explicit = prev_cip;
7644+
} /* for */
7645+
check_assertion(prev_of_pending != NULL &&
7646+
(explicit_cip == cibp->direct_list ||
7647+
prev_of_explicit != NULL));
7648+
/* Remove the pending entries from the end of the list and splice them
7649+
before explicit_cip. */
7650+
prev_of_pending->next = NULL;
7651+
cibp->end_of_direct_list = prev_of_pending;
7652+
last_pending->next = explicit_cip;
7653+
if (prev_of_explicit == NULL) {
7654+
cibp->direct_list = first_pending;
7655+
} else {
7656+
prev_of_explicit->next = first_pending;
7657+
} /* if */
7658+
cibp->first_pending_unresolved_base_init = NULL;
7659+
} /* if */
7660+
} /* move_pending_unresolved_base_inits */
7661+
7662+
76047663
static a_symbol_ptr look_up_mem_initializer_id(void)
76057664
/*
76067665
The current token is a (generalized) identifier of a mem-initializer-id (which
@@ -7967,7 +8026,8 @@ all known yet; it is left unchanged otherwise.
79678026
that only direct and virtual base classes can be specified. */
79688027
bcp = base_classes_of(class_type);
79698028
for (; bcp != NULL; bcp = bcp->next) {
7970-
if (same_entities(bcp->type, init_type)) {
8029+
if (identical_types_full(bcp->type, init_type,
8030+
ITF_EXACT_DECLTYPE_EXPR_MATCH_REQUIRED)) {
79718031
if (bcp->direct || bcp->is_virtual) {
79728032
if (found_bcp == NULL) {
79738033
found_bcp = bcp;
@@ -8036,10 +8096,13 @@ all known yet; it is left unchanged otherwise.
80368096
for (; new_cip != NULL; new_cip = new_cip->next) {
80378097
if (new_cip->variant.base_class == bcp) break;
80388098
} /* for */
8039-
if (new_cip == NULL && prototype_instantiation) {
8040-
new_cip = add_new_unresolved_base_ctor_init(cibp,init_type);
8041-
}
80428099
check_assertion(new_cip != NULL);
8100+
if (!bcp->is_virtual) {
8101+
/* Place pending unresolved base initializers before this matched
8102+
direct-base initializer, following their relative order in the
8103+
ctor-initializer list. */
8104+
move_pending_unresolved_base_inits(cibp, new_cip);
8105+
} /* if */
80438106
/* new_cip was initially marked as compiler-generated. Reset the
80448107
flag now that it's appeared explicitly in the ctor-initializer
80458108
list. */
@@ -9301,6 +9364,7 @@ initialized. These are addressed in the course of the processing.
93019364
cib.pending_decltype_pos = null_source_position;
93029365
cib.has_explicit_init = FALSE;
93039366
cib.out_of_order_diag_issued = FALSE;
9367+
cib.first_pending_unresolved_base_init = NULL;
93049368
cib.pack_expansion_context_started = FALSE;
93059369
if (user_defined && curr_token == tok_colon) {
93069370
/* User-specified initializers are present. */

0 commit comments

Comments
 (0)