Commit 096a4865 by Paolo Carlini Committed by Paolo Carlini

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
parent c167bc5b
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> 2013-09-04 Gabriel Dos Reis <gdr@integrable-solutions.net>
* cxx-pretty-print.h (cxx_pretty_printer::simple_type_specifier): * cxx-pretty-print.h (cxx_pretty_printer::simple_type_specifier):
......
...@@ -2773,15 +2773,93 @@ warn_hidden (tree t) ...@@ -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 /* Check for things that are invalid. There are probably plenty of other
things we should check for also. */ things we should check for also. */
static void static void
finish_struct_anon (tree t) finish_struct_anon (tree t)
{ {
tree field; for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
{ {
if (TREE_STATIC (field)) if (TREE_STATIC (field))
continue; continue;
...@@ -2790,53 +2868,7 @@ finish_struct_anon (tree t) ...@@ -2790,53 +2868,7 @@ finish_struct_anon (tree t)
if (DECL_NAME (field) == NULL_TREE if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field))) && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{ finish_struct_anon_r (field, /*complain=*/true);
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);
}
}
} }
} }
......
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> 2013-09-04 David Edelsohn <dje.gcc@gmail.com>
* g++.dg/warn/weak1.C: Skip on AIX. * g++.dg/warn/weak1.C: Skip on AIX.
......
// 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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment