diff options
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/init.cc | 2 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 5 | ||||
-rw-r--r-- | gcc/cp/search.cc | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/anon8.C | 16 |
5 files changed, 44 insertions, 3 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0e37d40..d450b3d 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 c5a55da..9571d18 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 e8efc32..a6341b9 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 e472a97..3f521b3 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 0000000..80124ca --- /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; +} |