@@ -26097,10 +26097,12 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2609726097 new_con->variant.address.offset -=
2609826098 (a_targ_ptrdiff_t)prev_bcp->offset;
2609926099 if (type_is(tp, tk_void) ||
26100- same_entities(tp, prev_bcp->derived_class)) {
26100+ (same_entities(tp, prev_bcp->derived_class) &&
26101+ prev_bcp->has_public_derivation)) {
2610126102 /* A cast to the most-derived class (either by casting to void*
2610226103 or because the destination type happens to match the most-
26103- derived class type). */
26104+ derived class type, of which the operand is a public base
26105+ class subobject). */
2610426106 remove_trailing_subobject_path_entry(new_con);
2610526107 clear_runtime_constant_address(result_storage, new_con);
2610626108 goto done;
@@ -26113,7 +26115,21 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2611326115 bcdp = bcdp->next;
2611426116 for (; dsp != tail->next; dsp = dsp->next) {
2611526117 if (same_entities(dsp->base_class->type, tp)) {
26116- if (new_bcp == NULL) {
26118+ a_derivation_step_ptr step;
26119+ a_boolean is_public_base = TRUE;
26120+ /* The operand must be a public base class subobject of the
26121+ destination subobject. */
26122+ for (step = dsp->next; step != tail->next;
26123+ step = step->next) {
26124+ if (!step->base_class->has_public_derivation) {
26125+ is_public_base = FALSE;
26126+ } /* if */
26127+ } /* for */
26128+ if (!is_public_base) {
26129+ /* Move on to the final strategy (which will fail too). */
26130+ new_bcp = NULL;
26131+ bcdp = NULL;
26132+ } else if (new_bcp == NULL) {
2611726133 new_bcp = dsp->base_class;
2611826134 } else if (dsp->base_class != new_bcp) {
2611926135 /* The subobject on the derivation path is not unambiguous.
@@ -26139,7 +26155,11 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2613926155 &expr->position, new_bcp->type, ips);
2614026156 } /* if */
2614126157 goto done;
26142- } else if (!is_accessible_base_class(new_bcp)) {
26158+ } else if (!prev_bcp->has_public_derivation ||
26159+ !new_bcp->has_public_derivation) {
26160+ /* The operand must be a public base class subobject of the
26161+ most-derived object, and the destination a public base
26162+ class of the most-derived type. */
2614326163 if (pointer_case) {
2614426164 clear_address(result_storage, NULL);
2614526165 } else {
@@ -26189,6 +26209,7 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2618926209 a_base_class_ptr bcp, baseward_bcp;
2619026210 a_type_ptr dtp;
2619126211 a_byte *subobj = opnd_addr->address;
26212+ a_boolean is_public_base = TRUE;
2619226213 /* Check for the null address case first. */
2619326214 if (subobj == NULL) {
2619426215 /* Casting a null pointer value results in a null pointer value. */
@@ -26205,8 +26226,8 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2620526226 do_constexpr_fail(result);
2620626227 goto done;
2620726228 } /* if */
26208- if (type_is(tp, tk_void) &&
26209- (baseward_bcp = find_base_in_type(opnd_type, tp))!= NULL) {
26229+ if (! type_is(tp, tk_void) &&
26230+ (baseward_bcp = find_base_in_type(opnd_type, tp)) != NULL) {
2621026231 /* The dynamic cast is actually a (static) derived-to-base cast. */
2621126232 if (baseward_bcp->ambiguous) {
2621226233 do_constexpr_fail(result);
@@ -26230,13 +26251,17 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2623026251 a_byte_count offset;
2623126252 get_mapped_byte_count(&persistent_map, bcp, offset);
2623226253 result_addr->address -= offset;
26254+ if (!bcp->has_public_derivation) is_public_base = FALSE;
2623326255 dtp = bcp->derived_class;
2623426256 if (same_entities(dtp, tp)) {
2623526257 /* We found a derived subobject of the right type. Since types with
2623626258 virtual bases cannot be literal types (and thus cannot be stored
2623726259 in interpreter memory), there is no concern about this being
26238- ambiguous. */
26239- goto done;
26260+ ambiguous. The cast succeeds only if the operand is a public base
26261+ class subobject of it; otherwise, it also is not a public base
26262+ class subobject of the most-derived object, and so the cast fails
26263+ below. */
26264+ if (is_public_base) goto done;
2624026265 } /* if */
2624126266 if (is_initialized(result_addr)) {
2624226267 bcp = *(a_base_class_ptr*)result_addr->address;
@@ -26253,11 +26278,13 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2625326278 goto done;
2625426279 } /* if */
2625526280 /* We've reached the most derived type (dtp) without encountering the
26256- destination type. This might still be a "sideways" cast. */
26281+ destination type as a class of which the operand is a public base
26282+ class subobject. This might still be a "sideways" cast. */
2625726283 baseward_bcp = find_base_in_type(dtp, tp);
2625826284 if (baseward_bcp != NULL) {
2625926285 /* There is a subobject of the right kind: Verify that it is
26260- unambiguous and accessible. */
26286+ unambiguous and that it and the operand are public base class
26287+ subobjects of the most-derived object. */
2626126288 if (baseward_bcp->ambiguous) {
2626226289 if (pointer_case) {
2626326290 clear_address(result_storage, NULL);
@@ -26267,7 +26294,7 @@ represented by an entry of type a_constant (ck_address or ck_integer).
2626726294 &expr->position, tp, ips);
2626826295 } /* if */
2626926296 goto done;
26270- } else if (!is_accessible_base_class( baseward_bcp) ) {
26297+ } else if (!is_public_base || ! baseward_bcp->has_public_derivation ) {
2627126298 if (pointer_case) {
2627226299 clear_address(result_storage, NULL);
2627326300 } else {
0 commit comments