Look through DECL_ANON_UNION_VAR_P during reflection-name parsing.

This commit is contained in:
Jakub Jelinek
2026-01-12 11:58:18 +01:00
committed by Marek Polacek
parent 5bc0ec8129
commit 95f5ec013f
5 changed files with 44 additions and 47 deletions

View File

@@ -4183,7 +4183,10 @@ write_reflection (tree refl)
write_type (arg);
else if (strcmp (prefix, "dm") == 0)
{
write_prefix (decl_mangling_context (arg));
tree ctx = decl_mangling_context (arg);
while (ctx && ANON_UNION_TYPE_P (ctx))
ctx = decl_mangling_context (TYPE_NAME (ctx));
write_prefix (ctx);
write_unqualified_name (arg);
}
else if (strcmp (prefix, "un") == 0)

View File

@@ -10052,6 +10052,15 @@ cp_parser_reflection_name (cp_parser *parser)
if (name != error_mark_node && decl == error_mark_node)
cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, loc);
/* If lookup finds a class member of an anonymous union, R represents
that class member. */
if (VAR_P (decl) && DECL_ANON_UNION_VAR_P (decl))
{
tree v = DECL_VALUE_EXPR (decl);
if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)
decl = TREE_OPERAND (v, 1);
}
return decl;
}

View File

@@ -1077,8 +1077,6 @@ eval_is_variable (const_tree r, reflect_kind kind)
if ((TREE_CODE (r) == PARM_DECL && kind != REFLECT_PARM)
|| (VAR_P (r)
&& kind == REFLECT_UNDEF
/* The definition of a variable excludes non-static data members. */
&& !DECL_ANON_UNION_VAR_P (r)
/* A structured binding is not a variable. */
&& !(DECL_DECOMPOSITION_P (r) && !DECL_DECOMP_IS_BASE (r)))
|| (VAR_P (r)
@@ -1299,8 +1297,6 @@ eval_is_class_member (tree r)
}
else if (TYPE_P (r) && typedef_variant_p (r))
r = TYPE_NAME (r);
else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
return boolean_true_node;
if (DECL_P (r) && DECL_CLASS_SCOPE_P (r))
return boolean_true_node;
else if (TYPE_P (r) && TYPE_CLASS_SCOPE_P (r))
@@ -1508,8 +1504,6 @@ eval_is_namespace_member (tree r)
}
else if (TYPE_P (r) && typedef_variant_p (r))
r = TYPE_NAME (r);
else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
return boolean_false_node;
if (r == global_namespace || r == unknown_type_node)
return boolean_false_node;
if (DECL_P (r) && DECL_NAMESPACE_SCOPE_P (r))
@@ -1527,8 +1521,6 @@ eval_is_namespace_member (tree r)
static tree
eval_is_nonstatic_data_member (const_tree r)
{
if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
return boolean_true_node;
if (TREE_CODE (r) == FIELD_DECL && !DECL_UNNAMED_BIT_FIELD (r))
return boolean_true_node;
else
@@ -1635,12 +1627,6 @@ eval_has_automatic_storage_duration (const_tree r, reflect_kind kind)
static tree
eval_is_mutable_member (tree r)
{
if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
{
tree v = DECL_VALUE_EXPR (r);
if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)
r = TREE_OPERAND (v, 1);
}
if (TREE_CODE (r) == FIELD_DECL
&& !DECL_UNNAMED_BIT_FIELD (r)
&& DECL_MUTABLE_P (r))
@@ -2952,14 +2938,6 @@ eval_parent_of (location_t loc, const constexpr_ctx *ctx, tree r,
else
c = CP_TYPE_CONTEXT (r);
}
else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
{
tree v = DECL_VALUE_EXPR (r);
if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)
c = CP_DECL_CONTEXT (TREE_OPERAND (v, 1));
else
c = CP_DECL_CONTEXT (r);
}
else if (kind == REFLECT_BASE)
c = direct_base_parent (r);
else
@@ -6367,14 +6345,6 @@ eval_is_accessible (location_t loc, const constexpr_ctx *ctx, tree r,
else
c = CP_TYPE_CONTEXT (c);
}
else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
{
tree v = DECL_VALUE_EXPR (r);
if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)
c = CP_DECL_CONTEXT (TREE_OPERAND (v, 1));
else
c = CP_DECL_CONTEXT (r);
}
else
c = CP_DECL_CONTEXT (r);
}
@@ -7225,8 +7195,15 @@ can_extract_member_or_function_p (tree T, tree r, reflect_kind kind)
if (eval_is_bit_field (r, kind) == boolean_true_node)
return false;
/* static union { int m; }; extract<int>(^^m); is invalid. */
if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))
if (TREE_CODE (r) == FIELD_DECL
&& ANON_UNION_TYPE_P (DECL_CONTEXT (r)))
{
tree c = CP_TYPE_CONTEXT (DECL_CONTEXT (r));
while (ANON_UNION_TYPE_P (c))
c = CP_TYPE_CONTEXT (c);
if (!TYPE_P (c))
return false;
}
/* Create the X C::* type. */
tree type = build_offset_type (CP_DECL_CONTEXT (r), TREE_TYPE (r));
if (similar_type_p (type, T) && is_convertible (type, T))
@@ -8396,8 +8373,8 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,
foo.[: ^^S::bar :]. */
if (!address_p
&& !member_access_p
&& ((DECL_P (t) && DECL_NONSTATIC_MEMBER_P (t))
|| (VAR_P (t) && DECL_ANON_UNION_VAR_P (t))))
&& DECL_P (t)
&& DECL_NONSTATIC_MEMBER_P (t))
{
if (complain_p)
error_at (loc, "cannot implicitly reference a class member %qD "
@@ -8408,13 +8385,21 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,
splice-expression designating a non-static member m, other than an
explicit object member function, m shall be a direct member of some
class C that is not an anonymous union." */
if (address_p && VAR_P (t) && DECL_ANON_UNION_VAR_P (t))
if (address_p
&& TREE_CODE (t) == FIELD_DECL
&& ANON_UNION_TYPE_P (DECL_CONTEXT (t)))
{
tree c = CP_TYPE_CONTEXT (DECL_CONTEXT (t));
while (ANON_UNION_TYPE_P (c))
c = CP_TYPE_CONTEXT (c);
if (!TYPE_P (c))
{
if (complain_p)
error_at (loc, "unary %<&%> applied to an anonymous union member %qD "
"that is not a direct member of a named class", t);
error_at (loc, "unary %<&%> applied to an anonymous union member "
"%qD that is not a direct member of a named class", t);
return false;
}
}
/* [expr.prim.splice]/2: "The expression is ill-formed if S [the construct
designated by splice-specifier] is

View File

@@ -3,12 +3,12 @@
static union { int m; };
constexpr auto r = ^^m;
auto p = [:r:]; // { dg-error "cannot implicitly reference a class member .m. through a splice" }
auto p = [:r:]; // { dg-error "cannot implicitly reference a class member .<unnamed union>::m. through a splice" }
namespace N {
static union { int mn; };
constexpr auto rn = ^^mn;
auto pn = [:rn:]; // { dg-error "cannot implicitly reference a class member .mn. through a splice" }
auto pn = [:rn:]; // { dg-error "cannot implicitly reference a class member .N::<unnamed union>::mn. through a splice" }
}
struct S {
@@ -25,14 +25,14 @@ f ()
static union {
int x;
};
auto rx = [: ^^x :]; // { dg-error "cannot implicitly reference a class member .x. through a splice" }
auto rx = [: ^^x :]; // { dg-error "cannot implicitly reference a class member .f\\\(\\\)::<unnamed union>::x. through a splice" }
union {
union {
int u;
};
};
auto ru = [: ^^u :]; // { dg-error "cannot implicitly reference a class member .u. through a splice" }
auto ru = [: ^^u :]; // { dg-error "cannot implicitly reference a class member .f\\\(\\\)::<unnamed union>::<unnamed union>::u. through a splice" }
struct L {
union {

View File

@@ -219,9 +219,9 @@ baz (int x)
// { dg-final { scan-assembler "_Z3barILi216ELDmtyN3NS24TClsILi42EEEEEvv" } }
// { dg-final { scan-assembler "_Z3barILi220ELDmdm1S3memEEvv" } }
// { dg-final { scan-assembler "_Z3barILi221ELDmdm3NS21S3memEEvv" } }
// { dg-final { scan-assembler "_Z3barILi222ELDmdm2auEEvv" } }
// { dg-final { scan-assembler "_Z3barILi223ELDmdm3NS21XUt_1aEEvv" } }
// { dg-final { scan-assembler "_Z3barILi224ELDmdm3NS21YIiEUt_1aEEvv" } }
// { dg-final { scan-assembler "_Z3barILi222ELDmdm3NS22auEEvv" } }
// { dg-final { scan-assembler "_Z3barILi223ELDmdm3NS21X1aEEvv" } }
// { dg-final { scan-assembler "_Z3barILi224ELDmdm3NS21YIiE1aEEvv" } }
// { dg-final { scan-assembler "_Z3barILi230ELDmun1S_EEvv" } }
// { dg-final { scan-assembler "_Z3barILi231ELDmun3NS21S_EEvv" } }
// { dg-final { scan-assembler "_Z3barILi232ELDmun3NS21S0_EEvv" } }