diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2013-09-04 23:52:48 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2013-09-04 23:52:48 +0000 |
commit | 096a48656c7734c99f029b3c0e26c545b8644ec7 (patch) | |
tree | 570076f0b7a08c8f4adb498a312cf967f8a21b35 | |
parent | c167bc5b7d51a6d582324040201106fab36723da (diff) | |
download | gcc-096a48656c7734c99f029b3c0e26c545b8644ec7.zip gcc-096a48656c7734c99f029b3c0e26c545b8644ec7.tar.gz gcc-096a48656c7734c99f029b3c0e26c545b8644ec7.tar.bz2 |
re PR c++/24926 (gcc ignores access level violation for anonymous structs)
/cp
2013-09-04 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/24926
* class.c (finish_struct_anon_r): New.
(finish_struct_anon): Use it.
/testsuite
2013-09-04 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/24926
* g++.dg/parse/access11.C: New.
From-SVN: r202266
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/class.c | 132 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/access11.C | 35 |
4 files changed, 128 insertions, 50 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index db4cd66..be8258d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2013-09-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/24926 + * class.c (finish_struct_anon_r): New. + (finish_struct_anon): Use it. + 2013-09-04 Gabriel Dos Reis <gdr@integrable-solutions.net> * cxx-pretty-print.h (cxx_pretty_printer::simple_type_specifier): diff --git a/gcc/cp/class.c b/gcc/cp/class.c index bcd8076..3d34b92 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2773,15 +2773,93 @@ warn_hidden (tree t) } } +/* Recursive helper for finish_struct_anon. */ + +static void +finish_struct_anon_r (tree field, bool complain) +{ + bool is_union = TREE_CODE (TREE_TYPE (field)) == UNION_TYPE; + tree elt = TYPE_FIELDS (TREE_TYPE (field)); + for (; elt; elt = DECL_CHAIN (elt)) + { + /* We're generally only interested in entities the user + declared, but we also find nested classes by noticing + the TYPE_DECL that we create implicitly. You're + allowed to put one anonymous union inside another, + though, so we explicitly tolerate that. We use + TYPE_ANONYMOUS_P rather than ANON_AGGR_TYPE_P so that + we also allow unnamed types used for defining fields. */ + if (DECL_ARTIFICIAL (elt) + && (!DECL_IMPLICIT_TYPEDEF_P (elt) + || TYPE_ANONYMOUS_P (TREE_TYPE (elt)))) + continue; + + if (TREE_CODE (elt) != FIELD_DECL) + { + if (complain) + { + if (is_union) + permerror (input_location, + "%q+#D invalid; an anonymous union can " + "only have non-static data members", elt); + else + permerror (input_location, + "%q+#D invalid; an anonymous struct can " + "only have non-static data members", elt); + } + continue; + } + + if (complain) + { + if (TREE_PRIVATE (elt)) + { + if (is_union) + permerror (input_location, + "private member %q+#D in anonymous union", elt); + else + permerror (input_location, + "private member %q+#D in anonymous struct", elt); + } + else if (TREE_PROTECTED (elt)) + { + if (is_union) + permerror (input_location, + "protected member %q+#D in anonymous union", elt); + else + permerror (input_location, + "protected member %q+#D in anonymous struct", elt); + } + } + + TREE_PRIVATE (elt) = TREE_PRIVATE (field); + TREE_PROTECTED (elt) = TREE_PROTECTED (field); + + /* Recurse into the anonymous aggregates to handle correctly + access control (c++/24926): + + class A { + union { + union { + int i; + }; + }; + }; + + int j=A().i; */ + if (DECL_NAME (elt) == NULL_TREE + && ANON_AGGR_TYPE_P (TREE_TYPE (elt))) + finish_struct_anon_r (elt, /*complain=*/false); + } +} + /* Check for things that are invalid. There are probably plenty of other things we should check for also. */ static void finish_struct_anon (tree t) { - tree field; - - for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) + for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) { if (TREE_STATIC (field)) continue; @@ -2790,53 +2868,7 @@ finish_struct_anon (tree t) if (DECL_NAME (field) == NULL_TREE && ANON_AGGR_TYPE_P (TREE_TYPE (field))) - { - bool is_union = TREE_CODE (TREE_TYPE (field)) == UNION_TYPE; - tree elt = TYPE_FIELDS (TREE_TYPE (field)); - for (; elt; elt = DECL_CHAIN (elt)) - { - /* We're generally only interested in entities the user - declared, but we also find nested classes by noticing - the TYPE_DECL that we create implicitly. You're - allowed to put one anonymous union inside another, - though, so we explicitly tolerate that. We use - TYPE_ANONYMOUS_P rather than ANON_AGGR_TYPE_P so that - we also allow unnamed types used for defining fields. */ - if (DECL_ARTIFICIAL (elt) - && (!DECL_IMPLICIT_TYPEDEF_P (elt) - || TYPE_ANONYMOUS_P (TREE_TYPE (elt)))) - continue; - - if (TREE_CODE (elt) != FIELD_DECL) - { - if (is_union) - permerror (input_location, "%q+#D invalid; an anonymous union can " - "only have non-static data members", elt); - else - permerror (input_location, "%q+#D invalid; an anonymous struct can " - "only have non-static data members", elt); - continue; - } - - if (TREE_PRIVATE (elt)) - { - if (is_union) - permerror (input_location, "private member %q+#D in anonymous union", elt); - else - permerror (input_location, "private member %q+#D in anonymous struct", elt); - } - else if (TREE_PROTECTED (elt)) - { - if (is_union) - permerror (input_location, "protected member %q+#D in anonymous union", elt); - else - permerror (input_location, "protected member %q+#D in anonymous struct", elt); - } - - TREE_PRIVATE (elt) = TREE_PRIVATE (field); - TREE_PROTECTED (elt) = TREE_PROTECTED (field); - } - } + finish_struct_anon_r (field, /*complain=*/true); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8faee5a..176d997 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-09-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/24926 + * g++.dg/parse/access11.C: New. + 2013-09-04 David Edelsohn <dje.gcc@gmail.com> * g++.dg/warn/weak1.C: Skip on AIX. diff --git a/gcc/testsuite/g++.dg/parse/access11.C b/gcc/testsuite/g++.dg/parse/access11.C new file mode 100644 index 0000000..7004fa7 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/access11.C @@ -0,0 +1,35 @@ +// PR c++/24926 + +class A { + union { + int i; // { dg-error "private" } + }; + union { + int j; // { dg-error "private" } + }; + union { + union { + int k; // { dg-error "private" } + }; + union { + union { + int l; // { dg-error "private" } + }; + union { + int m; // { dg-error "private" } + union { + int n; // { dg-error "private" } + int o; // { dg-error "private" } + }; + }; + }; + }; +}; + +int a1 = A().i; // { dg-error "context" } +int a2 = A().j; // { dg-error "context" } +int a3 = A().k; // { dg-error "context" } +int a4 = A().l; // { dg-error "context" } +int a5 = A().m; // { dg-error "context" } +int a6 = A().n; // { dg-error "context" } +int a7 = A().o; // { dg-error "context" } |