diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0e37d4043d0c0ad4c0865afc2865d6a498e6feeb..d450b3d5b78adc9e208fbdacc196b1201247fc7d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7534,6 +7534,7 @@ extern int at_function_scope_p (void); extern bool at_class_scope_p (void); extern bool at_namespace_scope_p (void); extern tree context_for_name_lookup (tree); +extern tree type_context_for_name_lookup (tree); extern tree lookup_conversions (tree); extern tree binfo_from_vbase (tree); extern tree binfo_for_vbase (tree, tree); diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index c5a55dae56393831d2a1a2bd3433361e95110ef7..9571d18170ea8070c7fd7a1e3de12c1fd30bd81e 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -597,7 +597,7 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain) DECL_INSTANTIATING_NSDMI_P (member) = 1; bool pushed = false; - tree ctx = DECL_CONTEXT (member); + tree ctx = type_context_for_name_lookup (member); processing_template_decl_sentinel ptds (/*reset*/false); if (!currently_open_class (ctx)) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index e8efc32f2c26051ce874d88dd7264e0bf58d9dce..a6341b98af21aabc047e3faf59fe22559b7aed6f 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -26439,11 +26439,12 @@ cp_parser_class_specifier (cp_parser* parser) /* Now parse any NSDMIs. */ FOR_EACH_VEC_SAFE_ELT (unparsed_nsdmis, ix, decl) { - if (class_type != DECL_CONTEXT (decl)) + tree ctx = type_context_for_name_lookup (decl); + if (class_type != ctx) { if (pushed_scope) pop_scope (pushed_scope); - class_type = DECL_CONTEXT (decl); + class_type = ctx; pushed_scope = push_scope (class_type); } inject_this_parameter (class_type, TYPE_UNQUALIFIED); diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc index e472a97679dce36ec862a3430551e694655a6fe2..3f521b3bd72fc5eb83cc1c1a15ef2863f5a8c323 100644 --- a/gcc/cp/search.cc +++ b/gcc/cp/search.cc @@ -485,6 +485,25 @@ context_for_name_lookup (tree decl) return context; } +/* Like the above, but always return a type, because it's simpler for member + handling to refer to the anonymous aggr rather than a function. */ + +tree +type_context_for_name_lookup (tree decl) +{ + tree context = DECL_P (decl) ? DECL_CONTEXT (decl) : decl; + gcc_checking_assert (CLASS_TYPE_P (context)); + + while (context && TYPE_P (context) && ANON_AGGR_TYPE_P (context)) + { + tree next = TYPE_CONTEXT (context); + if (!TYPE_P (next)) + break; + context = next; + } + return context; +} + /* Returns true iff DECL is declared in TYPE. */ static bool @@ -881,6 +900,10 @@ accessible_p (tree type, tree decl, bool consider_local_p) else otype = type; + /* Anonymous unions don't have their own access. */ + if (ANON_AGGR_TYPE_P (type)) + type = type_context_for_name_lookup (type); + /* [class.access.base] A member m is accessible when named in class N if diff --git a/gcc/testsuite/g++.dg/lookup/anon8.C b/gcc/testsuite/g++.dg/lookup/anon8.C new file mode 100644 index 0000000000000000000000000000000000000000..80124caba63f89a0227653592dc36721fad313fa --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/anon8.C @@ -0,0 +1,16 @@ +// PR c++/105452 +// { dg-do compile { target c++11 } } + +template <typename T> +struct C { + int i = 42; + union { + T v = i; + static_assert(sizeof(v) == sizeof(char), ""); + }; +}; + +int main() { + C<char> x; + return x.v; +}