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); write_type (arg);
else if (strcmp (prefix, "dm") == 0) 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); write_unqualified_name (arg);
} }
else if (strcmp (prefix, "un") == 0) 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) if (name != error_mark_node && decl == error_mark_node)
cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, loc); 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; 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) if ((TREE_CODE (r) == PARM_DECL && kind != REFLECT_PARM)
|| (VAR_P (r) || (VAR_P (r)
&& kind == REFLECT_UNDEF && 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. */ /* A structured binding is not a variable. */
&& !(DECL_DECOMPOSITION_P (r) && !DECL_DECOMP_IS_BASE (r))) && !(DECL_DECOMPOSITION_P (r) && !DECL_DECOMP_IS_BASE (r)))
|| (VAR_P (r) || (VAR_P (r)
@@ -1299,8 +1297,6 @@ eval_is_class_member (tree r)
} }
else if (TYPE_P (r) && typedef_variant_p (r)) else if (TYPE_P (r) && typedef_variant_p (r))
r = TYPE_NAME (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)) if (DECL_P (r) && DECL_CLASS_SCOPE_P (r))
return boolean_true_node; return boolean_true_node;
else if (TYPE_P (r) && TYPE_CLASS_SCOPE_P (r)) 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)) else if (TYPE_P (r) && typedef_variant_p (r))
r = TYPE_NAME (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) if (r == global_namespace || r == unknown_type_node)
return boolean_false_node; return boolean_false_node;
if (DECL_P (r) && DECL_NAMESPACE_SCOPE_P (r)) if (DECL_P (r) && DECL_NAMESPACE_SCOPE_P (r))
@@ -1527,8 +1521,6 @@ eval_is_namespace_member (tree r)
static tree static tree
eval_is_nonstatic_data_member (const_tree r) 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)) if (TREE_CODE (r) == FIELD_DECL && !DECL_UNNAMED_BIT_FIELD (r))
return boolean_true_node; return boolean_true_node;
else else
@@ -1635,12 +1627,6 @@ eval_has_automatic_storage_duration (const_tree r, reflect_kind kind)
static tree static tree
eval_is_mutable_member (tree r) 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 if (TREE_CODE (r) == FIELD_DECL
&& !DECL_UNNAMED_BIT_FIELD (r) && !DECL_UNNAMED_BIT_FIELD (r)
&& DECL_MUTABLE_P (r)) && DECL_MUTABLE_P (r))
@@ -2952,14 +2938,6 @@ eval_parent_of (location_t loc, const constexpr_ctx *ctx, tree r,
else else
c = CP_TYPE_CONTEXT (r); 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) else if (kind == REFLECT_BASE)
c = direct_base_parent (r); c = direct_base_parent (r);
else else
@@ -6367,14 +6345,6 @@ eval_is_accessible (location_t loc, const constexpr_ctx *ctx, tree r,
else else
c = CP_TYPE_CONTEXT (c); 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 else
c = CP_DECL_CONTEXT (r); 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) if (eval_is_bit_field (r, kind) == boolean_true_node)
return false; return false;
/* static union { int m; }; extract<int>(^^m); is invalid. */ /* 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
return false; && 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. */ /* Create the X C::* type. */
tree type = build_offset_type (CP_DECL_CONTEXT (r), TREE_TYPE (r)); tree type = build_offset_type (CP_DECL_CONTEXT (r), TREE_TYPE (r));
if (similar_type_p (type, T) && is_convertible (type, T)) 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 :]. */ foo.[: ^^S::bar :]. */
if (!address_p if (!address_p
&& !member_access_p && !member_access_p
&& ((DECL_P (t) && DECL_NONSTATIC_MEMBER_P (t)) && DECL_P (t)
|| (VAR_P (t) && DECL_ANON_UNION_VAR_P (t)))) && DECL_NONSTATIC_MEMBER_P (t))
{ {
if (complain_p) if (complain_p)
error_at (loc, "cannot implicitly reference a class member %qD " error_at (loc, "cannot implicitly reference a class member %qD "
@@ -8408,12 +8385,20 @@ check_splice_expr (location_t loc, location_t start_loc, tree t,
splice-expression designating a non-static member m, other than an splice-expression designating a non-static member m, other than an
explicit object member function, m shall be a direct member of some explicit object member function, m shall be a direct member of some
class C that is not an anonymous union." */ 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)))
{ {
if (complain_p) tree c = CP_TYPE_CONTEXT (DECL_CONTEXT (t));
error_at (loc, "unary %<&%> applied to an anonymous union member %qD " while (ANON_UNION_TYPE_P (c))
"that is not a direct member of a named class", t); c = CP_TYPE_CONTEXT (c);
return false; 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);
return false;
}
} }
/* [expr.prim.splice]/2: "The expression is ill-formed if S [the construct /* [expr.prim.splice]/2: "The expression is ill-formed if S [the construct

View File

@@ -3,12 +3,12 @@
static union { int m; }; static union { int m; };
constexpr auto r = ^^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 { namespace N {
static union { int mn; }; static union { int mn; };
constexpr auto rn = ^^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 { struct S {
@@ -25,14 +25,14 @@ f ()
static union { static union {
int x; 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 {
union { union {
int u; 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 { struct L {
union { union {

View File

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