This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR c++/26693
- From: Dodji Seketeli <dodji at redhat dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Cc: Jason Merrill <jason at redhat dot com>
- Date: Wed, 29 Oct 2008 23:07:43 +0100
- Subject: [PATCH] PR c++/26693
Hello,
This patch tries to fix PR c++/26693.
Please read the bug analysis in the comments attached to the PR at
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26693.
This patch also touches libstdc++ as fixing the PR in g++ revealed a
typedef name private to a class name being used outside of the class.
If you think I should make a separate patch for libstdc++, please let me
know.
The patch passes regtest for trunk on x86-64. I am about to try an apply
it and regtest it on 4.3 as well.
Thanks.
Dodji.
gcc/cp/ChangeLog:
2008-10-29 Dodji Seketeli <dodji@redhat.com>
PR c++/26693
* decl.c (grokdeclarator): when a typedef appears in a
class, make sure to create the typedef variant type node
for it. If the typedef'ed struct/class was anonymous, set
the proper type name to all its type variants.
* pt.c (tsubst): if we are accessing a type that is a typedef name
defined in a class, make sure the typedef name is accessible.
gcc/testsuite/ChangeLog:
2008-10-29 Dodji Seketeli <dodji@redhat.com>
PR c++/26693
* g++.dg/template/typedef11.C: New test.
libstdc++-v3/ChangeLog:
@@ -1,3 +1,9 @@
2008-10-29 Dodji Seketeli <dodji@redhat.com>
* include/ext/bitmap_allocator.h: the typedefs should be made public
if we want them to be accessible. This has been revealed by the patch
that fixes PR c++/26693 in g++.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b0b03a5..cde9241 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8680,6 +8680,33 @@ grokdeclarator (const cp_declarator *declarator,
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
decl = build_decl (TYPE_DECL, unqualified_id, type);
+
+ /* When a typedef statement appears in a class/struct, make sure a
+ 'typedef variant type' node is associated to that typedef statement.
+ This will help to later be able to check the access of the typedef name.
+ Please read the comment of the function clone_underlying_type in
+ c-decl.c to learn more about how to represent the type of
+ a typedef statement. */
+ if (decl_context == FIELD
+ && !uses_template_parms (type))
+ {
+ if (DECL_IS_BUILTIN (decl))
+ {
+ if (TYPE_NAME (type) == 0)
+ TYPE_NAME (type) = decl;
+ }
+ else
+ {
+ DECL_ORIGINAL_TYPE (decl) = type;
+ type = build_variant_type_copy (type);
+ TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (decl));
+ TYPE_NAME (type) = decl;
+ TREE_TYPE (decl) = type;
+ }
+ }
+
+
if (id_declarator && declarator->u.id.qualifying_scope) {
error ("%Jtypedef name may not be a nested-name-specifier", decl);
TREE_TYPE (decl) = error_mark_node;
@@ -8714,12 +8741,11 @@ grokdeclarator (const cp_declarator *declarator,
&& TYPE_ANONYMOUS_P (type)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
- tree oldname = TYPE_NAME (type);
tree t;
/* Replace the anonymous name with the real name everywhere. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (TYPE_NAME (t) == oldname)
+ if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 13a2361..75dd215 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8921,22 +8921,41 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
&& TYPE_NAME (t) != TYPE_MAIN_DECL (t))
{
tree decl = TYPE_NAME (t);
-
+
if (DECL_CLASS_SCOPE_P (decl)
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
- && uses_template_parms (DECL_CONTEXT (decl)))
+ && uses_template_parms (DECL_CONTEXT (decl))
+ && uses_template_parms (decl))
{
tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
r = retrieve_specialization (tmpl, gen_args, false);
+ if (r && !enforce_access (TYPE_BINFO (DECL_CONTEXT (r)), r, r))
+ return error_mark_node;
}
else if (DECL_FUNCTION_SCOPE_P (decl)
&& DECL_TEMPLATE_INFO (DECL_CONTEXT (decl))
&& uses_template_parms (DECL_TI_ARGS (DECL_CONTEXT (decl))))
r = retrieve_local_specialization (decl);
else
- /* The typedef is from a non-template context. */
- return t;
+ {
+ /* The typedef is from a non-template context. */
+
+ if (DECL_CONTEXT (decl)
+ && AGGREGATE_TYPE_P (DECL_CONTEXT (decl))
+ && !uses_template_parms (DECL_CONTEXT (decl)))
+ {
+ /* t has been lowered from a typedef'ed type (namely decl) that is
+ a member of a class/struct. E.g:
+ class Foo {
+ typedef t X;
+ };
+ In that example, we need to make sure X is accessible from here. */
+ if (!enforce_access (TYPE_BINFO (DECL_CONTEXT (decl)), decl, decl))
+ return error_mark_node;
+ }
+ return t;
+ }
if (r)
{
diff --git a/gcc/testsuite/g++.dg/template/typedef11.C b/gcc/testsuite/g++.dg/template/typedef11.C
index db7a1d3..6e71729 100644
--- a/gcc/testsuite/g++.dg/template/typedef11.C
+++ b/gcc/testsuite/g++.dg/template/typedef11.C
@@ -2,16 +2,24 @@
// Origin: PR c++/26693
// { dg-do compile }
-class Foo
+
+class Alpha
+{
+ typedef int X; // { dg-error "'typedef int Alpha::X' is private" }
+};
+
+template<int>
+class Beta
{
- typedef int X; // { dg-error "'typedef int Foo::X' is private" }
+ typedef int Y; // { dg-error "'typedef int Beta<0>::Y' is private" }
};
template <int>
int
bar ()
{
- return Foo::X (); // { dg-error "within this context" }
+ Beta<0>::Y i = 0; // { dg-error "within this context" }
+ return Alpha::X (); // { dg-error "within this context" }
}
int i = bar<0> ();
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index 7f5466a..7768bd2 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -549,11 +549,13 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
*/
class free_list
{
+ public:
typedef size_t* value_type;
typedef __detail::__mini_vector<value_type> vector_type;
typedef vector_type::iterator iterator;
typedef __mutex __mutex_type;
+ private:
struct _LT_pointer_compare
{
bool