diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index c0872530b10..06bd396c03e 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -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) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index fbb53cb38fb..8e034f21396 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -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; } diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index 329fd77c464..237f630d71b 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -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(^^m); is invalid. */ - if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r)) - return false; + 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,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 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))) { - 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; + 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); + return false; + } } /* [expr.prim.splice]/2: "The expression is ill-formed if S [the construct diff --git a/gcc/testsuite/g++.dg/reflect/anon2.C b/gcc/testsuite/g++.dg/reflect/anon2.C index b69306096d5..cd064247b95 100644 --- a/gcc/testsuite/g++.dg/reflect/anon2.C +++ b/gcc/testsuite/g++.dg/reflect/anon2.C @@ -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 .::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::::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\\\(\\\)::::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\\\(\\\)::::::u. through a splice" } struct L { union { diff --git a/gcc/testsuite/g++.dg/reflect/mangle1.C b/gcc/testsuite/g++.dg/reflect/mangle1.C index a3084c93b84..49947b8b36e 100644 --- a/gcc/testsuite/g++.dg/reflect/mangle1.C +++ b/gcc/testsuite/g++.dg/reflect/mangle1.C @@ -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" } }