This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] PR c++/26693
Manuel López-Ibáñez a écrit :
Couldn't you abstract out this code and clone_underlying_type into a
function shared by C/C++? They look almost the same to me.
Yes. I just didn't want to be too disruptive at a first shot. But what
you say makes sense. In the attached patch, I have moved
clone_underlying_type to tree.c and I am using it in the c++ front end now.
Also, I have the impression that function name is not really self
explanatory. Maybe something along the lines of
setup_type_decl_for_typedef() would be better ?
Actually, I
don't understand why c-decl.c does not use TYPE_STUB_DECL.
I am not sure either. It kept clone_underlying_type() as it is though
for now. I would appreciate if someone could explain why it does not use it.
[...]
@@ -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);
-
+
Whitespace
Oops. I removed that.
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
Is this patch against trunk? I don't see this testcase in FSF's trunk.
Yes. It's me screwing a bit. This is a new test file. The attached path
makes it clear.
The patch passes regstests on trunk for x86-64.
Thanks.
gcc/ChangeLog
2008-10-30 Dodji Seketeli <dodji@redhat.com>
* c-decl.c: (clone_underlying_type): Move this ...
* tree.c: ... here so that it can be re-used by other front ends.
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:
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/c-decl.c b/gcc/c-decl.c
index eba6161..2226928 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1971,67 +1971,6 @@ warn_if_shadowing (tree new_decl)
}
}
-
-/* Subroutine of pushdecl.
-
- X is a TYPE_DECL for a typedef statement. Create a brand new
- ..._TYPE node (which will be just a variant of the existing
- ..._TYPE node with identical properties) and then install X
- as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
-
- The whole point here is to end up with a situation where each
- and every ..._TYPE node the compiler creates will be uniquely
- associated with AT MOST one node representing a typedef name.
- This way, even though the compiler substitutes corresponding
- ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
- early on, later parts of the compiler can always do the reverse
- translation and get back the corresponding typedef name. For
- example, given:
-
- typedef struct S MY_TYPE;
- MY_TYPE object;
-
- Later parts of the compiler might only know that `object' was of
- type `struct S' if it were not for code just below. With this
- code however, later parts of the compiler see something like:
-
- struct S' == struct S
- typedef struct S' MY_TYPE;
- struct S' object;
-
- And they can then deduce (from the node for type struct S') that
- the original object declaration was:
-
- MY_TYPE object;
-
- Being able to do this is important for proper support of protoize,
- and also for generating precise symbolic debugging information
- which takes full account of the programmer's (typedef) vocabulary.
-
- Obviously, we don't want to generate a duplicate ..._TYPE node if
- the TYPE_DECL node that we are now processing really represents a
- standard built-in type. */
-
-static void
-clone_underlying_type (tree x)
-{
- if (DECL_IS_BUILTIN (x))
- {
- if (TYPE_NAME (TREE_TYPE (x)) == 0)
- TYPE_NAME (TREE_TYPE (x)) = x;
- }
- else if (TREE_TYPE (x) != error_mark_node
- && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
- {
- tree tt = TREE_TYPE (x);
- DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_variant_type_copy (tt);
- TYPE_NAME (tt) = x;
- TREE_USED (tt) = TREE_USED (x);
- TREE_TYPE (x) = tt;
- }
-}
-
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b0b03a5..8a5d1c3 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8680,6 +8680,13 @@ 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. */
+ if (decl_context == FIELD
+ && !uses_template_parms (type))
+ clone_underlying_type (decl);
+
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 +8721,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..c9f5c20 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8924,19 +8924,38 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
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
new file mode 100644
index 0000000..6e71729
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef11.C
@@ -0,0 +1,25 @@
+// Author: Dodji Seketeli <dodji@redhat.com>
+// Origin: PR c++/26693
+// { dg-do compile }
+
+
+class Alpha
+{
+ typedef int X; // { dg-error "'typedef int Alpha::X' is private" }
+};
+
+template<int>
+class Beta
+{
+ typedef int Y; // { dg-error "'typedef int Beta<0>::Y' is private" }
+};
+
+template <int>
+int
+bar ()
+{
+ 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/gcc/tree.c b/gcc/tree.c
index 10b50d1..f60818b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9167,4 +9167,64 @@ build_target_option_node (void)
return t;
}
+/* Setup a TYPE_DECL node as a typedef representation.
+
+ X is a TYPE_DECL for a typedef statement. Create a brand new
+ ..._TYPE node (which will be just a variant of the existing
+ ..._TYPE node with identical properties) and then install X
+ as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
+
+ The whole point here is to end up with a situation where each
+ and every ..._TYPE node the compiler creates will be uniquely
+ associated with AT MOST one node representing a typedef name.
+ This way, even though the compiler substitutes corresponding
+ ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
+ early on, later parts of the compiler can always do the reverse
+ translation and get back the corresponding typedef name. For
+ example, given:
+
+ typedef struct S MY_TYPE;
+ MY_TYPE object;
+
+ Later parts of the compiler might only know that `object' was of
+ type `struct S' if it were not for code just below. With this
+ code however, later parts of the compiler see something like:
+
+ struct S' == struct S
+ typedef struct S' MY_TYPE;
+ struct S' object;
+
+ And they can then deduce (from the node for type struct S') that
+ the original object declaration was:
+
+ MY_TYPE object;
+
+ Being able to do this is important for proper support of protoize,
+ and also for generating precise symbolic debugging information
+ which takes full account of the programmer's (typedef) vocabulary.
+
+ Obviously, we don't want to generate a duplicate ..._TYPE node if
+ the TYPE_DECL node that we are now processing really represents a
+ standard built-in type. */
+
+void
+clone_underlying_type (tree x)
+{
+ if (DECL_IS_BUILTIN (x))
+ {
+ if (TYPE_NAME (TREE_TYPE (x)) == 0)
+ TYPE_NAME (TREE_TYPE (x)) = x;
+ }
+ else if (TREE_TYPE (x) != error_mark_node
+ && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
+ {
+ tree tt = TREE_TYPE (x);
+ DECL_ORIGINAL_TYPE (x) = tt;
+ tt = build_variant_type_copy (tt);
+ TYPE_NAME (tt) = x;
+ TREE_USED (tt) = TREE_USED (x);
+ TREE_TYPE (x) = tt;
+ }
+}
+
#include "gt-tree.h"
diff --git a/gcc/tree.h b/gcc/tree.h
index a85b4c6..2b3b128 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3405,6 +3405,8 @@ struct tree_target_option GTY(())
/* Return a tree node that encapsulates the current target options. */
extern tree build_target_option_node (void);
+extern void clone_underlying_type (tree x);
+
/* Define the overall contents of a tree node.
It may be any of the structures declared above
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